Design patterns are proven solutions to common software design problems. Familiarity with design patterns such as Singleton, Factory, and Observer can help you write more efficient and maintainable code.
To learn more about design patterns in Java, visit our article: Design Patterns in Java.
Ensures a class has only one instance and provides a global point of access to it.
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
Defines an interface for creating an object but lets subclasses alter the type of objects that will be created.
public interface Shape {
void draw();
}
public class Circle implements Shape {
public void draw() {
System.out.println("Circle drawn");
}
}
public class ShapeFactory {
public static Shape getShape(String shapeType) {
if (shapeType.equalsIgnoreCase("CIRCLE")) {
return new Circle();
}
return null;
}
}
Provides an interface for creating families of related or dependent objects without specifying their concrete classes.
public interface GUIFactory {
Button createButton();
Checkbox createCheckbox();
}
public class WinFactory implements GUIFactory {
public Button createButton() {
return new WinButton();
}
public Checkbox createCheckbox() {
return new WinCheckbox();
}
}
Separates the construction of a complex object from its representation, allowing the same construction process to create different representations.
public class Pizza {
private String dough;
private String sauce;
private String topping;
public static class Builder {
private String dough;
private String sauce;
private String topping;
public Builder dough(String dough) {
this.dough = dough;
return this;
}
public Builder sauce(String sauce) {
this.sauce = sauce;
return this;
}
public Builder topping(String topping) {
this.topping = topping;
return this;
}
public Pizza build() {
Pizza pizza = new Pizza();
pizza.dough = this.dough;
pizza.sauce = this.sauce;
pizza.topping = this.topping;
return pizza;
}
}
}
Creates new objects by copying an existing object, known as the prototype.
public class Prototype implements Cloneable {
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
Allows incompatible interfaces to work together by converting the interface of a class into another interface that a client expects.
public interface Target {
void request();
}
public class Adaptee {
public void specificRequest() {
System.out.println("Specific request");
}
}
public class Adapter implements Target {
private Adaptee adaptee;
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
public void request() {
adaptee.specificRequest();
}
}
Decouples an abstraction from its implementation so that the two can vary independently.
public interface Implementor {
void operation();
}
public class ConcreteImplementorA implements Implementor {
public void operation() {
System.out.println("ConcreteImplementorA operation");
}
}
public abstract class Abstraction {
protected Implementor implementor;
public Abstraction(Implementor implementor) {
this.implementor = implementor;
}
public abstract void operation();
}
Composes objects into tree structures to represent part-whole hierarchies, allowing clients to treat individual objects and compositions uniformly.
public interface Component {
void operation();
}
public class Leaf implements Component {
public void operation() {
System.out.println("Leaf operation");
}
}
public class Composite implements Component {
private List children = new ArrayList<>();
public void add(Component component) {
children.add(component);
}
public void operation() {
for (Component child : children) {
child.operation();
}
}
}
Attaches additional responsibilities to an object dynamically, providing a flexible alternative to subclassing for extending functionality.
public interface Coffee {
double cost();
}
public class SimpleCoffee implements Coffee {
public double cost() {
return 1.0;
}
}
public class MilkDecorator implements Coffee {
private Coffee coffee;
public MilkDecorator(Coffee coffee) {
this.coffee = coffee;
}
public double cost() {
return coffee.cost() + 0.5;
}
}
Provides a simplified interface to a complex subsystem, making it easier to use.
public class SubsystemA {
public void operationA() {
System.out.println("Subsystem A operation");
}
}
public class SubsystemB {
public void operationB() {
System.out.println("Subsystem B operation");
}
}
public class Facade {
private SubsystemA subsystemA;
private SubsystemB subsystemB;
public Facade() {
subsystemA = new SubsystemA();
subsystemB = new SubsystemB();
}
public void operation() {
subsystemA.operationA();
subsystemB.operationB();
}
}
Uses sharing to support a large number of fine-grained objects efficiently.
public class Flyweight {
private String intrinsicState;
public Flyweight(String intrinsicState) {
this.intrinsicState = intrinsicState;
}
public void operation(String extrinsicState) {
System.out.println("Intrinsic: " + intrinsicState + ", Extrinsic: " + extrinsicState);
}
}
Provides a surrogate or placeholder for another object to control access to it.
public interface Subject {
void request();
}
public class RealSubject implements Subject {
public void request() {
System.out.println("RealSubject request");
}
}
public class Proxy implements Subject {
private RealSubject realSubject;
public void request() {
if (realSubject == null) {
realSubject = new RealSubject();
}
realSubject.request();
}
}
Passes a request along a chain of handlers, allowing multiple handlers to process the request.
public abstract class Handler {
protected Handler next;
public void setNext(Handler next) {
this.next = next;
}
public abstract void handleRequest(int request);
}
public class ConcreteHandlerA extends Handler {
public void handleRequest(int request) {
if (request < 10) {
System.out.println("Handler A handled request " + request);
} else if (next != null) {
next.handleRequest(request);
}
}
}
Encapsulates a request as an object, allowing for parameterization of clients with queues, requests, and operations.
public interface Command {
void execute();
}
public class Light {
public void turnOn() {
System.out.println("Light is ON");
}
public void turnOff() {
System.out.println("Light is OFF");
}
}
public class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
public void execute() {
light.turnOn();
}
}
Defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
public interface Observer {
void update(String message);
}
public class ConcreteObserver implements Observer {
public void update(String message) {
System.out.println("Received message: " + message);
}
}
public class Subject {
private List observers = new ArrayList<>();
public void addObserver(Observer observer) {
observers.add(observer);
}
public void notifyObservers(String message) {
for (Observer observer : observers) {
observer.update(message);
}
}
}
Allows an object to alter its behavior when its internal state changes.
public interface State {
void handle();
}
public class ConcreteStateA implements State {
public void handle() {
System.out.println("Handling state A");
}
}
public class Context {
private State state;
public void setState(State state) {
this.state = state;
}
public void request() {
state.handle();
}
}
Defines a family of algorithms, encapsulates each one, and makes them interchangeable.
public interface Strategy {
int doOperation(int num1, int num2);
}
public class OperationAdd implements Strategy {
public int doOperation(int num1, int num2) {
return num1 + num2;
}
}
public class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public int executeStrategy(int num1, int num2) {
return strategy.doOperation(num1, num2);
}
}
Defines the skeleton of an algorithm in a method, deferring some steps to subclasses.
public abstract class AbstractClass {
public final void templateMethod() {
stepOne();
stepTwo();
}
protected abstract void stepOne();
protected abstract void stepTwo();
}
public class ConcreteClass extends AbstractClass {
protected void stepOne() {
System.out.println("Step One");
}
protected void stepTwo() {
System.out.println("Step Two");
}
}
Represents an operation to be performed on the elements of an object structure.
public interface Visitor {
void visit(Element element);
}
public class ConcreteVisitor implements Visitor {
public void visit(Element element) {
System.out.println("Visiting " + element.getName());
}
}
public interface Element {
void accept(Visitor visitor);
}
public class ConcreteElement implements Element {
private String name;
public ConcreteElement(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
Defines an object that encapsulates how a set of objects interact, promoting loose coupling.
public interface Mediator {
void notify(Component sender, String event);
}
public class ConcreteMediator implements Mediator {
private ComponentA componentA;
private ComponentB componentB;
public void setComponentA(ComponentA componentA) {
this.componentA = componentA;
}
public void setComponentB(ComponentB componentB) {
this.componentB = componentB;
}
public void notify(Component sender, String event) {
if (sender == componentA) {
componentB.doSomething();
} else if (sender == componentB) {
componentA.doSomething();
}
}
}
Passes a request along a chain of handlers, allowing multiple handlers to process the request.
public abstract class Handler {
protected Handler next;
public void setNext(Handler next) {
this.next = next;
}
public abstract void handleRequest(int request);
}
public class ConcreteHandlerA extends Handler {
public void handleRequest(int request) {
if (request < 10) {
System.out.println("Handler A handled request " + request);
} else if (next != null) {
next.handleRequest(request);
}
}
}
Encapsulates a request as an object, allowing for parameterization of clients with queues, requests, and operations.
public interface Command {
void execute();
}
public class Light {
public void turnOn() {
System.out.println("Light is ON");
}
public void turnOff() {
System.out.println("Light is OFF");
}
}
public class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
public void execute() {
light.turnOn();
}
}
Defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
public interface Observer {
void update(String message);
}
public class ConcreteObserver implements Observer {
public void update(String message) {
System.out.println("Received message: " + message);
}
}
public class Subject {
private List observers = new ArrayList<>();
public void addObserver(Observer observer) {
observers.add(observer);
}
public void notifyObservers(String message) {
for (Observer observer : observers) {
observer.update(message);
}
}
}
Allows an object to alter its behavior when its internal state changes.
public interface State {
void handle();
}
public class ConcreteStateA implements State {
public void handle() {
System.out.println("Handling state A");
}
}
public class Context {
private State state;
public void setState(State state) {
this.state = state;
}
public void request() {
state.handle();
}
}
Defines a family of algorithms, encapsulates each one, and makes them interchangeable.
public interface Strategy {
int doOperation(int num1, int num2);
}
public class OperationAdd implements Strategy {
public int doOperation(int num1, int num2) {
return num1 + num2;
}
}
public class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public int executeStrategy(int num1, int num2) {
return strategy.doOperation(num1, num2);
}
}
Defines the skeleton of an algorithm in a method, deferring some steps to subclasses.
public abstract class AbstractClass {
public final void templateMethod() {
stepOne();
stepTwo();
}
protected abstract void stepOne();
protected abstract void stepTwo();
}
public class ConcreteClass extends AbstractClass {
protected void stepOne() {
System.out.println("Step One");
}
protected void stepTwo() {
System.out.println("Step Two");
}
}
Represents an operation to be performed on the elements of an object structure.
public interface Visitor {
void visit(Element element);
}
public class ConcreteVisitor implements Visitor {
public void visit(Element element) {
System.out.println("Visiting " + element.getName());
}
}
public interface Element {
void accept(Visitor visitor);
}
public class ConcreteElement implements Element {
private String name;
public ConcreteElement(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
Defines an object that encapsulates how a set of objects interact, promoting loose coupling.
public interface Mediator {
void notify(Component sender, String event);
}
public class ConcreteMediator implements Mediator {
private ComponentA componentA;
private ComponentB componentB;
public void setComponentA(ComponentA componentA) {
this.componentA = componentA;
}
public void setComponentB(ComponentB componentB) {
this.componentB = componentB;
}
public void notify(Component sender, String event) {
if (sender == componentA) {
componentB.doSomething();
} else if (sender == componentB) {
componentA.doSomething();
}
}
}
Passes a request along a chain of handlers, allowing multiple handlers to process the request.
public abstract class Handler {
protected Handler next;
public void setNext(Handler next) {
this.next = next;
}
public abstract void handleRequest(int request);
}
public class ConcreteHandlerA extends Handler {
public void handleRequest(int request) {
if (request < 10) {
System.out.println("Handler A handled request " + request);
} else if (next != null) {
next.handleRequest(request);
}
}
}
Encapsulates a request as an object, allowing for parameterization of clients with queues, requests, and operations.
public interface Command {
void execute();
}
public class Light {
public void turnOn() {
System.out.println("Light is ON");
}
public void turnOff() {
System.out.println("Light is OFF");
}
}
public class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
public void execute() {
light.turnOn();
}
}
Defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
public interface Observer {
void update(String message);
}
public class ConcreteObserver implements Observer {
public void update(String message) {
System.out.println("Received message: " + message);
}
}
public class Subject {
private List observers = new ArrayList<>();
public void addObserver(Observer observer) {
observers.add(observer);
}
public void notifyObservers(String message) {
for (Observer observer : observers) {
observer.update(message);
}
}
}
Allows an object to alter its behavior when its internal state changes.
public interface State {
void handle();
}
public class ConcreteStateA implements State {
public void handle() {
System.out.println("Handling state A");
}
}
public class Context {
private State state;
public void setState(State state) {
this.state = state;
}
public void request() {
state.handle();
}
}
Defines a family of algorithms, encapsulates each one, and makes them interchangeable.
public interface Strategy {
int doOperation(int num1, int num2);
}
public class OperationAdd implements Strategy {
public int doOperation(int num1, int num2) {
return num1 + num2;
}
}
public class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public int executeStrategy(int num1, int num2) {
return strategy.doOperation(num1, num2);
}
}
Defines the skeleton of an algorithm in a method, deferring some steps to subclasses.
public abstract class AbstractClass {
public final void templateMethod() {
stepOne();
stepTwo();
}
protected abstract void stepOne();
protected abstract void stepTwo();
}
public class ConcreteClass extends AbstractClass {
protected void stepOne() {
System.out.println("Step One");
}
protected void stepTwo() {
System.out.println("Step Two");
}
}
Represents an operation to be performed on the elements of an object structure.
public interface Visitor {
void visit(Element element);
}
public class ConcreteVisitor implements Visitor {
public void visit(Element element) {
System.out.println("Visiting " + element.getName());
}
}
public interface Element {
void accept(Visitor visitor);
}
public class ConcreteElement implements Element {
private String name;
public ConcreteElement(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
Defines an object that encapsulates how a set of objects interact, promoting loose coupling.
public interface Mediator {
void notify(Component sender, String event);
}
public class ConcreteMediator implements Mediator {
private ComponentA componentA;
private ComponentB componentB;
public void setComponentA(ComponentA componentA) {
this.componentA = componentA;
}
public void setComponentB(ComponentB componentB) {
this.componentB = componentB;
}
public void notify(Component sender, String event) {
if (sender == componentA) {
componentB.doSomething();
} else if (sender == componentB) {
componentA.doSomething();
}
}
}
Passes a request along a chain of handlers, allowing multiple handlers to process the request.
public abstract class Handler {
protected Handler next;
public void setNext(Handler next) {
this.next = next;
}
public abstract void handleRequest(int request);
}
public class ConcreteHandlerA extends Handler {
public void handleRequest(int request) {
if (request < 10) {
System.out.println("Handler A handled request " + request);
} else if (next != null) {
next.handleRequest(request);
}
}
}
Encapsulates a request as an object, allowing for parameterization of clients with queues, requests, and operations.
public interface Command {
void execute();
}
public class Light {
public void turnOn() {
System.out.println("Light is ON");
}
public void turnOff() {
System.out.println("Light is OFF");
}
}
public class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
public void execute() {
light.turnOn();
}
}
Defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
public interface Observer {
void update(String message);
}
public class ConcreteObserver implements Observer {
public void update(String message) {
System.out.println("Received message: " + message);
}
}
public class Subject {
private List observers = new ArrayList<>();
public void addObserver(Observer observer) {
observers.add(observer);
}
public void notifyObservers(String message) {
for (Observer observer : observers) {
observer.update(message);
}
}
}
Allows an object to alter its behavior when its internal state changes.
public interface State {
void handle();
}
public class ConcreteStateA implements State {
public void handle() {
System.out.println("Handling state A");
}
}
public class Context {
private State state;
public void setState(State state) {
this.state = state;
}
public void request() {
state.handle();
}
}
Defines a family of algorithms, encapsulates each one, and makes them interchangeable.
public interface Strategy {
int doOperation(int num1, int num2);
}
public class OperationAdd implements Strategy {
public int doOperation(int num1, int num2) {
return num1 + num2;
}
}
public class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public int executeStrategy(int num1, int num2) {
return strategy.doOperation(num1, num2);
}
}
Defines the skeleton of an algorithm in a method, deferring some steps to subclasses.
public abstract class AbstractClass {
public final void templateMethod() {
stepOne();
stepTwo();
}
protected abstract void stepOne();
protected abstract void stepTwo();
}
public class ConcreteClass extends AbstractClass {
protected void stepOne() {
System.out.println("Step One");
}
protected void stepTwo() {
System.out.println("Step Two");
}
}
Represents an operation to be performed on the elements of an object structure.
public interface Visitor {
void visit(Element element);
}
public class ConcreteVisitor implements Visitor {
public void visit(Element element) {
System.out.println("Visiting " + element.getName());
}
}
public interface Element {
void accept(Visitor visitor);
}
public class ConcreteElement implements Element {
private String name;
public ConcreteElement(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
Defines an object that encapsulates how a set of objects interact, promoting loose coupling.
public interface Mediator {
void notify(Component sender, String event);
}
public class ConcreteMediator implements Mediator {
private ComponentA componentA;
private ComponentB componentB;
public void setComponentA(ComponentA componentA) {
this.componentA = componentA;
}
public void setComponentB(ComponentB componentB) {
this.componentB = componentB;
}
public void notify(Component sender, String event) {
if (sender == componentA) {
componentB.doSomething();
} else if (sender == componentB) {
componentA.doSomething();
}
}
}
Passes a request along a chain of handlers, allowing multiple handlers to process the request.
public abstract class Handler {
protected Handler next;
public void setNext(Handler next) {
this.next = next;
}
public abstract void handleRequest(int request);
}
public class ConcreteHandlerA extends Handler {
public void handleRequest(int request) {
if (request < 10) {
System.out.println("Handler A handled request " + request);
} else if (next != null) {
next.handleRequest(request);
}
}
}
Encapsulates a request as an object, allowing for parameterization of clients with queues, requests, and operations.
public interface Command {
void execute();
}
public class Light {
public void turnOn() {
System.out.println("Light is ON");
}
public void turnOff() {
System.out.println("Light is OFF");
}
}
public class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
public void execute() {
light.turnOn();
}
}
Defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
public interface Observer {
void update(String message);
}
public class ConcreteObserver implements Observer {
public void update(String message) {
System.out.println("Received message: " + message);
}
}
public class Subject {
private List observers = new ArrayList<>();
public void addObserver(Observer observer) {
observers.add(observer);
}
public void notifyObservers(String message) {
for (Observer observer : observers) {
observer.update(message);
}
}
}
Allows an object to alter its behavior when its internal state changes.
public interface State {
void handle();
}
public class ConcreteStateA implements State {
public void handle() {
System.out.println("Handling state A");
}
}
public class Context {
private State state;
public void setState(State state) {
this.state = state;
}
public void request() {
state.handle();
}
}
Defines a family of algorithms, encapsulates each one, and makes them interchangeable.
public interface Strategy {
int doOperation(int num1, int num2);
}
public class OperationAdd implements Strategy {
public int doOperation(int num1, int num2) {
return num1 + num2;
}
}
public class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public int executeStrategy(int num1, int num2) {
return strategy.doOperation(num1, num2);
}
}
Defines the skeleton of an algorithm in a method, deferring some steps to subclasses.
public abstract class AbstractClass {
public final void templateMethod() {
stepOne();
stepTwo();
}
protected abstract void stepOne();
protected abstract void stepTwo();
}
public class ConcreteClass extends AbstractClass {
protected void stepOne() {
System.out.println("Step One");
}
protected void stepTwo() {
System.out.println("Step Two");
}
}