Master Core Design Patterns: Factory, Singleton, Decorator, Strategy, Proxy, Observer
This article explains six essential software design patterns—Factory, Singleton, Decorator, Strategy, Proxy, and Observer—covering their concepts, structure, advantages, drawbacks, typical use cases, and provides concise Java code examples for each.
Introduction
Design patterns help optimize code structure, making it more elegant and flexible. This article introduces common patterns such as Factory, Singleton, Decorator, Strategy, Proxy, and Observer, explaining their concepts, structure, advantages, drawbacks, typical use cases, and simple Java implementations.
1. Factory Pattern
The Factory pattern provides an interface for creating objects without specifying the exact concrete class.
Simple Factory
Analogy: ordering a cappuccino—any coffee shop (the factory) can produce the drink regardless of brand.
Factory : responsible for creating all product instances.
Product : abstract product interface shared by all concrete products.
ConcreteProduct : concrete implementation of a product.
Advantages : decouples client from concrete classes, easy to add new products. Disadvantages : factory must change when products change.
Typical use case : database connection factories such as SqlSessionFactory.
package FactoryMethod;
public class FactoryPattern {
public static void main(String[] args) {
Factory factory = new ConcreteFactoryA();
Product product = factory.createProduct();
product.use();
}
}
interface Product {
void use();
}
class ConcreteProductA implements Product {
public void use() {
System.out.println("Concrete product A...");
}
}
class ConcreteProductB implements Product {
public void use() {
System.out.println("Concrete product B...");
}
}
interface Factory {
Product createProduct();
}
class ConcreteFactoryA implements Factory {
public Product createProduct() {
System.out.println("ConcreteFactoryA creates -> ConcreteProductA.");
return new ConcreteProductA();
}
}
class ConcreteFactoryB implements Factory {
public Product createProduct() {
System.out.println("ConcreteFactoryB creates -> ConcreteProductB.");
return new ConcreteProductB();
}
}2. Singleton Pattern
The Singleton pattern ensures a class has only one instance and provides a global access point to it.
Singleton : the sole instance.
Advantages : global unique instance, reduces resource consumption. Disadvantages : no abstraction layer, hard to extend.
Typical use case : global ID generator, configuration manager.
public class Singleton {
private static volatile Singleton instance = null;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}3. Decorator Pattern
The Decorator pattern adds responsibilities to objects dynamically without affecting other objects.
Component : abstract component.
ConcreteComponent : concrete component.
Decorator : abstract decorator that holds a component.
ConcreteDecorator : adds behavior.
Advantages : more flexible than inheritance, allows runtime composition. Disadvantages : many small decorator classes can increase complexity.
Typical use case : adding features to UI components, I/O streams.
package decorator;
public class DecoratorPattern {
public static void main(String[] args) {
Component component = new ConcreteComponent();
component.operation();
System.out.println("---------------------------------");
Component decorator = new ConcreteDecorator(component);
decorator.operation();
}
}
interface Component {
void operation();
}
class ConcreteComponent implements Component {
public ConcreteComponent() {
System.out.println("Creating concrete component");
}
public void operation() {
System.out.println("Concrete component operation");
}
}
class Decorator implements Component {
protected Component component;
public Decorator(Component component) {
this.component = component;
}
public void operation() {
component.operation();
}
}
class ConcreteDecorator extends Decorator {
public ConcreteDecorator(Component component) {
super(component);
}
public void operation() {
super.operation();
addBehavior();
}
public void addBehavior() {
System.out.println("Adding extra behavior");
}
}4. Strategy Pattern
The Strategy pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable.
Context : uses a Strategy.
Strategy : abstract algorithm interface.
ConcreteStrategy : concrete algorithm implementation.
Advantages : adheres to Open/Closed principle, eliminates complex conditional statements. Disadvantages : client must know all available strategies.
Typical use case : selecting different sorting algorithms at runtime.
package strategy;
public class StrategyPattern {
public static void main(String[] args) {
Context context = new Context();
Strategy strategyA = new ConcreteStrategyA();
context.setStrategy(strategyA);
context.algorithm();
System.out.println("-----------------");
Strategy strategyB = new ConcreteStrategyB();
context.setStrategy(strategyB);
context.algorithm();
}
}
interface Strategy {
void algorithm();
}
class ConcreteStrategyA implements Strategy {
public void algorithm() {
System.out.println("Concrete Strategy A executed");
}
}
class ConcreteStrategyB implements Strategy {
public void algorithm() {
System.out.println("Concrete Strategy B executed");
}
}
class Context {
private Strategy strategy;
public Strategy getStrategy() { return strategy; }
public void setStrategy(Strategy strategy) { this.strategy = strategy; }
public void algorithm() { strategy.algorithm(); }
}5. Proxy Pattern
The Proxy pattern provides a surrogate or placeholder for another object to control access to it.
Subject : abstract subject.
RealSubject : the real object.
Proxy : controls access to RealSubject.
Advantages : reduces coupling, can add security, lazy loading, logging, etc. Disadvantages : adds an extra level of indirection, may affect performance.
Typical use case : remote proxies, virtual proxies, access control.
package proxy;
public class ProxyPattern {
public static void main(String[] args) {
Proxy proxy = new Proxy();
proxy.request();
}
}
interface Subject {
void request();
}
class RealSubject implements Subject {
public void request() {
System.out.println("Real subject request");
}
}
class Proxy implements Subject {
private RealSubject realSubject;
public void request() {
if (realSubject == null) {
realSubject = new RealSubject();
}
preRequest();
realSubject.request();
afterRequest();
}
private void preRequest() { System.out.println("Pre-processing"); }
private void afterRequest() { System.out.println("Post-processing"); }
}6. Observer Pattern
The Observer pattern defines a one‑to‑many dependency so that when one object changes state, all its dependents are notified and updated automatically.
Subject : the observable.
ConcreteSubject : concrete implementation of Subject.
Observer : abstract observer.
ConcreteObserver : concrete observer implementation.
Advantages : decouples subject from observers, promotes reusable components. Disadvantages : potential overhead when many observers exist.
Typical use case : event handling, UI updates, notification systems.
package observer;
import java.util.*;
public class ObserverPattern {
public static void main(String[] args) {
Subject subject = new ConcreteSubject();
Observer obsA = new ConcreteObserverA();
Observer obsB = new ConcreteObserverB();
subject.add(obsA);
subject.add(obsB);
subject.setState(0);
}
}
abstract class Subject {
protected List<Observer> observers = new ArrayList<>();
public void add(Observer o) { observers.add(o); }
public void remove(Observer o) { observers.remove(o); }
public abstract void notifyObservers();
}
class ConcreteSubject extends Subject {
private int state;
public void setState(int s) { this.state = s; notifyObservers(); }
public void notifyObservers() {
System.out.println("Subject state changed...");
for (Observer o : observers) { o.process(); }
}
}
interface Observer { void process(); }
class ConcreteObserverA implements Observer {
public void process() { System.out.println("Observer A processing"); }
}
class ConcreteObserverB implements Observer {
public void process() { System.out.println("Observer B processing"); }
}Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Alibaba Cloud Developer
Alibaba's official tech channel, featuring all of its technology innovations.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
