设计模式是面向对象编程中解决特定问题的最佳实践总结。GoF 提出 23 种经典设计模式,按用途分为创建型、结构型和行为型三类。
一、单例模式(Singleton)
确保一个类只有一个实例,并提供全局访问点。
// 双重校验锁(推荐)
public class Singleton {
private static volatile Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
// 枚举实现(最安全,防止反射破坏)
public enum Singleton {
INSTANCE;
public void doSomething() { }
}
二、工厂模式(Factory)
将对象的创建与使用分离,让子类决定实例化哪个类。
// 简单工厂
public class AnimalFactory {
public static Animal create(String type) {
switch (type) {
case "dog": return new Dog();
case "cat": return new Cat();
default: throw new IllegalArgumentException();
}
}
}
// 工厂方法
interface AnimalFactory {
Animal create();
}
class DogFactory implements AnimalFactory {
public Animal create() { return new Dog(); }
}
三、策略模式(Strategy)
定义一系列算法,把它们封装起来,使它们可以互相替换。
// 支付策略接口
interface PaymentStrategy {
void pay(double amount);
}
class AliPay implements PaymentStrategy {
public void pay(double amount) {
System.out.println("支付宝支付: " + amount);
}
}
class WechatPay implements PaymentStrategy {
public void pay(double amount) {
System.out.println("微信支付: " + amount);
}
}
// 上下文
class Order {
private PaymentStrategy strategy;
public void setStrategy(PaymentStrategy s) { this.strategy = s; }
public void checkout(double amount) { strategy.pay(amount); }
}
四、观察者模式(Observer)
定义对象间的一对多依赖,当一个对象状态改变时,所有依赖者自动收到通知。
// JDK 已提供 Observer 接口,也可以用事件监听器方式实现
interface Observer {
void update(String message);
}
class Subject {
private List<Observer> observers = new ArrayList<>();
public void attach(Observer o) { observers.add(o); }
public void detach(Observer o) { observers.remove(o); }
public void notifyAll(String msg) {
for (Observer o : observers) { o.update(msg); }
}
}
五、装饰器模式(Decorator)
动态地给对象添加额外职责,比继承更灵活。
// Java IO 流是装饰器模式的经典应用
// BufferedReader br = new BufferedReader(new FileReader("file.txt"));
interface Coffee { double cost(); }
class SimpleCoffee implements Coffee {
public double cost() { return 10; }
}
class MilkDecorator implements Coffee {
private Coffee coffee;
public MilkDecorator(Coffee c) { this.coffee = c; }
public double cost() { return coffee.cost() + 2; }
}
六、设计模式选择指南
| 场景 | 推荐模式 |
|---|---|
| 全局唯一实例 | 单例模式 |
| 对象创建复杂 | 工厂模式 / 建造者模式 |
| 算法可替换 | 策略模式 |
| 状态变化通知 | 观察者模式 |
| 动态增强功能 | 装饰器模式 |
| 适配不同接口 | 适配器模式 |
七、总结
设计模式不是银弹,不要为了用而用。编写代码时优先考虑可读性和可维护性,当发现代码有明显的"坏味道"时,再思考用设计模式来重构。