Refactoring Guru already has the best blog to learn Design patterns. Here I am just trying to give a brief about each design.
Design patterns are solutions to recurring problems and design paradigms.
Behavioral design patterns focus on the algorithms and the distribution of responsibilities among objects.
You can get the Java code here or some detailed examples.
Let's dive into each one.......
Chain of Responsibility
Chain of Responsibility is a behavioral design pattern that allows requests to be passed along a chain of handlers. When a request is received, each handler determines whether to process it or to forward it to the next handler in the chain.
Class Diagram
The primary goal of this pattern is to decouple the sender of a request from its receivers. Instead of the sender knowing exactly which object can fulfill a request, it simply sends the request to the "head" of the chain.
-
Key Components
- Handler (Interface/Abstract Class): Defines the interface for handling requests and usually contains a reference to the "next" handler in the line.
- Concrete Handlers: These are the actual workers. They check if they can handle the specific request. If they can, they process it; if not, they forward it to their successor.
- Client: Initiates the request and usually composes the chain by linking handlers together.
-
Why Use It?
- Reduced Coupling: The client doesn't need to know the internal structure of the chain or which specific object handles the task.
- Flexibility: You can add, remove, or reorder handlers dynamically without breaking the client code.
- Single Responsibility: Each class focuses on one specific type of processing or decision-making.
-
Real-World Example
Think of a Technical Support Call Center.- Level 1 Support answers first. If it's a basic password reset, they handle it.
- If it’s a complex server error, they pass the "request" to Level 2.
- If Level 2 can't solve it, it goes to Level 3 (Engineers).
Command Pattern
The Command pattern is a behavioral design pattern that converts a request into a standalone object that encapsulates all the details of that request. This transformation allows you to pass requests as method arguments, delay or queue their execution, and support undoable operations.
Class Diagram
The key idea is to "encapsulate a request as an object." By converting a command (like "Turn On Light" or "Save File") into its own object, you can treat that request as a variable. You can pass it to other objects, store it for later, or queue it. The object that asks for the action (the Invoker) is decoupled from the object that actually does the work (the Receiver).
-
Key Components
- Command (Interface): Defines the interface all commands must implement, typically an
execute()method and optionally anundo()method. - Concrete Command: The actual command object. It "knows" its specific Receiver (the object that will do the work) and implements
execute()by calling methods on that Receiver. - Invoker (Sender): The object that triggers the command. It holds a reference to a Command object and calls
execute()at the right time. Crucially, the Invoker doesn't know what the command actually does or who receives it. - Receiver (Receiver): The object that holds the business logic. It knows how to perform the actual work (e.g., a Light class with
turnOn()andturnOff()methods). - Client: The code responsible for creating the Concrete Command objects and setting up the links between the Invoker and the command.
- Command (Interface): Defines the interface all commands must implement, typically an
-
Key Benefits
- Decoupling: Senders (Invokers) and receivers are completely separated. They interact through the Command interface.
- Flexibility: You can easily add new commands without modifying either the client or the invoker code.
- Undo/Redo: Since a command object stores its state and knows the receiver, it is simple to implement
undo()andredo()by keeping a history of executed command objects. - Queuing/Logging: You can queue commands for later execution, log them for debugging, or transmit them over a network.
-
Real-World Example
A simple smart home remote.- Invoker: The
RemoteControlobject with buttons (ButtonA,ButtonB). - Command (Interface): Command interface with
execute(). - Concrete Command:
LightOnCommandandLightOffCommand. - Receiver: The physical
LivingRoomLightobject. - Client: The application that configures the remote control by saying: "When
ButtonAis pressed, execute thisLightOnCommandlinked to thatLivingRoomLight."
- Invoker: The
Iterator
Iterator is a behavioral design pattern that allows you to traverse elements of a collection without revealing its underlying structure (list, stack, tree, etc.).
Class Diagram
The main goal of the Iterator pattern is to take the responsibility for traversal out of the collection and place it in a separate object called an Iterator. This keeps the collection clean and focused solely on storing data, while allowing multiple different ways to "walk through" that data simultaneously.
-
Key Components
- Iterator (Interface): Defines the operations required to traverse the collection (e.g.,
getNext(),hasMore(), orreset()). - Concrete Iterator: Implements the traversal algorithm. It keeps track of the current position in the traversal, so the collection doesn't have to.
- Iterable Collection (Interface): Declares a method for getting an iterator compatible with the collection.
- Concrete Collection: Returns a new instance of a specific Concrete Iterator class each time the client requests one.
- Iterator (Interface): Defines the operations required to traverse the collection (e.g.,
-
Why Use It?
- Clean Code: It follows the Single Responsibility Principle by decoupling the traversal logic from the data structure.
- Uniform Interface: You can traverse different types of complex data structures (like a Graph vs. a List) using the exact same client code.
- Parallel Traversal: Since each iterator object maintains its own state, you can have two or three different "pointers" moving through the same collection at once.
-
Real-World Example
Think of a TV Remote.- The Collection is the list of programmed channels.
- The Iterator is the logic behind the "Next" and "Previous" buttons.
- The remote allows you to cycle through the channels (the traversal) without you needing to know how the TV stores the channel list internally (the representation).
Mediator
Mediator is a behavioral design pattern that reduces chaotic dependencies between objects. The pattern limits direct communication among the objects and requires them to collaborate only through a mediator object.
Class Diagram
The Mediator pattern acts as a "middleman" or an air traffic controller. Instead of dozens of objects (components) knowing about each other and calling each other's methods—which creates a tangled "spaghetti code" mess—they all talk to a single Mediator object. The Mediator knows how all the components should interact and directs the flow of data.
-
Key Components
- Mediator (Interface): Defines the communication protocol (usually a
notifymethod) that components use to notify the mediator of an event. - Concrete Mediator: Holds references to all the components it manages and coordinates their interactions. It knows which component needs to react when another component triggers an event.
- Components (Colleagues): These are various classes that perform business logic. They don't know other components exist; they only know their Mediator. When something happens in a component, it just notifies the Mediator.
- Mediator (Interface): Defines the communication protocol (usually a
-
Why Use It?
- Decoupling: Components become highly reusable because they no longer depend on other specific classes.
- Simplified Maintenance: Interaction logic is centralized in one place (the Mediator) rather than scattered across multiple components.
- Easier Customization: You can change how a whole system of objects interacts by simply creating a new Mediator subclass.
-
Real-World Example
An Air Traffic Control (ATC) Tower.- Components: Different airplanes (Boeing 747, Cessna, Airbus).
- Mediator: The ATC Tower.
The pilots don't talk to every other pilot in the sky to decide who lands first. They all talk to the Tower. The Tower coordinates the landing sequence to prevent collisions, keeping the individual aircraft decoupled.
Momento
Memento is a behavioral design pattern that allows an object to save and restore its previous state without revealing its implementation details.
Class Diagram
The Memento pattern allows an object (the Originator) to export a snapshot of its internal state into a small, opaque object (the Memento). This snapshot can be stored by another object (the Caretaker) and later handed back to the Originator to reset it to that exact point in time. Crucially, the Caretaker cannot see or modify the data inside the Memento.
-
Key Components
- Originator: The main object that has some internal state. It creates Mementos of itself and knows how to restore its state from them.
- Memento: A "dumb" data object that acts as a snapshot. It is usually immutable and only provides its data back to the Originator that created it.
- Caretaker: The object responsible for the Memento's "safekeeping." It might keep a stack (history) of Mementos to allow for multiple undo steps, but it never operates on or examines the contents of the Memento.
-
Why Use It?
- Encapsulation: It avoids exposing the Originator's internal fields to the rest of the program just to save state.
- Simplified Originator: The Originator doesn't need to keep track of its own history; the Caretaker handles the storage logic.
- Undo/Redo: It is the standard way to implement multi-level undo functionality in applications.
-
Real-World Example
A Code Editor (like VS Code).- Originator: The document or buffer containing your code.
- Memento: A snapshot of the text at a specific point in time.
- Caretaker: The editor's history manager.
When you press
Ctrl+Z, the Caretaker pulls the last Memento from its stack and returns it to the Originator to restore the text.
Observer
Observer is a behavioral design pattern that provides a subscription mechanism to notify multiple objects of any events occurring in the observed object.
Class Diagram
The pattern works like a subscription service. A central object, the Subject, maintains a list of subscribers called Observers. Whenever a significant event occurs or the Subject's state changes, it loops through its list of observers and calls the "update" method on each. The Subject doesn't need to know the specific details of what the observers do; it just needs to know they want to be notified.
-
Key Components
- Subject (Publisher): The object being watched. It provides an interface for attaching and detaching observers.
- Concrete Subject: Stores the state of interest and sends a notification to its observers when the state changes.
- Observer (Subscriber): An interface defining the
update()method that the Subject calls. - Concrete Observers: Individual objects that implement the update interface to perform specific actions (like refreshing a UI or logging data) when they receive a notification.
-
Why Use It?
- Loose Coupling: The Subject and Observers can vary independently. You can add new observer classes without changing the Subject’s code.
- Broadcast Communication: Unlike a standard function call, the Subject doesn't need to know who or how many objects are listening.
- Real-time Updates: It is the foundation for reactive programming and event-driven systems.
-
Real-World Example
YouTube Channels.- Subject: A YouTube Channel.
- Observers: The subscribers who have "hit the bell icon."
- Action: When the Channel uploads a new video, it doesn't manually email every person. It simply triggers a "notify" event, and YouTube's system automatically pushes a notification to every subscriber's device.
State
State is a behavioral design pattern that allows an object to change its behavior when its internal state changes, making it seem as though the object has changed its class.
Class Diagram
The State pattern is essentially a clean alternative to massive switch or if-else statements. Instead of having one class manage every possible behavior for every possible condition, it delegates the work to a State object. When the internal state changes, the Context object swaps out its current State object for a new one, immediately changing its behavior for the next request.
-
Key Components
- Context: The class that the outside world interacts with. It maintains a reference to a Concrete State object that represents the current state.
- State (Interface): Defines the methods that all concrete states must implement.
- Concrete States: Each class implements behaviors associated with a specific state of the Context. These classes can also trigger a transition to a different state by calling a method on the Context.
-
Why Use It?
- Organized Code: It eliminates "flag" variables and complex conditional logic, making the code much easier to read and maintain.
- State-Specific Behavior: It ensures that an object performs only actions valid for its current state.
- Open/Closed Principle: You can add new states and behaviors without changing the existing Context or State classes.
-
Real-World Example
An Automated Teller Machine (ATM).- Context: The ATM machine.
- States:
NoCardState,HasCardState,CorrectPinState,OutOfCashState. - Logic: If the machine is in
NoCardState, the "Withdraw" button does nothing. Once you insert a card, the machine transitions toHasCardState, and the buttons' behavior changes to allow PIN entry. If the machine runs out of bills, it switches toOutOfCashState, where all transaction requests are automatically denied.
Strategy
Strategy is a behavioral design pattern that defines a family of algorithms, places each in a separate class, and allows their objects to be interchangeable.
Class Diagram
The Strategy pattern is about swapping logic at runtime. Instead of a single class having one fixed way to perform a task (or using a giant conditional block to choose a method), it delegates the task to a "Strategy" object. The Context doesn't know the specifics of how the work is done; it just knows the Strategy object has an execute() method.
-
Key Components
- Strategy (Interface): A common interface for all supported algorithms.
- Concrete Strategies: These classes implement different variations of an algorithm (e.g., different sorting methods or different payment types).
- Context: Maintains a reference to one of the Strategy objects. It communicates with the strategy via the interface and can have its strategy changed at any time by the client.
-
Why Use It?
- Runtime Switching: You can change an object's behavior while the program is running (e.g., switching from "Fastest Route" to "Avoid Tolls" in a GPS).
- Isolation: You separate the "how-to" (the algorithm) from the "when-to" (the business logic in the context).
- Open/Closed Principle: You can introduce new strategies without changing the Context.
-
Real-World Example
An E-commerce Checkout.- Context: The
ShoppingCart. - Strategy (Interface):
PaymentMethod. - Concrete Strategies:
CreditCardPayment,PayPalPayment,CryptoPayment. - Logic: The
ShoppingCartdoesn't need to contain the code for every payment API in the world. It just asks the chosenPaymentMethodtoprocess(). When the user clicks a different radio button on the website, the app simply swaps the strategy object.
- Context: The
Template Method
The Template Method is a behavioral design pattern that outlines the framework of an algorithm in the superclass, allowing subclasses to override specific steps without altering the overall structure.
Class Diagram
The Template Method pattern is all about defining a fixed process while allowing for flexible details. The base class contains the "template" (a final method) that calls a series of steps in a specific order. Some of these steps are implemented in the base class (common logic), while others are left abstract for subclasses to fill in (specific logic).
-
Key Components
- Abstract Class: Contains the
templateMethod(), which defines the sequence of the algorithm. It also declares "abstract steps" that subclasses must implement. - Concrete Classes: Implement the abstract steps to provide specific behavior. They do not override the template method itself; only its parts.
- Hooks: Optional methods in the base class that have a default (usually empty) implementation. Subclasses can override them to "hook" into the algorithm at specific points if needed.
- Abstract Class: Contains the
-
Why Use It?
- Code Reuse: You write the common "boilerplate" code once in the superclass and only vary the parts that need to change.
- Controlled Extension: It limits where subclasses can intervene in an algorithm, ensuring the core structure remains intact.
- Single Point of Change: If the overall workflow needs to change (e.g., adding a new global step), you only have to update the base class.
-
Real-World Example
Making a Beverage.- Abstract Class: CaffeineBeverage.
- Template Method:
prepareRecipe()(Boil water -> Brew -> Pour in cup -> Add condiments). - Common Steps:
boilWater()andpourInCup()are the same for everything. - Abstract Steps:
brew()andaddCondiments(). - Concrete Classes:
- Coffee: Implements
brew()as "Drip through filter" andaddCondiments()as "Add sugar and milk." - Tea: Implements
brew()as "Steep tea bag" andaddCondiments()as "Add lemon."
- Coffee: Implements
Visitor
Visitor is a behavioral design pattern that separates algorithms from the objects they operate on.
Class Diagram
The Visitor pattern uses a technique called Double Dispatch. Instead of the object knowing how to perform a task, it "accepts" a Visitor. The object then passes itself to the Visitor (visitor.visit(this)). This allows the Visitor to look at the object's specific type and execute the appropriate logic. This way, you can add an infinite number of new "Visitors" (operations) without ever touching the Element classes again.
-
Key Components
- Visitor (Interface): Declares a set of visiting methods, one for each type of concrete element in the object structure.
- Concrete Visitor: Implements different versions of the same algorithm, tailored for all target element classes.
- Element (Interface): Declares an
accept()method that takes a visitor as an argument. - Concrete Element: Implements the
accept()method. It essentially says: "I am Element A, Visitor, please handle me using yourvisitElementAlogic." - ObjectStructure: A collection (like a List or a Tree) that can iterate through its elements and let the visitor "visit" each one.
-
Why Use It?
- Open/Closed Principle: You can define new operations over a complex object structure without changing the classes of the elements.
- Single Responsibility: You can move multiple related behaviors into a single Visitor class rather than spreading them across many element classes.
- Clean Data Classes: It keeps your data-holding classes (Elements) simple, as they don't need to store logic for every possible operation (exporting, auditing, calculating, etc.).
-
Real-World Example
A Tax Inspector visiting different types of businesses.- Elements:
Restaurant,Factory,TechStartup. - Visitor:
TaxInspector. - Logic: Each business "accepts" the inspector. The inspector then applies different tax rules depending on whether they are in a restaurant (food tax), a factory (environmental tax), or a startup (capital gains). If the government introduces a new "Green Audit," you just create a new
GreenAuditorvisitor; you don't need to rewrite the code for the Restaurant or Factory.
- Elements:




















Top comments (0)