The Chain of Responsibility pattern is a behavioral design pattern where a request is passed through a chain of handlers. Each handler decides either to process the request or to pass it to the next handler in the chain.
// Define a handler interface
interface Handler {
void handleRequest(Request request);
void setNextHandler(Handler nextHandler);
}
// Concrete handler 1
class ConcreteHandler1 implements Handler {
private Handler nextHandler;
@Override
public void handleRequest(Request request) {
if (request.getLevel() <= 10) {
System.out.println("Request handled by ConcreteHandler1");
} else if (nextHandler != null) {
nextHandler.handleRequest(request);
} else {
System.out.println("Request cannot be handled");
}
}
@Override
public void setNextHandler(Handler nextHandler) {
this.nextHandler = nextHandler;
}
}
// Concrete handler 2
class ConcreteHandler2 implements Handler {
private Handler nextHandler;
@Override
public void handleRequest(Request request) {
if (request.getLevel() > 10 && request.getLevel() <= 20) {
System.out.println("Request handled by ConcreteHandler2");
} else if (nextHandler != null) {
nextHandler.handleRequest(request);
} else {
System.out.println("Request cannot be handled");
}
}
@Override
public void setNextHandler(Handler nextHandler) {
this.nextHandler = nextHandler;
}
}
// Request class
class Request {
private int level;
public Request(int level) {
this.level = level;
}
public int getLevel() {
return level;
}
}
public class Main {
public static void main(String[] args) {
// Create handlers
Handler handler1 = new ConcreteHandler1();
Handler handler2 = new ConcreteHandler2();
// Set the chain of responsibility
handler1.setNextHandler(handler2);
// Send requests to the chain
handler1.handleRequest(new Request(5));
handler1.handleRequest(new Request(15));
handler1.handleRequest(new Request(25));
}
}
Command
The Command pattern is a behavioral design pattern that encapsulates a request as an object, thereby allowing you to parameterize clients with queues, requests, and operations.
// Command interface
interface Command {
void execute();
}
// Receiver class
class Light {
public void turnOn() {
System.out.println("Light is on");
}
public void turnOff() {
System.out.println("Light is off");
}
}
// Concrete command classes
class TurnOnCommand implements Command {
private Light light;
public TurnOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.turnOn();
}
}
class TurnOffCommand implements Command {
private Light light;
public TurnOffCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.turnOff();
}
}
// Invoker class
class Switch {
private Command turnOnCommand;
private Command turnOffCommand;
public Switch(Command turnOnCommand, Command turnOffCommand) {
this.turnOnCommand = turnOnCommand;
this.turnOffCommand = turnOffCommand;
}
public void turnOn() {
turnOnCommand.execute();
}
public void turnOff() {
turnOffCommand.execute();
}
}
public class Main {
public static void main(String[] args) {
// Create receiver
Light light = new Light();
// Create commands
Command turnOnCommand = new TurnOnCommand(light);
Command turnOffCommand = new TurnOffCommand(light);
// Create invoker
Switch lightSwitch = new Switch(turnOnCommand, turnOffCommand);
// Execute commands
lightSwitch.turnOn();
lightSwitch.turnOff();
}
}
Iterator
The Iterator pattern is a behavioral design pattern that provides a way to access elements of an aggregate object sequentially without exposing its underlying representation.
import java.util.ArrayList;
import java.util.List;
// Iterator interface
interface Iterator<T> {
boolean hasNext();
T next();
}
// Concrete Iterator implementation
class ListIterator<T> implements Iterator<T> {
private List<T> list;
private int index = 0;
public ListIterator(List<T> list) {
this.list = list;
}
@Override
public boolean hasNext() {
return index < list.size();
}
@Override
public T next() {
if (!hasNext()) {
throw new IndexOutOfBoundsException();
}
return list.get(index++);
}
}
// Aggregate interface
interface Aggregate<T> {
Iterator<T> iterator();
}
// Concrete Aggregate implementation
class ListAggregate<T> implements Aggregate<T> {
private List<T> list;
public ListAggregate() {
list = new ArrayList<>();
}
public void add(T item) {
list.add(item);
}
@Override
public Iterator<T> iterator() {
return new ListIterator<>(list);
}
}
public class Main {
public static void main(String[] args) {
ListAggregate<String> aggregate = new ListAggregate<>();
aggregate.add("Item 1");
aggregate.add("Item 2");
aggregate.add("Item 3");
Iterator<String> iterator = aggregate.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
Mediator
The Mediator pattern is a behavioral design pattern that promotes loose coupling by centralizing communication between different objects. Instead of objects communicating directly with each other, they communicate through a mediator object.
import java.util.ArrayList;
import java.util.List;
// Mediator interface
interface Mediator {
void sendMessage(String message, Colleague colleague);
}
// Colleague interface
interface Colleague {
void receiveMessage(String message);
}
// Concrete mediator implementation
class ConcreteMediator implements Mediator {
private List<Colleague> colleagues = new ArrayList<>();
public void addColleague(Colleague colleague) {
colleagues.add(colleague);
}
@Override
public void sendMessage(String message, Colleague colleague) {
for (Colleague c : colleagues) {
if (c != colleague) {
c.receiveMessage(message);
}
}
}
}
// Concrete colleague implementation
class ConcreteColleague implements Colleague {
private Mediator mediator;
public ConcreteColleague(Mediator mediator) {
this.mediator = mediator;
}
public void sendMessage(String message) {
mediator.sendMessage(message, this);
}
@Override
public void receiveMessage(String message) {
System.out.println("Received message: " + message);
}
}
public class Main {
public static void main(String[] args) {
ConcreteMediator mediator = new ConcreteMediator();
ConcreteColleague colleague1 = new ConcreteColleague(mediator);
ConcreteColleague colleague2 = new ConcreteColleague(mediator);
ConcreteColleague colleague3 = new ConcreteColleague(mediator);
mediator.addColleague(colleague1);
mediator.addColleague(colleague2);
mediator.addColleague(colleague3);
colleague1.sendMessage("Hello from colleague 1");
colleague2.sendMessage("Hi from colleague 2");
colleague3.sendMessage("Hey from colleague 3");
}
}
Memento
The Memento pattern is a behavioral design pattern that allows an object to capture its internal state without exposing its implementation details and then restore that state later without violating encapsulation. This pattern is useful when you need to implement undo/redo functionality or maintain checkpoints in an application.
// Originator class
class Originator {
private String state;
public void setState(String state) {
this.state = state;
}
public String getState() {
return state;
}
public Memento saveStateToMemento() {
return new Memento(state);
}
public void getStateFromMemento(Memento memento) {
state = memento.getState();
}
}
// Memento class
class Memento {
private String state;
public Memento(String state) {
this.state = state;
}
public String getState() {
return state;
}
}
// Caretaker class
class Caretaker {
private Memento memento;
public void saveMemento(Memento memento) {
this.memento = memento;
}
public Memento retrieveMemento() {
return memento;
}
}
// Main class
public class Main {
public static void main(String[] args) {
Originator originator = new Originator();
Caretaker caretaker = new Caretaker();
originator.setState("State 1");
caretaker.saveMemento(originator.saveStateToMemento());
originator.setState("State 2");
caretaker.saveMemento(originator.saveStateToMemento());
originator.setState("State 3");
System.out.println("Current state: " + originator.getState());
originator.getStateFromMemento(caretaker.retrieveMemento());
System.out.println("Restored state: " + originator.getState());
}
}
Observer
The Observer pattern is a behavioral design pattern where an object, known as the subject, maintains a list of its dependents, called observers, and notifies them of any state changes, usually by calling one of their methods.
import java.util.ArrayList;
import java.util.List;
// Subject interface
interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers();
}
// Concrete subject class
class ConcreteSubject implements Subject {
private List<Observer> observers = new ArrayList<>();
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
notifyObservers();
}
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(state);
}
}
}
// Observer interface
interface Observer {
void update(int state);
}
// Concrete observer class
class ConcreteObserver implements Observer {
private int observerState;
@Override
public void update(int state) {
observerState = state;
System.out.println("Observer state updated: " + observerState);
}
}
// Main class
public class Main {
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();
ConcreteObserver observer1 = new ConcreteObserver();
ConcreteObserver observer2 = new ConcreteObserver();
subject.registerObserver(observer1);
subject.registerObserver(observer2);
subject.setState(5);
subject.setState(10);
}
}
Command
The State pattern is a behavioral design pattern that allows an object to alter its behavior when its internal state changes. This pattern is useful when an object's behavior depends on its state, and it needs to change its behavior dynamically based on changes to its internal state.
// Context class
class Context {
private State state;
public void setState(State state) {
this.state = state;
}
public void request() {
state.handleRequest();
}
}
// State interface
interface State {
void handleRequest();
}
// Concrete state classes
class ConcreteStateA implements State {
@Override
public void handleRequest() {
System.out.println("Handling request in State A");
}
}
class ConcreteStateB implements State {
@Override
public void handleRequest() {
System.out.println("Handling request in State B");
}
}
// Main class
public class Main {
public static void main(String[] args) {
Context context = new Context();
// Set initial state to State A
context.setState(new ConcreteStateA());
context.request(); // Output: Handling request in State A
// Change state to State B
context.setState(new ConcreteStateB());
context.request(); // Output: Handling request in State B
}
}
Strategy
The Strategy pattern is a behavioral design pattern that enables a client to choose from a family of algorithms at runtime. It defines a family of algorithms, encapsulates each algorithm, and makes them interchangeable. This pattern allows the algorithm to vary independently from the clients that use it.
// Strategy interface
interface PaymentStrategy {
void pay(int amount);
}
// Concrete strategy classes
class CreditCardPayment implements PaymentStrategy {
private String cardNumber;
private String expiryDate;
private String cvv;
public CreditCardPayment(String cardNumber, String expiryDate, String cvv) {
this.cardNumber = cardNumber;
this.expiryDate = expiryDate;
this.cvv = cvv;
}
@Override
public void pay(int amount) {
System.out.println("Paid " + amount + " via credit card.");
}
}
class PayPalPayment implements PaymentStrategy {
private String email;
private String password;
public PayPalPayment(String email, String password) {
this.email = email;
this.password = password;
}
@Override
public void pay(int amount) {
System.out.println("Paid " + amount + " via PayPal.");
}
}
// Context class
class ShoppingCart {
private PaymentStrategy paymentStrategy;
public void setPaymentStrategy(PaymentStrategy paymentStrategy) {
this.paymentStrategy = paymentStrategy;
}
public void checkout(int amount) {
paymentStrategy.pay(amount);
}
}
// Main class
public class Main {
public static void main(String[] args) {
ShoppingCart cart = new ShoppingCart();
// Use credit card payment strategy
cart.setPaymentStrategy(new CreditCardPayment("1234 5678 9012 3456", "12/24", "123"));
cart.checkout(100);
// Use PayPal payment strategy
cart.setPaymentStrategy(new PayPalPayment("example@example.com", "password"));
cart.checkout(50);
}
}