Java Design Patterns Interview Questions PDF By ScholarHat
1.
Top 50 JavaDesign Patterns Interview Questions and Answers
Java Design Patterns
Java Design Patterns are useful in software development because they provide tested answers to common problems. They support developer
that is easier to maintain, understand, and expand.
In this Design Pattern tutorial, I'll cover the top 50 Java Design Patterns interview questions and answers in which we will cover three categor
intermediate, and experienced. Here, we will try to cover all important aspects of design patterns and their types.
Top 20 Java Design Patterns Interview Questions and Answers For Beginners
1. What is a design pattern in Java?
A design pattern is a reusable solution to common issues in software design.
It gives a proven framework for addressing specific issues and can assist developers in writing efficient and maintainable code.
There are three types of design patterns that are:
Creational Design Pattern
Structural Design Pattern
Behavioral Design Pattern
2.
4. What isthe Observer Design Pattern?
The Observer pattern allows items to communicate with each other.It's similar to telling others about something and everyone knowing what's g
when multiple objects need to be notified when something occurs to one object.
2. Explain the Singleton Design Pattern?
The Singleton Design Pattern is a design pattern that ensures a class has only one instance and provides a global point of access to that instan
exactly one object is needed to coordinate actions across the system.
Single Instance: Ensures only one instance of the class exists.
Global Access: Provides a global point of access via a static method.
Private Constructor: The Constructor is private to prevent direct instantiation.
Lazy Initialization: The instance is created only when first needed (in some implementations).
Thread Safety: Requires handling concurrency to ensure a single instance in multithreaded environments.
5. Can you describe the Decorator Design Pattern?
The Decorator pattern allows you to add new features to an object while keeping its appearance and functionality intact. You create a new class t
the existing object and adds new functionality to it. To apply the Decorator Pattern, we have to:
3. When would you use the Factory Design Pattern?
It is the most often used design pattern in Java.
These design patterns fall under the Creational Pattern, which provides one of the finest ways to construct an object.
In the Factory pattern, we do not expose the creation logic to the client. Instead, we refer to the generated object using a standard interface.
The Factory Pattern allows sub-classes to select the sort of object to produce.
The Factory Pattern is often referred to as Virtual Constructor.
To apply the Observer Pattern, we have to:
Define an interface for Observer objects that specifies which method(s) will be invoked when the monitored object's state changes.
Create an interface for the Subject (observed) object that allows Observer objects to register, remove, and be notified about changes.
Create concrete Observer classes that implement the Observer interface and have their implementation of the Update method.
Create a concrete Subject class that implements the Subject interface and stores a list of registered Observer objects.
This class also includes methods for changing the state of an object, which sends alerts to all registered Observers.
3.
The Chain ofResponsibility Pattern is a behavioral design pattern in which an object delegates a request along a chain of potential handle
overview:
The Prototype Design Pattern is a creational design pattern that allows objects to be duplicated or cloned rather than developed from the start, m
a replica of an existing item. It is used to efficiently construct duplicate objects while avoiding the overhead associated with initializing new instan
To apply the Prototype Pattern, we have to:
Define a prototype interface that declares a method for cloning itself.
Create concrete prototype classes that implement the prototype interface and define how they should be cloned.
Define a client class that uses the prototype objects to create new instances by cloning existing ones.
Ensure that the cloning process is efficient and accurately replicates the original object's state.
The Template Method pattern is a design pattern that allows you to create a list of steps to complete a task, but some of the stages can be com
ways. You begin by creating a basic list of steps, and then you create a primary step that instructs the other phases to execute. Each stage can b
all work together to accomplish the desired result.
To apply the Template Pattern, we have to:
Create an abstract base class that includes a template function. The template method should invoke additional methods (abstract or conc
specified algorithmic processes.
Define abstract methods in the base class to represent the steps that subclasses must complete.
Create concrete subclasses that implement the abstract methods to give step-specific implementations.
Client code can generate a concrete subclass instance and perform the algorithm using the template method.
Create an interface or abstract class that specifies the methods that both the original object and the decorator must implement.
Create a concrete class that implements the interface or abstract class while representing the actual item.
Create a decorator class that implements the same interface or abstract class and includes an instance of the original object.
Apply the interface or abstract class's methods in the decorator class by calling the right methods on the original object instance and adding n
The Strategy Design Pattern is a type of behavioral design that defines a set of algorithms, encapsulates them, and allows them to be used i
enables a client to select an algorithm from a family of algorithms at runtime, increasing flexibility and allowing the algorithm to change independ
that utilizes it.
To apply the Strategy Pattern, we have to:
Define a strategy interface that specifies the method(s) for the algorithm.
Create concrete strategy classes that implement this interface with specific algorithm details.
Define a context class that holds a reference to a strategy object and invokes the algorithm through the strategy interface.
Allow the context class to change the strategy object at runtime, providing the flexibility to use different algorithms as needed.
The Adapter pattern allows diverse items to operate together, even if they were not designed to do so. It transforms one item into another,
collaborate. This is useful when two things are incompatible but must coexist.
To apply the adapter pattern, we have to:
Identify the interface that the client intends to utilize.
Identify the current interface that has to be modified to meet the goal interface.
Construct an Adapter class that defines the target interface and includes an instance of the current interface.
Create the target interface's methods in the Adapter class by calling the appropriate methods on the existing interface instance.
6. Explain the Adapter Design Pattern.
7. What is the Strategy Design Pattern?
8. What is the Template Method Pattern?
9. How does the Prototype Design Pattern work?
10. Describe the Chain of Responsibility Pattern.
4.
Usage
Example
Definition
This pattern uncouplesthe sender of a request from its receivers by giving a chain of objects to process it.
Each handler in the chain decides either to process the request or to pass it down the chain.
Think of a customer support service in which requests can be of different kinds, say a problem related to billing, technical issues, or just gene
A request for support comes in and is passed along the chain of departments until the appropriate one is capable of processing it.
This design pattern makes the system more flexible and dynamic, where new handlers can be easily added without changing existing code.
To apply the Command Pattern, we're going to have to:
Create a Command interface or abstract class to define the execute method.
Create concrete classes that use the Command interface to represent various commands. These classes should contain a reference to the re
will carry out the command.
Create an invoker class that will run the instructions by calling their execute function.
Client code should construct and pass concrete Command instances to the invoker class.
When you want to allow multiple objects to handle a request and pass the request along a chain of handlers.
It is especially useful in cases where an exact handler is not known a priori and when different handlers need to be included based on either t
or conditions.
The Facade Design Pattern is a kind of Structural Design Pattern that provides a simplified interface to a complex subsystem, allowing it to
mostly comprises the creation of a single class called the "facade," which provides an instance through which all the set of interfaces from the su
The Flyweight Design Pattern is a structural design pattern that reduces memory usage by sharing common elements of things. It is especial
working with a large number of things that have many similarities but differ in a few ways. Sharing common data and creating lightweight objects
overhead of memory consumption and improve performance.
To apply the Flyweight Pattern, we have to:
Define a Flyweight interface that declares methods for interacting with shared and intrinsic data.
Create concrete Flyweight classes that implement the Flyweight interface and manage the shared (extrinsic) data.
Define a Flyweight Factory that maintains a pool of existing Flyweight objects and provides a method to retrieve or create them.
Ensure that clients use the Flyweight Factory to get Flyweight instances, passing only the extrinsic data to manage the variations in state.
The Command pattern is a method for organizing and controlling requests in a computer program.Instead of delivering direct instructions
execute our requests using objects known as commands.
This allows us to utilize various requests for different clients, maintain track of prior requests, and undo earlier operations.
We describe how commands should be executed using an interface or class, and then we design different classes to represent different types of
13. What is the Facade Design Pattern?
12. Explain the Flyweight Design Pattern.
11. What is the Command Design Pattern?
5.
The use-cases ofComposite design pattern:
When we want to show a partial or complete hierarchy of items.
If we need to add responsibilities dynamically to a particular object without affecting other objects.
The Adapter design aims to make interfaces of one or more classes look comparable.
The Bridge pattern is intended to separate a class's interface from its implementation, allowing us to alter or replace the way it is imp
changing the client code.
The Bridge Design Pattern lies within structural design patterns. It decouples the abstraction from the implementation and thus allows
independently. It is an abstraction layer through which you can vary the abstraction part and the implementation part independently.
To apply the Bridge Pattern, we have to:
Define an abstraction class that contains a reference to an implementation interface and provides methods for interacting with it.
Create an implementation interface that declares methods for the concrete implementations to define.
Create concrete implementations that implement the implementation interface and provide specific functionality.
Implement concrete abstractions that extend the abstraction class, and delegate calls to the implementation interface, allowing the a
different implementations.
The Mediator Design Pattern manages complex communications and controls interactions among objects in a system. It centralizes comm
objects, thereby not letting them tighten the coupling and reducing dependencies. Here's how it works:
1. Central Mediator: It defines an interface for communication between objects. Objects do not communicate with each other directly; ra
through the mediator.
2. Colleagues: These are the objects that wish to communicate. They direct their requests to the mediator instead of addressing them directly to
3. Decoupling: The usage of the mediator helps to decouple objects from each other, which leads to less maintenance and a certain degree of fl
accessed. Then, the complex details of the subsystem are hidden from the client.
To apply the Facade Pattern, we have to:
Define a Facade class that presents a simple, unified interface to the subsystem.
Encapsulate the complexity of the subsystem by including references to the subsystem classes within the Facade.
Implement methods in the Facade class, which calls upon the corresponding subsystem classes to execute the client's requests.
The Facade class is meant to interact with the subsystem so that it simplifies the interaction of the client and decreases dependency on th
subsystem.
The Composite Design Pattern is a Structural Design Pattern that allows objects to be composed in tree-like structures to represent part-whol
client should be able to treat both individual objects and compositions of objects uniformly, which will make it easy for clients to use these
structures.
To apply the Composite Pattern, we have to:
Define a component interface that declares common methods for leaf and composite objects.
Create leaf classes that implement the component interface and represent the basic elements of the structure.
Create composite classes that implement the component interface and contain a collection of child components (both leaf and other compo
Implement methods in the composite classes to manage child components, allowing clients to treat both individual objects and composition
14. Describe the Bridge Design Pattern.
15. What is the Composite Design Pattern?
16. How does the Mediator Design Pattern work?
18. Describe the uses of the Composite Design Pattern.
17. How is the Bridge pattern different from the Adapter pattern?
19. What are Some Design Patterns used in the JDK library?
6.
The JDK libraryincorporates some of the following design patterns:
Wrapper classes employ the decorator pattern.
Calendar classes (runtime) employ the singleton pattern.
Wrapper classes, like Integer, use a factory pattern.valueOf.
Swing and Abstract Window Toolkit (AWT) are examples of event-handling frameworks that use the observer approach.
This design pattern can be complex, requiring a lot of memory and time. As a result, it is critical to exercise caution when using it.
This Pattern is ineffective when the Object's intrinsic attributes are huge. It can increase the complexity of the process.
1. Encapsulation of Object Creation: It centralizes object creation logic in a factory, making it easy to change, extend, or replace without altering
2. Loose Coupling: Clients depend on abstractions (interfaces or base classes) rather than specific implementations, enabling eas
implementations.
3. Scalability: New types of objects can be introduced by modifying the factory, without modifying existing code, promoting easy extension.
While it serves some purposes well, there are several drawbacks of the Singleton pattern:
Hidden Dependencies: This creates a global instance that all parts of the code must rely on, making dependencies less obvious and theref
code becomes harder.
Testing Problems: Singletons can be hard to mock or isolate in unit tests; this often leads to less effective and more coupled test cases.
Concurrency Issues: The Singleton instance must be carefully synchronized in multi-threaded environments to make sure there is no multip
bottleneck in performance.
Nonflexibility: It enforces a single instance, which can be problematic if the application needs to handle multiple instances or adapt t
requirements.
21. What are the drawbacks of using the Singleton pattern?
22. How does the Factory Design Pattern improve code flexibility?
20. What are the essential points to keep in mind for the Flyweight Design Pattern?
Top 15 Java Design Patterns Interview Questions and Answers For Intermediate
Example
// Vehicle Interface (Product)
interface Vehicle {
}
void drive();
// Concrete implementation: Car
class Car implements Vehicle {
}
@Override
public void drive() {
System.out.println("Driving a car.");
}
// Concrete implementation: Bike
class Bike implements Vehicle {
}
@Override
public void drive() {
System.out.println("Riding a bike.");
}
// Factory class to create vehicles
class VehicleFactory {
// Factory method to create vehicle instances based on type
7.
Output
Example
Explanation
Try it Yourself>>
In this example,
Vehicle Interface: Represents a generic vehicle.
Car and Bike: Concrete implementations of the Vehicle interface.
VehicleFactory: Contains the logic to instantiate and return objects based on input (Car or Bike).
Main Class: Demonstrates how to use the factory to create different vehicle objects.
The Observer Design Pattern can be applied in various real-world scenarios where one object (the subject) needs to notify other objects (observ
its state without tightly coupling them. Below is a common real-world application:
Weather Monitoring System: A weather station (subject) needs to notify multiple devices (observers) like displays and apps whenever the tempe
23. How can the Observer Design Pattern be applied in a real-world scenario?
Driving a car.
Riding a bike.
import java.util.ArrayList;
import java.util.List;
// Observer Interface
interface Observer {
void update(float temperature);
// Client code
public class Main {
public static void main(String[] args) {
// Create a Car using the factory
Vehicle myCar = VehicleFactory.createVehicle("Car");
myCar.drive(); // Output: Driving a car.
}
// Create a Bike using the factory
Vehicle myBike = VehicleFactory.createVehicle("Bike");
myBike.drive(); // Output: Riding a bike.
}
}
public static Vehicle createVehicle(String vehicleType) {
if (vehicleType.equalsIgnoreCase("Car")) {
return new Car();
} else if (vehicleType.equalsIgnoreCase("Bike")) {
return new Bike();
} else {
throw new IllegalArgumentException("Invalid vehicle type.");
}
}
8.
}
public DisplayDevice(String name){
this.name = name;
}
// Concrete Observer: Display Device
class DisplayDevice implements Observer {
private String name;
}
private void notifyObservers() {
for (Observer observer : observers) {
observer.update(temperature);
}
}
public void addObserver(Observer observer) {
observers.add(observer);
}
public void removeObserver(Observer observer) {
observers.remove(observer);
}
public void setTemperature(float temperature) {
this.temperature = temperature;
notifyObservers();
}
// Subject (Weather Station)
class WeatherStation {
private List<Observer> observers = new ArrayList<>();
private float temperature;
// Creating and adding observers Observer display1 = new
DisplayDevice("Front Room"); Observer display2 = new
DisplayDevice("Back Room");
weatherStation.addObserver(display1);
weatherStation.addObserver(display2);
// Main class
public class Main {
public static void main(String[] args) {
WeatherStation weatherStation = new WeatherStation();
// Change in temperature
weatherStation.setTemperature(25.5f); // All displays will be notified
}
@Override
public void update(float temperature) {
System.out.println(name + " display: Current temperature is " + temperature + "°C");
}
9.
Output
Example
Explanation
Try it Yourself>>
In this example,
WeatherStation: Subject that maintains a list of observers and notifies them of temperature changes.
DisplayDevice: Concrete observer that updates its display based on the temperature.
Main: Demonstrates adding observers and updating the temperature, showing how all observers are notified.
The role of the template method design pattern are:
Define Algorithm: Provides a skeleton for an algorithm in a base class.
Allow Extensions: Subclasses implement specific steps of the algorithm, allowing customization.
Promote Reuse: Reuses the common algorithm structure while allowing subclasses to vary specific parts.
Control Flow: Ensures the algorithm’s structure is consistent while enabling variations in the implementation details.
We have a base class,CoffeeTemplate,that outlines the steps to make coffee, with some steps implemented in a concrete subclass.
24. What is the role of the Template Method Design Pattern?
}
}
// Abstract class with template method
abstract class CoffeeTemplate {
// Concrete subclass for making Coffee
// Template method defining the algorithm
public final void makeCoffee() {
boilWater();
brewCoffeeGrinds();
pourInCup();
addCondiments();
}
// Steps that subclasses can implement
protected abstract void brewCoffeeGrinds();
protected abstract void addCondiments();
// Common steps implemented in the base class
private void boilWater() {
System.out.println("Boiling water.");
}
Front Room display: Current temperature is 25.5°C
Back Room display: Current temperature is 25.5°C
}
private void pourInCup() {
System.out.println("Pouring coffee into cup.");
}
10.
Output
Explanation
In this example,
Tryit Yourself >>
Boiling water.
Dripping coffee through filter.
Pouring coffee into cup.
Adding sugar and milk.
Boiling water.
Steeping the tea.
Pouring coffee into cup.
Adding lemon.
// Concrete subclass for making Tea
class Tea extends CoffeeTemplate {
class Coffee extends CoffeeTemplate {
}
@Override
protected void addCondiments() {
System.out.println("Adding lemon.");
}
@Override
protected void brewCoffeeGrinds() {
System.out.println("Steeping the tea.");
}
}
@Override
protected void addCondiments() {
System.out.println("Adding sugar and milk.");
}
@Override
protected void brewCoffeeGrinds() {
System.out.println("Dripping coffee through filter.");
}
}
CoffeeTemplate tea = new Tea();
tea.makeCoffee(); // Output: Boiling water. Steeping the tea. Pouring coffee into cup. Adding lemon.
}
// Main class
public class Main {
public static void main(String[] args) {
CoffeeTemplate coffee = new Coffee();
coffee.makeCoffee(); // Output: Boiling water. Dripping coffee through filter. Pouring coffee into cup. Adding s
11.
CoffeeTemplate: Defines thetemplate method makeCoffee() with steps for making coffee or tea.
Coffee and Tea: Subclasses provide specific implementations for brewing and adding condiments.
Main: Demonstrates creating coffee and tea objects and calling makeCoffee(), which follows the template defined in the base class.
The Strategy Design Patternchanges an object's behavior at runtime by encapsulating a family of algorithms into separate classes. This patter
to switch between different strategies (or algorithms) without altering the code that uses it.
The Advantages of the Adapter Design Pattern are:
Adaptable: The Adapter Design Pattern overcomes the incompatibility between interfaces by taking an interface of one class and convert
interface, one expected by the client, that way making formerly incompatible systems work together seamlessly.
Reusability:The existing code can already be reused for a new system without any modification to the original code. That will help to redu
and rework of already existing codes and systems.
Flexibility: Adapters can be easily changed or replaced without changing the client code, thus enabling flexibility to attach different compone
per changing requirements.
Decoupling: Reduces the dependency of client code on the subsystem by abstracting the integration logic and helps in producing much
maintainable code.
25. Explain the advantages of using the Adapter Design Pattern?
26. How is the Strategy Design Pattern used to change the behavior of an object?
Example
// Strategy Interface
interface PaymentStrategy {
}
void pay(int amount);
public PayPalPayment(String email) {
// Concrete Strategy: PayPalPayment
class PayPalPayment implements PaymentStrategy {
private String email;
public CreditCardPayment(String cardNumber) {
this.cardNumber = cardNumber;
}
// Concrete Strategy: CreditCardPayment
class CreditCardPayment implements PaymentStrategy {
private String cardNumber;
}
@Override
public void pay(int amount) {
System.out.println("Paying " + amount + " using Credit Card: " + cardNumber);
}
12.
Output
Explanation
Try it Yourself>>
In this example,
PaymentStrategy: Defines a common interface for payment methods.
CreditCardPayment and PayPalPayment: Concrete strategies implementing the payment interface with specific behaviors.
PaymentProcessor: Context class that uses a PaymentStrategy object and can switch strategies dynamically.
Main: Demonstrates switching between different payment strategies at runtime.
27. What are the key components of the Builder Design Pattern?
this.email = email;
}
}
public void processPayment(int amount) {
paymentStrategy.pay(amount);
}
// Context: PaymentProcessor
class PaymentProcessor {
private PaymentStrategy paymentStrategy;
Paying 100 using Credit Card: 1234-5678-9876-5432
Paying 200 using PayPal account: user@example.com
// Main class
public class Main {
public static void main(String[] args) {
PaymentProcessor processor = new PaymentProcessor();
public void setPaymentStrategy(PaymentStrategy paymentStrategy) {
this.paymentStrategy = paymentStrategy;
}
}
@Override
public void pay(int amount) {
System.out.println("Paying " + amount + " using PayPal account: " + email);
}
// Using Credit Card Payment Strategy
PaymentStrategy creditCard = new CreditCardPayment("1234-5678-9876-5432");
processor.setPaymentStrategy(creditCard);
processor.processPayment(100); // Output: Paying 100 using Credit Card: 1234-5678-9876-5432
}
// Switching to PayPal Payment Strategy
PaymentStrategy paypal = new PayPalPayment("user@example.com");
processor.setPaymentStrategy(paypal);
processor.processPayment(200); // Output: Paying 200 using PayPal account: user@example.com
}
13.
Implements the Builderinterface.
Constructs and assembles the parts of the product.
Keeps track of the product's current state.
There are five key components ofthe builderDesign Pattern:
Defines the steps required to build the parts of a complex object.
Provides methods for creating different parts of the product.
Uses the Director and Builder to create the product.
Does not need to understand the details of how the product is assembled.
Represents the complex object being constructed.
Consists of various parts or components that are assembled by the builder.
Uses the Builder object to construct the product.
Defines the order in which the steps should be executed to build the product.
Access Control: The proxy can control access to the RealSubject, e.g., by implementing security checks.
Lazy Initialization: The proxy can delay the creation of the RealSubject until it is actually needed, improving performance.
Logging: The proxy can log access to the RealSubject, which is useful for monitoring or debugging.
Caching: The proxy can cache results from the RealSubject to optimize performance.
The Proxy Design Pattern is a structural design pattern that provides a surrogate or placeholder for another object. It controls access to the re
perform additional actions such as lazy initialization, access control, logging, or caching.
5. Client
Example
4. Director
3. Product
1. Builder Interface
2. Concrete Builder
Main Functions of the Proxy Pattern
28. What is the proxy pattern, and what does it do?
// Subject Interface
interface Image {
}
void display();
// Real Subject
class RealImage implements Image {
private String filename;
public RealImage(String filename) {
this.filename = filename;
loadImageFromDisk();
}
private void loadImageFromDisk() {
System.out.println("Loading " + filename);
}
14.
Output
Explanation
Try it Yourself>>
In this example,
Image: The common interface for RealImage and ProxyImage.
RealImage: The actual object that performs the heavy lifting.
ProxyImage: Manages access to RealImage, adding lazy initialization.
Main: Demonstrates how the proxy delays the loading of the image until it is needed.
Loading image1.jpg
Displaying image1.jpg
Loading image2.jpg
Displaying image2.jpg
Displaying image1.jpg
// Proxy
class ProxyImage implements Image {
private RealImage realImage;
private String filename;
public ProxyImage(String filename) {
this.filename = filename;
}
}
@Override
public void display() {
if (realImage == null) {
realImage = new RealImage(filename);
}
realImage.display();
}
// Client code
public class Main {
public static void main(String[] args) {
Image image1 = new ProxyImage("image1.jpg");
Image image2 = new ProxyImage("image2.jpg");
}
@Override
public void display() {
System.out.println("Displaying " + filename);
}
}
// Image is loaded only when display() is called image1.display(); // Output:
Loading image1.jpg, Displaying image1.jpg image2.display(); // Output: Loading
image2.jpg, Displaying image2.jpg image1.display(); // Output: Displaying
image1.jpg (no loading)
}
15.
30. Explain theData Access Object (DAO) Design Pattern?
The Data Access Object (DAO) Design Pattern is a structural pattern that separates the data access logic from the business logic of an applicat
abstract interface for accessing data, which allows the rest of the application to interact with the data source (such as a database) without know
how the data is stored and retrieved.
29. How is the bridge pattern different from the adapter pattern?
31. How would you use the Prototype Design Pattern to clone objects?
The Prototype Design Pattern creates copies of objects without needing to know their specific classes. This pattern is particularly useful w
instances of objects is costly or complex.
Focus
Aspects
Purpose
Example
Use Case
Components
1. Define a Prototype Interface:Create an interface that declares a clone method. This method is responsible for copying the object.
2. Implement the Prototype: Create concrete classes that implement the prototype interface. Implement the clone method to provide a wa
object.
3. Client Code: Use the clone method to create new objects based on an existing prototype.
Bridge Pattern
Separates abstraction from implementation, allowing them to vary independently.
Adapter Pattern
Converts the interface of a class into anoth
a client expects.
Involves an interface that needs adaptation
that translates it.
Useful when integrating incompatible inter
into a system.
Adapting a Rectangle class to fit into an
expected by a client.
Making incompatible interfaces compatible
Involves an abstraction (interface) and its implementation (details).
Useful when needing to extend both the abstraction and implementation
independently.
An abstract Shape class with different DrawingAPI implementations (e.g., drawing
on different platforms).
Decoupling the interface and implementation.
Abstracts Data Access: Provides an interface to interact with the data source, hiding implementation details.
Encapsulates CRUD Operations: Standardizes methods for creating, reading, updating, and deleting data.
Separates Concerns: Keeps data access code separate from business logic for better maintainability.
Supports Multiple Implementations: Allows different data sources or storage mechanisms to be used interchangeably.
Facilitates Testing: Enables easier unit testing by using mock implementations of the DAO interface.
Example
Key steps involved:
// Prototype interface
interface Prototype {
Prototype clone();
}
// Getter
public String getName() {
// Constructor
public ConcretePrototype(String name) {
this.name = name;
}
// Concrete prototype class
class ConcretePrototype implements Prototype {
private String name;
16.
Output
Explanation
Try it Yourself>>
Prototype Interface: Prototype defines the clone method for cloning objects.
ConcretePrototype: Implements the Prototype interface. The clone method creates a new instance of ConcretePrototype with the same na
object.
Main Class: Creates an instance of ConcretePrototype, clones it, and prints the names of both the original and cloned objects.
Here are the benefits of using the Visitor Design Pattern in short bullet points:
Separation of Concerns: It distinguishes algorithms from the objects on which they work. This enables you to introduce new actions witho
classes.
Improved Maintainability: By separating the actions from the object structure, the code is easier to maintain and extend. Changes to opera
the object structure, and vice versa.
Versatility in Integrating Operations: Additional operations can be introduced without affecting existing object structures. This makes it e
features or functionality.
32. What are the benefits of using the Visitor Design Pattern?
return name;
}
Original Object Name: Original
Cloned Object Name: Original
// Setter
public void setName(String name) {
this.name = name;
}
}
// Implement the clone method
@Override
public Prototype clone() {
// Create a new instance with the same name
return new ConcretePrototype(this.name);
}
// Clone the original object
ConcretePrototype clone = (ConcretePrototype) original.clone();
// Main class to demonstrate the Prototype Pattern
public class Main {
public static void main(String[] args) {
// Create an original object
ConcretePrototype original = new ConcretePrototype("Original");
}
// Display the results
System.out.println("Original Object Name: " + original.getName());
System.out.println("Cloned Object Name: " + clone.getName());
}
17.
Consistent Interface: Itprovides a consistent interface for conducting operations on various sorts of objects, hence improving the cohere
distinct pieces in the object structure.
The roles of the mediator design pattern are:
Centralizes Communication: Manages and centralizes interactions between objects, reducing direct dependencies between them.
Simplifies Object Interaction: Facilitates communication between complex sets of objects by defining a mediator object that handles all inte
Reduces Coupling: Decouples components, making it easier to change or extend them independently without affecting others.
Encapsulates Communication Logic: Encapsulates the communication logic in the mediator, promoting cleaner and more maintainable code
Improves Control and Coordination: Provides a single point of control for complex interactions, improving coordination and managing o
effectively.
Imagine an online shopping system where a customer can place an order. This system might involve multiple subsystems such as invent
payment processing, and shipping services. Each subsystem has its own complex interface and operations.
33. Explain the role of the Mediator Design Pattern?
34. Describe a scenario where the Facade Design Pattern can be applied.
Scenario: Online Shopping System
Example
// Facade class
class OrderFacade {
private InventoryService inventoryService;
private PaymentService paymentService;
private ShippingService shippingService;
public OrderFacade() {
inventoryService = new InventoryService();
paymentService = new PaymentService();
shippingService = new ShippingService();
}
// Inventory subsystem
class InventoryService {
}
public void checkStock(String item) {
System.out.println("Checking stock for " + item);
}
// Shipping subsystem
class ShippingService {
}
public void arrangeShipping(String address) {
System.out.println("Arranging shipping to " + address);
}
public void placeOrder(String item, String paymentDetails, String address) {
// Payment subsystem
class PaymentService {
}
public void processPayment(String paymentDetails) {
System.out.println("Processing payment with details: " + paymentDetails);
}
18.
Output
Explanation
1. Using synchronizedkeyword (Lazy Initialization)
Try it Yourself >>
Aspect
Purpose
Immutability
Equality
Usage
Value Object (VO)
Represents a descriptive piece of data for transfer.
Typically immutable, once created, its state cannot change.
Equality is based on the value of attributes.
Used to transfer data between different parts of a system.
Integration
Example
Not related to databases or persistence.
java public class Address { private final String street; ... }
In this example
Subsystems: Handle different aspects of the system but have complex interfaces.
Facade: OrderFacade provides a simplified method placeOrder to handle complex interactions with the subsystems.
Client Code: Uses the OrderFacade to place an order without needing to interact with each subsystem directly.
There are several approaches to implementing a thread-safe Singleton in Java. Below are two of the most common methods:
Java Data Object (JDO)
Manages persistent storage of Java objects.
Mutable; managed for persistence in a data store.
Equality is based on object identity or database row identity.
Used for storing and retrieving objects from a database.
Directly related to database operations and mapping.
java import javax.jdo.annotations.*; @PersistenceCapable public c
36. How would you implement a thread-safe Singleton in Java?
35. What is the difference between Value Object (VO) and Java Data Object (JDO)?
Top 15 Java Design Patterns Interview Questions and Answers For Experienced
Checking stock for Laptop
Processing payment with details: Credit Card
Arranging shipping to 123 Main St, Anytown, USA
Order placed successfully!
// Main class to demonstrate the Facade Pattern
public class Main {
public static void main(String[] args) {
// Create a facade instance
OrderFacade orderFacade = new OrderFacade();
}
inventoryService.checkStock(item);
paymentService.processPayment(paymentDetails);
shippingService.arrangeShipping(address);
System.out.println("Order placed successfully!");
}
}
// Place an order using the simplified facade interface
orderFacade.placeOrder("Laptop", "Credit Card", "123 Main St, Anytown, USA");
}
19.
Try it Yourself>>
This method ensures that the Singleton instance is created only when it's needed, and the synchronized keyword guarantees thread safety.
This method improves performance by minimizing the use of synchronized, which is only used when the instance is null. After the instan
synchronized block is bypassed.
Output
2. Double-Checked Locking (Efficient and Thread-Safe)
class Singleton {
}
// Method to demonstrate Singleton behavior
void showMessage() {
System.out.println("Hello from Singleton!");
}
public class Main {
public static void main(String[] args) {
// Getting the singleton instance
Singleton singleton1 = Singleton.getInstance();
singleton1.showMessage();
// Getting the singleton instance again
Singleton singleton2 = Singleton.getInstance();
singleton2.showMessage();
// Method to provide access to the Singleton instance
static Singleton getInstance() {
return SingletonHelper.INSTANCE;
}
// Constructor with package-private (default) visibility
Singleton() {
System.out.println("Singleton Instance Created");
}
// Static inner class responsible for holding Singleton instance
static class SingletonHelper {
static final Singleton INSTANCE = new Singleton();
}
}
// Checking if both instances are the same
if (singleton1 == singleton2) {
System.out.println("Both instances are the same (Singleton pattern working correctly)");
} else {
System.out.println("Instances are different (Singleton pattern failed)");
}
}
20.
Explanation
In this example,
LazyInitialization: The Singleton instance is created only when the getInstance() method is called for the first time.
Thread Safety: The class is loaded on the first call to getInstance(), and class loading is thread-safe in Java.
The Observer Design Pattern is used to create a one-to-many relationship between objects. It allows an object, called the "subject," to notify a lis
"listeners") automatically whenever there is a change in its state, without the subject having to know who the observers are.
Real-Time Monitoring System Example: Server Health Monitoring System
Data Access Object (DAO) pattern is a structural pattern that provides an abstract interface to interact with a database or any other persi
encapsulates all the data access logic, allowing the business logic to interact with the persistence layer without needing to know the details o
stored or retrieved.
Abstraction: The DAO pattern separates the business logic from the data access logic by creating a layer dedicated to CRUD operations (Cre
Delete).
Encapsulation: The pattern encapsulates database access logic, making the business layer independent of the data source.
Reusability: By separating the data access logic, the DAO pattern promotes reuse and makes it easier to switch between different data sourc
mechanisms.
Maintainability: Changes to the data source (e.g., moving from a relational database to NoSQL) are localized to the DAO classes, minimizing
in other parts of the application.
Testability: The DAO pattern makes unit testing easier because the business logic can be tested independently of the persistence layer.
37. Explain the Data Access Object (DAO) pattern?
38. Explain the use of the Observer pattern in a real-time monitoring system?
import java.util.ArrayList;
import java.util.List;
// Observer interface
interface Observer {
}
void update(String healthStatus);
public Server() {
this.observers = new ArrayList<>();
// Subject interface
interface Subject {
}
void addObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers();
// Server class which is the subject being observed
class Server implements Subject {
private List<Observer> observers;
private String serverHealth;
Singleton Instance Created
Hello from Singleton!
Hello from Singleton!
Both instances are the same (Singleton pattern working correctly)
21.
}
public Admin(String name){
this.adminName = name;
}
// Concrete Observer: Admin
class Admin implements Observer {
private String adminName;
public String getServerHealth() {
return serverHealth;
}
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(serverHealth);
}
}
public void setServerHealth(String health) {
this.serverHealth = health;
notifyObservers();
}
@Override
public void addObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
// Main class to demonstrate the real-time monitoring system using the Observer pattern
public class RealTimeMonitoringSystem {
public static void main(String[] args) {
// Create the subject (server) being observed
}
@Override
public void update(String healthStatus) {
System.out.println("Admin " + adminName + " notified. Server Health: " + healthStatus);
}
// Concrete Observer: Logging System
class LoggingSystem implements Observer {
}
@Override
public void update(String healthStatus) {
System.out.println("Logging System: Server health status updated to: " + healthStatus);
}
22.
Out[ut
Explanation
In this example,
Tryit Yourself >>
The Server class represents the system being monitored (the subject).
Server server = new Server();
// Register observers with the server
server.addObserver(admin1);
server.addObserver(admin2);
server.addObserver(loggingSystem);
Changing server health to: Healthy
Admin Alice notified. Server Health: Healthy
Admin Bob notified. Server Health: Healthy
Logging System: Server health status updated to: Healthy
Changing server health to: Unstable
Admin Alice notified. Server Health: Unstable
Admin Bob notified. Server Health: Unstable
Logging System: Server health status updated to: Unstable
Changing server health to: Critical
Admin Alice notified. Server Health: Critical
Admin Bob notified. Server Health: Critical
Logging System: Server health status updated to: Critical
Changing server health to: Down
Admin Alice notified. Server Health: Down
Logging System: Server health status updated to: Down
// Create observers
Admin admin1 = new Admin("Alice");
Admin admin2 = new Admin("Bob");
LoggingSystem loggingSystem = new LoggingSystem();
// Simulate server health changes
System.out.println("Changing server health to: Healthy");
server.setServerHealth("Healthy");
System.out.println("Changing server health to: Unstable");
server.setServerHealth("Unstable");
System.out.println("Changing server health to: Critical");
server.setServerHealth("Critical");
}
// Unregister an observer (Admin2) and update server health
server.removeObserver(admin2);
System.out.println("Changing server health to: Down");
server.setServerHealth("Down");
}
23.
Virtual proxies areutilized to create the pricey object.
The proxy in the implementation manages the true subject's lifetime.
It determines the requirement for instance creation and when to reuse it.
Virtual proxies improve performance.
Caching proxies are used to save expensive calls to the actual subject.
There are numerous caching mechanisms that the proxy can employ.
Many of them are read-through, write-through, cache-aside, and time-dependent.
Caching proxies are used to improve performance.
There are numerous instances where the proxy pattern is advantageous. Let's look at a few different proxies:
The Admin and LoggingSystem classes are concrete observers that listen for changes in the server’s health.
When the server’s health changes (e.g., from "Healthy" to "Unstable"), it automatically notifies all registered observers (admins and the logg
the notifyObservers() method.
Admins and the logging system receive real-time updates without needing to manually check the server’s status.
The Observer pattern is ideal for systems that need to broadcast state changes to multiple objects, such as server monitoring, where vario
users (admins, logging systems, dashboards) need real-time notifications.
It decouples the subject (server) from the observers, making the system more flexible and easier to maintain. New observers can be added o
changing the subject’s logic.
A Remote Proxy provides a local representative for an object that resides in a different address space, typically on a different machine o
interaction with it as if it were local.
It handles the communication, serialization, and network complexities between the client and the remote object, simplifying distributed comp
The Model-View-Controller (MVC) pattern is a software architectural pattern used for building user interfaces. It divides an application into thr
components: Model (data and business logic), View (UI representation), and Controller (handles user input and interactions).
Model: Manages data and business logic, interacting with the database.
View: Displays the data from the model to the user, handling the UI layer.
Controller: Interprets user inputs, updating the model or the view as necessary.
Separation of Concerns: Each component has a specific role, making the application modular and easier to maintain.
Reusability: Changes to the view or model can be made independently, enhancing flexibility.
A Smart Proxy adds extra functionality to the object it represents, such as caching, logging, or access control, before forwarding requests to t
It can enhance performance, track usage, or manage additional services without altering the original object’s implementation.
A Protection Proxy controls access to an object by adding a layer of authorization, ensuring that only authorized users or operations ca
methods or data.
It acts as a gatekeeper, preventing unauthorized access by validating requests before forwarding them to the actual object.
5. Smart Proxies
2. Virtual proxies
4. Remote proxies
3. Caching Proxies
1. Protection proxy
Use cases of the Observer Pattern
39. What are the MVC patterns?
40. Explain some different types of proxies.
41. How would you use the Command Design Pattern to implement an undo feature?
24.
The Command DesignPattern is ideal for implementing an undo feature because it encapsulates a request as an object. This allows you to pa
with queues, requests, and operations and to support undo functionality.
1. Define Command Interface: Create an interface for commands that includes methods for executing and undoing the command.
2. Create Concrete Commands: Implement concrete command classes that encapsulate the operations and their corresponding undo logic.
3. Maintain Command History: Keep a stack or list of executed commands to enable undo functionality.
4. Invoker: Use an invoker to execute commands and store them in history. It also handles the undo operation by calling the undo method on
command.
5. Receiver: The receiver is the object that performs the actual work of the command.
Steps to Implement Undo with the Command Pattern
// Command interface
interface Command {
}
void execute();
void undo();
import java.util.Stack;
@Override
public void execute() {
editor.write(text);
}
}
@Override
public String toString() {
return text.toString();
}
public void write(String str) {
text.append(str);
}
// Concrete Command for writing text
class WriteCommand implements Command {
private TextEditor editor;
private String text;
public void undoWrite(String str) {
int start = text.length() - str.length();
if (start >= 0) {
text.delete(start, text.length());
}
}
// Receiver class
class TextEditor {
private StringBuilder text = new StringBuilder();
public WriteCommand(TextEditor editor, String text) {
this.editor = editor;
this.text = text;
}
25.
Output
}
@Override
public void undo(){
editor.undoWrite(text);
}
Editor Content: Hello World!
Editor Content after undo: Hello
}
public void undo() {
if (!history.isEmpty()) {
Command command = history.pop();
command.undo();
}
}
public void executeCommand(Command command) {
command.execute();
history.push(command);
}
// Invoker class
class CommandManager {
private Stack<Command> history = new Stack<>();
// Execute commands
commandManager.executeCommand(writeHello);
commandManager.executeCommand(writeWorld);
System.out.println("Editor Content: " + editor);
Command writeHello = new WriteCommand(editor, "Hello ");
Command writeWorld = new WriteCommand(editor, "World!");
// Main class to demonstrate the Command Pattern with undo feature
public class CommandPatternDemo {
public static void main(String[] args) {
TextEditor editor = new TextEditor();
CommandManager commandManager = new CommandManager();
// Undo the last command
commandManager.undo();
System.out.println("Editor Content after undo: " + editor);
}
// Undo the next command
commandManager.undo();
System.out.println("Editor Content after second undo: " + editor);
}
Try it Yourself >>
26.
Explanation
Steps to UseVisitor Pattern for File System Operations:
In this example,
Command Interface: Defines methods for execute and undo.
Concrete Command: Implements specific operations and their undo logic.
Invoker: Manages command execution and maintains a history stack for undo functionality.
Receiver: Performs the actual operations, like writing and undoing text.
Client: Executes commands and performs undo operations via the CommandManager.
The Visitor design pattern effectively implements operations on a file system by separating the algorithm from the objects on which it operates.
The impact of the Flyweight pattern on system performance are:
Reduced Memory Usage: By sharing common objects rather than creating new instances, the Flyweight pattern minimizes memory consum
when dealing with large numbers of similar objects.
Improved Performance: Reduces overhead associated with creating and managing multiple similar objects, leading to more efficient resou
faster execution.
Enhanced Scalability: Helps systems scale better by avoiding the performance hit of instantiating and maintaining numerous objec
environments with high object creation rates.
Encapsulation of Shared Data: Centralizes and manages shared data, reducing duplication and inconsistencies while simplifying maintenanc
Increased Complexity: Introduces additional complexity in managing the shared objects and their intrinsic and extrinsic states, which can c
and debugging.
1. Define the Element Interface: Create an interface or abstract class for file system elements (e.g., File and Directory), which includes an ac
takes a Visitor.
2. Create Concrete Elements:Implement the File and Directory classes, each with an accept method that invokes the appropriate visit method on
3. Define the Visitor Interface: Create an interface for visitors that defines a visit method for each type of element (e.g., visitFile and visitDirectory
4. Implement Concrete Visitors: Implement concrete visitor classes that perform specific operations (e.g., PrintVisitor for printing detai
calculating total size).
5. Use Visitors: Apply visitors to file system elements to perform operations without altering the element classes.
42. What is the impact of the Flyweight pattern on system performance?
43. How can the Visitor pattern be used to implement operations on a file system?
import java.util.ArrayList;
import java.util.List;
// Element interface
interface FileSystemElement {
}
void accept(Visitor visitor);
Editor Content after second undo:
// File class
class File implements FileSystemElement {
private String name;
private int size;
27.
int getSize() {
returnsize;
}
String getName() {
return name;
}
String getName() {
return name;
}
Directory(String name) {
this.name = name;
}
public File(String name, int size) {
this.name = name;
this.size = size;
}
}
@Override
public void accept(Visitor visitor) {
visitor.visitFile(this);
}
}
@Override
public void accept(Visitor visitor) {
visitor.visitDirectory(this);
}
List<FileSystemElement> getElements() {
return elements;
}
// Visitor for printing file system structure
class PrintVisitor implements Visitor {
// Visitor interface
interface Visitor {
}
void visitFile(File file);
void visitDirectory(Directory directory);
void addElement(FileSystemElement element) {
elements.add(element);
}
// Directory class
class Directory implements FileSystemElement {
private String name;
private List<FileSystemElement> elements = new ArrayList<>();
28.
}
int getTotalSize() {
returntotalSize;
}
@Override
public void visitFile(File file) {
totalSize += file.getSize();
}
// Visitor for calculating total size
class SizeVisitor implements Visitor {
private int totalSize = 0;
// Use PrintVisitor to print the file system structure
Visitor printVisitor = new PrintVisitor();
directory.accept(printVisitor);
}
@Override
public void visitDirectory(Directory directory) {
System.out.println("Directory: " + directory.getName());
for (FileSystemElement element : directory.getElements()) {
element.accept(this);
}
}
@Override
public void visitDirectory(Directory directory) {
for (FileSystemElement element : directory.getElements()) {
element.accept(this);
}
}
// Main class to demonstrate the Visitor Pattern with file system operations
class VisitorPatternDemo {
public static void main(String[] args) {
File file1 = new File("file1.txt", 100); File file2 = new
File("file2.txt", 200); Directory directory = new
Directory("myDirectory");
directory.addElement(file1);
directory.addElement(file2);
}
// Use SizeVisitor to calculate total size
SizeVisitor sizeVisitor = new SizeVisitor();
directory.accept(sizeVisitor);
System.out.println("Total size: " + sizeVisitor.getTotalSize() + " bytes");
}
@Override
public void visitFile(File file) {
System.out.println("File: " + file.getName() + ", Size: " + file.getSize() + " bytes");
}
29.
Output
Explanation
Try it Yourself>>
The purpose of the Momento Design Pattern are:
Undo/Redo operations: Allow objects to revert to a previous state when needed.
Encapsulation: Protect an object's internal state from external access while still enabling restoration.
State history tracking: Record and revert state changes over time in applications like text editors, game development, etc.
The Chain of Responsibility (CoR) pattern can be optimized in a large system using the following techniques:
Use a lookup mechanism: Instead of traversing the entire chain, use a lookup table or a map to quickly find the appropriate handler, redu
iterations.
Conditional shortcuts: Implement checks to exit the chain early if a condition is met or if it's clear the chain can be skipped for certain inputs.
Lazy initialization: Delay the creation of handlers until they are actually needed, which reduces memory usage and speeds up initialization.
Parallel handling: In cases where order is not important, process multiple handlers in parallel to improve response time. Caching: Cache
results of previously handled requests to prevent reprocessing similar requests and speed up handling.
The State design pattern simplifies state management in a complex application by:
Encapsulating state-specific behavior: It separates each state into its own class, making the logic for each state easier to manage and modif
Eliminating large conditional statements: Instead of using complex if-else or switch conditions to handle state transitions, the pattern dyn
the object's behavior by delegating state-specific tasks to state objects.
Making state transitions explicit: State changes are clearly managed through transitions between state objects, improving code
maintainability.
Promoting scalability: New states can be easily added without modifying existing code, ensuring the system can scale efficiently. Reducing
code duplication: By centralizing state-related logic into separate classes, common behavior can be shared or reused, leading to cle
In this example,
FileSystemElement Interface: Defines an accept() method for elements (files or directories) that accept a Visitor.
File and Directory Classes: File represents individual files, while Directory represents a collection of FileSystemElement objects.
FileSystemElement.
Visitor Interface: Defines methods visitFile() and visitDirectory() for performing operations on File and Directory elements.
PrintVisitor and SizeVisitor: Implement the Visitor interface. PrintVisitor prints the structure, and SizeVisitor calculates the total size of files
Main Method (VisitorPatternDemo): Demonstrates the use of both PrintVisitor and SizeVisitor to print the structure and calculate the total s
directory.
44. What is the purpose of the Memento Design Pattern?
47. What are the limitations of the Command Design Pattern?
45. How can the Chain of Responsibility pattern be optimized in a large system?
46. How can the State pattern simplify state management in a complex application?
Directory: myDirectory
File: file1.txt, Size: 100 bytes
File: file2.txt, Size: 200 bytes
Total size: 300 bytes
30.
The Interpreter DesignPattern can be used in a simple calculator application by defining a grammar for arithmetic expressions and implem
interpret different operations like addition, subtraction, etc.
Below is an example in Java that demonstrates how you can implement this pattern in a simple calculator.
The Decorator Design Pattern promotes code reusability in the following ways:
Flexible functionality extension: It allows new behavior to be added to objects dynamically without modifying their code, promoting the
classes.
Composition over inheritance: Instead of creating numerous subclasses to add features, decorators can be combined and applied in differe
the code more modular and reusable.
Single Responsibility: Each decorator focuses on a single piece of functionality, making it easier to reuse specific behaviors independent
objects
Open/Closed Principle: Classes can be extended without changing their original implementation, making the system adaptable and maintain
The Command Design Pattern may create numerous limitations:
Increased number of classes: Each command requires its own class, which can lead to a large number of additional classes, increasing the
system.
Higher memory usage: Storing commands for potential undo/redo functionality can increase memory consumption, especially in sys
commands.
Complexity in command management: Managing the lifecycle of commands (e.g., undo/redo, logging) can add complexity to the system, re
infrastructure.
Hard to maintain: With many command types, maintaining and understanding the relationships between them can become more challenging
Overhead for simple operations: Using the Command pattern for very basic or trivial operations may add unnecessary overhead to the design
48. How does the Decorator Design Pattern promote code reusability?
49. Explain how the Interpreter pattern can be used in a simple calculator application.
}
@Override
public int interpret() {
return number;
}
// Define the Expression interface
interface Expression {
}
int interpret();
public NumberExpression(int number) {
this.number = number;
}
// Non-Terminal Expression for addition
class AddExpression implements Expression {
private Expression leftExpression;
private Expression rightExpression;
// Terminal Expression for numbers
class NumberExpression implements Expression {
private int number;
31.
Output
Explanation
Try it Yourself>>
In this example
The Expression interface defines the interpret() method, which is implemented by all expression classes.
NumberExpression represents a number and returns its value.
AddExpression and SubtractExpression are used to combine other expressions.
The Calculator class constructs the expression tree for (5+3)-2 and prints the results.
Result: 6
// Non-Terminal Expression for subtraction
class SubtractExpression implements Expression {
private Expression leftExpression;
private Expression rightExpression;
public AddExpression(Expression left, Expression right) {
this.leftExpression = left;
this.rightExpression = right;
}
}
// Interpret and print the result
System.out.println("Result: " + expression.interpret());
}
public SubtractExpression(Expression left, Expression right) {
this.leftExpression = left;
this.rightExpression = right;
}
}
@Override
public int interpret() {
return leftExpression.interpret() + rightExpression.interpret();
}
}
@Override
public int interpret() {
return leftExpression.interpret() - rightExpression.interpret();
}
// Main class to test the Interpreter pattern
public class Calculator {
public static void main(String[] args) {
// Represents the expression (5 + 3) - 2
Expression expression = new SubtractExpression(
new AddExpression(new NumberExpression(5), new NumberExpression(3)),
new NumberExpression(2)
);
32.
50. What arethe advantages of using the Bridge Design Pattern?
The Bridge Design Pattern provides various advantages:
Separation of Abstraction and Implementation: It isolates the abstraction from the implementation, allowing them to change independently
managing complicated systems when changes in abstraction or implementation do not affect each other.
Increased Flexibility: It allows for the construction of new abstractions and implementations without changing existing code, enhanc
scalability.
Enhanced Maintainability: By decoupling abstraction from implementation, code maintenance and extension are simplified, making it easi
update.
Improved Code Reusability: It enables distinct implementations to be reused across several abstractions, eliminating code duplicatio
reusability.
This article provides a curated selection of the top 50 Java design pattern interview questions and answers for beginners, intermediate,
developers. It covers a wide spectrum of design patterns, from the basics like Singleton and Factory to more complex ones like Flyweight
component is intended to help developers, regardless of experience level, improve their comprehension and confidently respond to design pa
interviews. To master design patterns, enroll in ScholarHat's Master Software Architecture and Design Certification Training.
Summary