一、创建型模式(Creation Patterns)
1. 单例模式(Singleton)
- 核心思想:保证一个类仅有一个实例,并提供全局访问点。
- 实现方式:
public class Singleton { // 1. 私有静态实例,volatile 保证多线程可见性 private static volatile Singleton instance; // 2. 私有构造方法 private Singleton() {} // 3. 双重检查锁定(Double-Checked Locking) public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
- 场景:
- 数据库连接池(全局唯一,避免重复创建连接)
- 配置管理类(如读取配置文件)
- 优点:节省内存,避免重复创建对象。
- 缺点:需处理多线程安全问题,可能违反单一职责原则。
2. 工厂方法模式(Factory Method)
- 核心思想:定义一个创建对象的接口,但由子类决定实例化哪个类。
- 代码示例:
// 抽象产品 interface Product { void use(); } // 具体产品A class ConcreteProductA implements Product { public void use() { System.out.println("Using Product A"); } } // 抽象工厂 abstract class Creator { public abstract Product createProduct(); } // 具体工厂A class ConcreteCreatorA extends Creator { public Product createProduct() { return new ConcreteProductA(); } }
- 场景:
- 日志记录器(不同日志类型:文件、数据库)
- 跨平台UI组件(不同操作系统创建不同按钮)
- 优点:解耦客户端代码与具体类,扩展性强。
- 缺点:每新增一个产品,需新增一个工厂类。
3. 抽象工厂模式(Abstract Factory)
- 核心思想:创建一组相关或依赖的对象族(例如同一主题下的所有UI组件)。
- 代码示例:
// 抽象产品族:按钮和文本框 interface Button { void render(); } interface TextBox { void input(); } // Windows 风格产品 class WindowsButton implements Button { public void render() { System.out.println("Windows Button"); } } class WindowsTextBox implements TextBox { public void input() { System.out.println("Windows TextBox"); } } // 抽象工厂接口 interface GUIFactory { Button createButton(); TextBox createTextBox(); } // Windows 工厂 class WindowsFactory implements GUIFactory { public Button createButton() { return new WindowsButton(); } public TextBox createTextBox() { return new WindowsTextBox(); } }
- 场景:
- 跨平台应用开发(同一套UI在不同操作系统下表现不同)
- 游戏中的不同风格资源包(如科幻 vs 中世纪)
- 优点:保证产品族的兼容性。
- 缺点:新增产品族需要修改所有工厂类。
4. 建造者模式(Builder)
- 核心思想:分步骤构造复杂对象,允许不同表示形式。
- 代码示例:
class Computer { private String CPU; private String RAM; // 其他组件... // 建造者内部类 public static class Builder { private String CPU; private String RAM; public Builder setCPU(String cpu) { this.CPU = cpu; return this; // 链式调用 } public Builder setRAM(String ram) { this.RAM = ram; return this; } public Computer build() { Computer computer = new Computer(); computer.CPU = this.CPU; computer.RAM = this.RAM; return computer; } } } // 使用 Computer computer = new Computer.Builder() .setCPU("Intel i7") .setRAM("32GB") .build();
- 场景:
- 生成复杂对象(如HTML文档、SQL查询)
- 链式调用配置参数(如Retrofit、OkHttp的配置)
- 优点:封装对象的构造过程,支持灵活扩展。
- 缺点:代码量增加,适合构造复杂对象。
5. 原型模式(Prototype)
- 核心思想:通过克隆现有对象创建新对象,避免重复初始化。
- 代码示例:
class Prototype implements Cloneable { private String data; public Prototype(String data) { this.data = data; } @Override public Prototype clone() { try { return (Prototype) super.clone(); } catch (CloneNotSupportedException e) { return null; } } } // 使用 Prototype original = new Prototype("Original Data"); Prototype copy = original.clone();
- 场景:
- 游戏中的敌人复制(避免重复初始化属性)
- 对象初始化成本高(如数据库数据克隆)
- 优点:性能优化,绕过构造方法。
- 缺点:深拷贝与浅拷贝需谨慎处理。
二、结构型模式(Structural Patterns)
6. 适配器模式(Adapter)
- 核心思想:将一个接口转换成客户端期望的另一个接口。
- 代码示例:
// 旧接口(不兼容) class LegacyPrinter { void printDocument(String text) { System.out.println("Legacy Printer: " + text); } } // 新接口 interface ModernPrinter { void print(String content); } // 适配器类 class PrinterAdapter implements ModernPrinter { private LegacyPrinter legacyPrinter = new LegacyPrinter(); public void print(String content) { legacyPrinter.printDocument(content); } }
- 场景:
- 旧系统接口适配新系统
- 第三方库的接口封装
- 优点:复用旧代码,解决接口不兼容。
- 缺点:过多适配器会增加代码复杂度。
7. 装饰器模式(Decorator)
- 核心思想:动态地为对象添加职责(不修改原有类)。
- 代码示例:
// 基础组件 interface Coffee { double getCost(); String getDescription(); } // 具体组件 class SimpleCoffee implements Coffee { public double getCost() { return 1.0; } public String getDescription() { return "Simple Coffee"; } } // 装饰器基类 abstract class CoffeeDecorator implements Coffee { protected Coffee decoratedCoffee; public CoffeeDecorator(Coffee coffee) { this.decoratedCoffee = coffee; } } // 具体装饰器:加牛奶 class MilkDecorator extends CoffeeDecorator { public MilkDecorator(Coffee coffee) { super(coffee); } public double getCost() { return decoratedCoffee.getCost() + 0.5; } public String getDescription() { return decoratedCoffee.getDescription() + ", Milk"; } } // 使用 Coffee coffee = new MilkDecorator(new SimpleCoffee());
- 场景:
- Java IO流(如
BufferedReader
包装FileReader
) - Web请求的过滤器链
- Java IO流(如
- 优点:比继承更灵活,支持运行时扩展。
- 缺点:多层装饰可能导致代码复杂。
8. 代理模式(Proxy)
- 核心思想:控制对对象的访问(延迟加载、权限控制等)。
- 代码示例:
interface Image { void display(); } // 真实对象(高成本) class RealImage implements Image { private String filename; public RealImage(String filename) { this.filename = filename; loadFromDisk(); } private void loadFromDisk() { System.out.println("Loading image: " + filename); } public void display() { System.out.println("Displaying image: " + filename); } } // 代理类(延迟加载) class ProxyImage implements Image { private RealImage realImage; private String filename; public ProxyImage(String filename) { this.filename = filename; } public void display() { if (realImage == null) { realImage = new RealImage(filename); } realImage.display(); } }
- 场景:
- 虚拟代理(如图片延迟加载)
- 保护代理(如权限验证)
- 远程代理(如RPC调用)
- 优点:解耦客户端与真实对象,增强控制。
- 缺点:可能引入性能开销。
三、行为型模式(Behavioral Patterns)
9. 观察者模式(Observer)
- 核心思想:定义对象间的一对多依赖关系,当一个对象状态改变时,自动通知依赖它的对象。
- 代码示例:
// 主题(被观察者) interface Subject { void registerObserver(Observer o); void removeObserver(Observer o); void notifyObservers(); } // 具体主题(例如天气数据) class WeatherData implements Subject { private List<Observer> observers = new ArrayList<>(); private float temperature; public void setTemperature(float temp) { this.temperature = temp; notifyObservers(); } public void registerObserver(Observer o) { observers.add(o); } public void removeObserver(Observer o) { observers.remove(o); } public void notifyObservers() { for (Observer o : observers) { o.update(temperature); } } } // 观察者接口 interface Observer { void update(float temperature); } // 具体观察者(例如显示设备) class DisplayDevice implements Observer { public void update(float temperature) { System.out.println("Current Temperature: " + temperature); } }
- 场景:
- 事件驱动系统(如GUI按钮点击事件)
- 发布-订阅模型(如消息队列)
- 优点:解耦主题与观察者,支持广播通信。
- 缺点:观察者过多时可能影响性能。
10. 策略模式(Strategy)
- 核心思想:定义一系列算法,使其可以相互替换,且算法的变化独立于客户端。
- 代码示例:
// 策略接口 interface PaymentStrategy { void pay(int amount); } // 具体策略:信用卡支付 class CreditCardPayment implements PaymentStrategy { public void pay(int amount) { System.out.println("Paid " + amount + " via Credit Card"); } } // 上下文类(使用策略) class ShoppingCart { private PaymentStrategy strategy; public void setPaymentStrategy(PaymentStrategy strategy) { this.strategy = strategy; } public void checkout(int amount) { strategy.pay(amount); } } // 使用 ShoppingCart cart = new ShoppingCart(); cart.setPaymentStrategy(new CreditCardPayment()); cart.checkout(100);
- 场景:
- 支付方式选择(支付宝、微信、银行卡)
- 排序算法切换(快速排序、归并排序)
- 优点:避免多重条件判断,易于扩展新算法。
- 缺点:客户端必须理解不同策略的区别。
11. 责任链模式(Chain of Responsibility)
- 核心思想:将请求沿着处理链传递,直到有一个处理者处理它。
- 代码示例:
abstract class Handler { protected Handler nextHandler; public void setNext(Handler handler) { this.nextHandler = handler; } public abstract void handleRequest(int request); } // 具体处理者A class ConcreteHandlerA extends Handler { public void handleRequest(int request) { if (request <= 10) { System.out.println("Handler A processes request " + request); } else if (nextHandler != null) { nextHandler.handleRequest(request); } } } // 使用 Handler chain = new ConcreteHandlerA(); chain.setNext(new ConcreteHandlerB()); chain.handleRequest(5); // 由A处理 chain.handleRequest(20); // 由B处理
- 场景:
- Web框架的过滤器链(如Spring Security)
- 审批流程(如请假申请的多级审批)
- 优点:动态调整处理链,解耦发送者和接收者。
- 缺点:请求可能未被处理。
四、如何实际应用设计模式?
- 核心原则:先理解问题,再选择模式,避免为了用模式而用模式。
- 常见误区:
- 过度设计:简单问题强行套用复杂模式。
- 模式混用:多个模式叠加导致代码混乱。
- 学习建议:
- 从简单模式入手(如工厂、单例、观察者)。
- 结合开源框架(如Spring、JDK源码)学习模式的应用。
- 在重构中实践模式,逐步替换旧代码。
希望这些详细的解释和代码示例能帮助你深入理解设计模式!如果需要某个模式的进一步扩展,可以告诉我。