Table of Contents
Creational Patterns
Patterns that abstract the object instantiation process.
1. Abstract Factory
Concept: Create families of related or dependent objects without specifying concrete classes.
interface GUIFactory {
fun createButton(): Button
fun createCheckbox(): Checkbox
}
class MacGUIFactory : GUIFactory {
override fun createButton(): Button { return MacButton() }
override fun createCheckbox(): Checkbox { return MacCheckbox() }
}
class WindowsGUIFactory : GUIFactory {
override fun createButton(): Button { return WindowsButton() }
override fun createCheckbox(): Checkbox { return WindowsCheckbox() }
}
interface Button {
fun paint()
}
class MacButton : Button {
override fun paint() { System.out.println("Mac Button"); }
}
class WindowsButton implements Button {
public void paint() { System.out.println("Windows Button"); }
}
interface Checkbox {
fun check()
}
class MacCheckbox : Checkbox {
override fun check() { System.out.println("Mac Checkbox"); }
}
class WindowsCheckbox : Checkbox {
override fun check() { System.out.println("Windows Checkbox"); }
}
// Usage:
val factory = MacGUIFactory()
val button = factory.createButton()
val checkbox = factory.createCheckbox()
button.paint()
checkbox.check()
2. Builder
Concept: Separate object construction from representation.
class House {
private final String walls;
private final String roof;
private House(Builder b) {
this.walls = b.walls;
this.roof = b.roof;
}
static class Builder {
private String walls;
private String roof;
Builder walls(String walls) { ... }
Builder roof(String roofType) { ... }
House build() { ... }
}
// Usage:
House house = new House.Builder().walls("Brick").roof("Tiles").build();3. Factory Method
Concept: Factory method delegates instance creation to subclasses. This differs from the Abstract Factory pattern where the factory itself is instantiated by the client and then passed to the factory method.
interface Shape { void draw(); }
class Circle implements Shape { public void draw(){...} }
class ShapeFactory {
Shape createShape(String type) {
if(type.equals("circle")) return new Circle();
else return new Square();
}
// Usage:
Shape shape = factory.createShape("circle");
4. Prototype
Concept: Create new objects by cloning existing ones.
interface Prototype {
fun clone(): Prototype
}
class Concrete : Prototype {
override fun clone(): Prototype { return ConcretePrototype(this) }
}
// Usage:
val p1 = Concrete()
val copy = p1.clone()5. Singleton
Concept: Ensure only one instance of a class is created.
class Singleton private constructor() {
companion object {
val instance = Singleton()
}
}
// Usage:
val s = Singleton.instanceStructural Patterns
Patterns that ease design by identifying relationships between entities.
1. Adapter
Concept: Bridge incompatible interfaces.
interface MediaPlayer {
fun play()
}
class MP3Player : MediaPlayer {
override fun play() { println("Playing MP3") }
}
class MP4Adapter : MediaPlayer {
val mp3 = MP3Player()
override fun play() { mp3.play() }
}
// Usage:
val player = MP4Adapter()
player.play()
2. Facade
Concept: Provide simplified interface for complex subsystems.
class HomeTheaterFacade {
val projector = Projector()
val amplifier = Amplifier()
fun watchMovie() {
projector.on()
amplifier.on()
}
fun endMovie() {
projector.off()
amplifier.off()
}
}
// Usage:
val theater = HomeTheaterFacade()
theater.watchMovie()
theater.endMovie()3. Decorator
Concept: Add responsibilities dynamically.
interface Coffee {
fun cost(): Int
}
class Espresso : Coffee {
override fun cost(): Int { return 2 }
}
class MilkDecorator : Coffee {
val coffee: Coffee
constructor(coffee: Coffee) { this.coffee = coffee }
override fun cost(): Int { return coffee.cost() + 1 }
}
class SweetnerDecorator : Coffee {
val coffee: Coffee
constructor(coffee: Coffee) { this.coffee = coffee }
override fun cost(): Int { return coffee.cost() + 1 }
}
// Usage:
val coffee = SweetnerDecorator(MilkDecorator(Espresso()))
println(coffee.cost())
val coffee2 = MilkDecorator(Espresso())
println(coffee2.cost())4. Bridge
Concept: Decouple abstraction from implementation and hide implementation details from client.
interface Color {
void applyColor();
}
// Concrete Implementor
class RedColor implements Color {
public void applyColor() { System.out.println("Applying Red"); }
}
class BlueColor implements Color {
public void applyColor() { System.out.println("Applying Blue"); }
}
// Abstraction
abstract class Shape {
protected Color color;
Shape(Color c) { this.color = c; }
abstract void draw();
}
class Circle extends Shape {
Circle(Color c) { super(c); }
public void draw() { System.out.println("Drawing Circle"); }
}
class Square extends Shape {
Square(Color c) { super(c); }
public void draw() { System.out.println("Drawing Square"); }
}
// Usage:
val redCircle = Circle(RedColor())
redCircle.draw()
val blueCircle = Circle(BlueColor())
blueCircle.draw()
val redSquare = Square(RedColor())
redSquare.draw()
val blueSquare = Square(BlueColor())
blueSquare.draw()5. Composite
Concept: Compose objects into tree structures to represent part-whole hierarchies.
interface Component { void display(); }
class Leaf implements Component {
String name;
Leaf(String name) { this.name = name; }
public void display() { System.out.println(name); }
}
class Composite implements Component {
List<Component> components = new ArrayList<>();
void add(Component c) { components.add(c); }
public void display() { components.forEach(Component::display); }
}
// Usage:
Composite root = new Composite();
root.add(new Leaf("Leaf 1"));
Composite sub = new Composite();
sub.add(new Leaf("Leaf A"));
root.add(sub);
root.display();
6. Proxy
Concept: Provide a surrogate or placeholder for another object to control access to it.
interface Internet { void connect(); }
class RealInternet implements Internet {
public void connect() { System.out.println("Connected to Internet."); }
}
class ProxyInternet implements Internet {
RealInternet real;
String user;
Proxy(String user) { this.user = user; }
public void connect() {
if (userHasAccess())
new RealInternet().connect();
else
System.out.println("Access Denied!");
}
}
// Usage:
Internet internet = new ProxyInternet("guest");
internet.connect();
7. Flyweight
Concept: Share objects to reduce memory usage.
interface Shape { void draw(int x, int y); }
class Circle implements Shape {
String color;
Circle(String color) { this.color = color; }
public void draw(int x, int y) {
System.out.println(color + " circle at " + x + ", " + y);
}
}
class ShapeFactory {
static Map<String, Shape> shapes = new HashMap<>();
static Shape getCircle(String color) {
return shapes.computeIfAbsent(color, Circle::new);
}
}
// Usage:
Shape red = factory.getCircle("Red");
red.draw(10, 20);
Shape anotherRed = factory.getCircle("Red"); // reuses previous object
anotherRed.draw(20, 40);
Structural Patterns
Patterns that compose classes or objects into larger structures.
- Adapter
- Bridge
- Composite
- Decorator
- Facade
- Flyweight
- Proxy
Behavioral Patterns
Patterns defining object interactions and responsibilities between objects.
1. Strategy
Concept: Encapsulate interchangeable behaviors and allow them to be used interchangeably.
interface PaymentStrategy { fun pay(amount: Int) }
class CreditCardPayment : PaymentStrategy {
override fun pay(amount: Int) { System.out.println("Paid by Credit"); }
}
class PaypalPayment : PaymentStrategy {
override fun pay(amount: Int) { System.out.println("Paid by Paypal"); }
}
// Usage:
val payment = Payment(CreditCardPayment())
payment.execute()
val payment2 = Payment(PaypalPayment())
payment2.execute()
2. Observer
Concept: Notify objects about changes in state of another object.
interface Observer { fun update() }
class WeatherStation {
val observers = mutableListOf<Observer>()
fun addObserver(observer: Observer) { observers.add(observer) }
fun notifyObservers() { observers.forEach(Observer::update) }
}
class WeatherObserver : Observer {
override fun update() { println("Weather updated") }
}
// Usage:
val weatherStation = WeatherStation()
val weatherObserver = WeatherObserver()
weatherStation.addObserver(weatherObserver)
weatherStation.notifyObservers()
3. Strategy
Concept: Encapsulate algorithms, interchangeable.
interface SortStrategy { fun sort() }
class QuickSort : SortStrategy {
override fun sort() { println("Quick sorting") }
}
class Context(strategy: SortStrategy) {
fun execute() { strategy.sort() }
}
// Usage:
val ctx = Context(QuickSort())
ctx.execute()
4. Chain of Responsibility
Concept: Chain commands together.
interface Handler {
fun handle(request: String)
fun setNext(handler: Handler)
}
class ConcreteHandler1 : Handler {
var next: Handler? = null
override fun handle(request: String) { println("ConcreteHandler1 handled request") }
override fun setNext(handler: Handler) { next = handler }
}
class ConcreteHandler2 : Handler {
var next: Handler? = null
override fun handle(request: String) { println("ConcreteHandler2 handled request") }
override fun setNext(handler: Handler) { next = handler }
}
// Usage:
val handler1 = ConcreteHandler1()
val handler2 = ConcreteHandler2()
handler1.setNext(handler2)
handler1.handle("request")
5. Command
Concept: Encapsulate a request as an object and pass it to the invoker.
interface Command { fun execute() }
class ConcreteCommand : Command {
override fun execute() { println("ConcreteCommand executed") }
}
class Invoker {
val command: Command
constructor(command: Command) { this.command = command }
fun run() { command.execute() }
}
// Usage:
val invoker = Invoker(ConcreteCommand())
invoker.run()
6. Interpreter
Concept: Define a grammar for a language and implement an interpreter to parse sentences in the language.
interface Expression { fun interpret() }
class TerminalExpression : Expression {
override fun interpret() { println("TerminalExpression interpreted") }
}
class NonTerminalExpression : Expression {
override fun interpret() { println("NonTerminalExpression interpreted") }
}
// Usage:
val expression = NonTerminalExpression()
expression.interpret()
7. Iterator
Concept: Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.
interface Iterator { fun next(): Any? }
class ConcreteIterator : Iterator {
override fun next(): Any? { return null }
}
// Usage:
val iterator = ConcreteIterator()
iterator.next()
8. Mediator
Concept: Define an object that encapsulates how a set of objects interact.
interface Mediator { fun send(message: String) }
class ConcreteMediator : Mediator {
override fun send(message: String) { println("Mediator sent message: $message") }
}
// Usage:
val mediator = ConcreteMediator()
mediator.send("Hello")
9. Memento
Concept: Capture and restore an object’s state.
interface Memento { fun getState(): String }
class ConcreteMemento : Memento {
override fun getState(): String { return "State" }
}
// Usage:
val memento = ConcreteMemento()
memento.getState()
10. State
Concept: Allow an object to change its behavior when its internal state changes.
interface State { fun handle() }
class ConcreteState : State {
override fun handle() { println("ConcreteState handled") }
}
// Usage:
val state = ConcreteState()
state.handle()
11. Template Method
Concept: Define the program skeleton of an algorithm in a method, deferring some steps to subclasses.
abstract class Game {
abstract fun initialize()
abstract fun startPlay()
abstract fun endPlay()
}
class Cricket : Game {
override fun initialize() { println("Cricket Game Initialized! Start playing.") }
override fun startPlay() { println("Cricket Game Started. Enjoy the game!") }
override fun endPlay() { println("Cricket Game Finished!") }
}
// Usage:
val game = Cricket()
game.play()
12. Visitor
Concept: Represent an operation to be performed on the elements of an object structure.
interface Visitor { fun visit(element: Element) }
class ConcreteVisitor : Visitor {
override fun visit(element: Element) { println("ConcreteVisitor visited element") }
}
// Usage:
val visitor = ConcreteVisitor()
visitor.visit(Element())
Behavioral Patterns (Full list)
- Chain of Responsibility
- Command
- Interpreter
- Iterator
- Mediator
- Memento
- Observer
- State
- Strategy
- Template Method
- Visitor
Summary
| Creational | Structural | Behavioral |
|---|---|---|
| Abstract Factory | Adapter | Chain of Responsibility |
| Builder | Bridge | Command |
| Factory Method | Composite | Interpreter |
| Prototype | Decorator | Iterator |
| Singleton | Facade | Mediator |
| Decorator | Memento | |
| Flyweight | Observer | |
| Facade | State | |
| Proxy | Strategy | |
| Flyweight | Template Method | |
| Proxy | Visitor |
Why always me?