对设计模式的详细全面介绍,涵盖核心概念、23种经典设计模式、设计原则、应用场景及学习建议:
一、设计模式基础概念
1. 定义
设计模式(Design Pattern)是解决软件设计中常见问题的可复用方案,它是对代码设计经验的总结,提供了一套被验证的、可扩展的代码结构模板。
2. 核心价值
- 代码复用:避免重复解决相同问题。
- 解耦与扩展性:通过抽象和分层降低模块间依赖。
- 提升可维护性:统一代码结构,便于团队理解和修改。
- 优化性能:部分模式直接解决性能问题(如享元模式)。
3. 设计模式与架构模式的区别
- 设计模式:微观层面的代码结构优化(如单个模块或类的关系)。
- 架构模式:宏观层面的系统结构设计(如MVC、微服务、事件驱动)。
二、GoF 23种经典设计模式详解
根据《设计模式:可复用面向对象软件的基础》(GoF)分类:
(一)创建型模式(5种)
核心目标:解耦对象创建过程,增强灵活性和可控制性。
1. 工厂方法模式(Factory Method)
- 问题:需创建多种类型对象,但不想在代码中硬编码具体类。
- 实现:定义接口创建对象,由子类决定实例化哪个类。
- 示例:
interface Shape { void draw(); } class Circle implements Shape { public void draw() { /*画圆*/ } } class ShapeFactory { public Shape createShape(String type) { if ("circle".equals(type)) return new Circle(); // 其他形状... } }
2. 抽象工厂模式(Abstract Factory)
- 问题:需要创建一组相关或依赖的对象(如不同主题的UI组件)。
- 实现:提供接口创建多个产品族,而非单一产品。
- 示例:
interface GUIFactory { Button createButton(); Checkbox createCheckbox(); } class WindowsFactory implements GUIFactory { /*返回Windows风格组件*/ } class MacFactory implements GUIFactory { /*返回Mac风格组件*/ }
3. 单例模式(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; } }
4. 建造者模式(Builder)
- 问题:构造复杂对象时避免构造函数参数爆炸。
- 实现:分步构建,最后返回完整对象。
- 示例:构建HTTP请求:
Request request = new Request.Builder() .url("https://api.example.com") .method("POST") .header("Content-Type", "application/json") .body("{...}") .build();
5. 原型模式(Prototype)
- 问题:需高效复制复杂对象(如游戏中的敌人克隆)。
- 实现:实现
Cloneable
接口,重写clone()
方法。class Enemy implements Cloneable { private String type; public Enemy clone() { return new Enemy(this.type); // 深拷贝需处理引用对象 } }
(二)结构型模式(7种)
核心目标:通过组合类和对象形成更大的结构。
1. 适配器模式(Adapter)
- 问题:让不兼容的接口协同工作(如旧系统升级)。
- 实现:
- 类适配器:继承旧类实现新接口。
- 对象适配器:持有旧类实例,实现新接口。
// 旧类 class LegacyPrinter { void printDocument() { /*...*/ } } // 适配器 interface ModernPrinter { void print(); } class PrinterAdapter implements ModernPrinter { private LegacyPrinter legacyPrinter; public void print() { legacyPrinter.printDocument(); } }
2. 桥接模式(Bridge)
- 问题:将抽象与实现解耦,使其独立变化(如不同图形API的绘制)。
- 实现:分离抽象层(如形状)和实现层(如渲染引擎)。
interface Renderer { void renderCircle(float radius); } class VectorRenderer implements Renderer { /*矢量渲染*/ } abstract class Shape { protected Renderer renderer; public Shape(Renderer r) { this.renderer = r; } abstract void draw(); } class Circle extends Shape { private float radius; void draw() { renderer.renderCircle(radius); } }
3. 组合模式(Composite)
- 问题:以树形结构处理部分-整体关系(如文件系统)。
- 实现:统一叶子节点和组合节点的接口。
interface FileSystemComponent { void display(); } class File implements FileSystemComponent { /*文件*/ } class Directory implements FileSystemComponent { private List<FileSystemComponent> children = new ArrayList<>(); void add(FileSystemComponent c) { children.add(c); } void display() { children.forEach(FileSystemComponent::display); } }
4. 装饰器模式(Decorator)
- 问题:动态扩展对象功能(如Java I/O流)。
- 实现:包装原有对象,新增职责。
interface Coffee { double getCost(); } class SimpleCoffee implements Coffee { /*基础咖啡*/ } class MilkDecorator implements Coffee { private Coffee coffee; public MilkDecorator(Coffee c) { this.coffee = c; } public double getCost() { return coffee.getCost() + 0.5; } }
5. 外观模式(Facade)
- 问题:简化复杂子系统的调用(如一键启动电脑)。
- 实现:提供统一的高层接口。
class Computer { private CPU cpu; private Memory memory; public void start() { cpu.initialize(); memory.load(); // 其他子系统操作... } }
6. 享元模式(Flyweight)
- 问题:减少大量细粒度对象的内存消耗(如游戏中的树木)。
- 实现:共享对象内部状态,区分外部状态。
class TreeType { private String name, color; TreeType(String name, String color) { /*...*/ } } class TreeFactory { static Map<String, TreeType> pool = new HashMap<>(); static TreeType getTreeType(String name, String color) { String key = name + "_" + color; if (!pool.containsKey(key)) { pool.put(key, new TreeType(name, color)); } return pool.get(key); } }
7. 代理模式(Proxy)
- 问题:控制对象访问(如延迟加载、权限校验)。
- 实现:代理类持有真实对象引用,拦截请求。
interface Image { void display(); } class RealImage implements Image { /*从磁盘加载大图*/ } class ProxyImage implements Image { private RealImage realImage; public void display() { if (realImage == null) realImage = new RealImage(); realImage.display(); } }
(三)行为型模式(11种)
核心目标:优化对象间的通信与责任分配。
1. 责任链模式(Chain of Responsibility)
- 问题:多个对象依次处理请求(如审批流程)。
- 实现:每个处理器决定是否处理或传递请求。
abstract class Handler { protected Handler next; void setNext(Handler next) { this.next = next; } abstract void handleRequest(Request request); } class Manager extends Handler { void handleRequest(Request r) { if (canHandle(r)) { /*处理*/ } else { next.handleRequest(r); } } }
2. 命令模式(Command)
- 问题:将请求封装为对象,支持撤销、队列等操作。
- 实现:分离调用者与执行者。
interface Command { void execute(); } class LightOnCommand implements Command { private Light light; public void execute() { light.on(); } } class RemoteControl { private Command command; public void pressButton() { command.execute(); } }
3. 解释器模式(Interpreter)
- 问题:定义语言的文法规则(如SQL解析)。
- 实现:构建语法树,递归解释表达式。
interface Expression { boolean interpret(String context); } class TerminalExpression implements Expression { private String data; public boolean interpret(String context) { return context.contains(data); } }
4. 迭代器模式(Iterator)
- 问题:统一遍历集合元素的方式。
- 实现:分离集合结构与遍历逻辑。
interface Iterator<T> { boolean hasNext(); T next(); } class ListIterator implements Iterator<String> { private List<String> list; private int index = 0; // 实现hasNext()和next() }
5. 中介者模式(Mediator)
- 问题:减少对象间直接通信的复杂性(如聊天室)。
- 实现:通过中介对象协调多个组件交互。
class ChatRoom { public static void sendMessage(User user, String message) { // 处理消息分发逻辑 } }
6. 备忘录模式(Memento)
- 问题:捕获对象内部状态以实现撤销功能。
- 实现:保存状态快照,由原发器管理。
class Editor { private String content; public EditorMemento save() { return new EditorMemento(content); } public void restore(EditorMemento m) { content = m.getContent(); } }
7. 观察者模式(Observer)
- 问题:实现一对多的依赖通知(如事件监听)。
- 实现:主题维护观察者列表,状态变化时通知。
interface Observer { void update(String message); } class User implements Observer { public void update(String msg) { System.out.println("收到消息: " + msg); } } class NewsPublisher { private List<Observer> observers = new ArrayList<>(); public void addObserver(Observer o) { observers.add(o); } public void notify(String msg) { observers.forEach(o -> o.update(msg)); } }
8. 状态模式(State)
- 问题:对象行为随状态改变(如订单状态流转)。
- 实现:将状态抽象为独立类,委托行为给当前状态。
interface OrderState { void next(Order order); void prev(Order order); } class PaidState implements OrderState { public void next(Order order) { order.setState(new ShippedState()); } // ... }
9. 策略模式(Strategy)
- 问题:动态切换算法(如支付方式选择)。
- 实现:定义算法族,封装每个算法。
interface PaymentStrategy { void pay(int amount); } class CreditCardPayment implements PaymentStrategy { /*...*/ } class PayPalPayment implements PaymentStrategy { /*...*/ } class ShoppingCart { private PaymentStrategy strategy; public void checkout(int amount) { strategy.pay(amount); } }
10. 模板方法模式(Template Method)
- 问题:定义算法骨架,允许子类重写某些步骤。
- 实现:抽象类定义模板方法,子类实现具体步骤。
abstract class Game { abstract void initialize(); abstract void startPlay(); // 模板方法 public final void play() { initialize(); startPlay(); endPlay(); } }
11. 访问者模式(Visitor)
- 问题:在不修改类的前提下为类添加新操作(如代码分析工具)。
- 实现:通过访问者对象处理不同元素。
interface Visitor { void visit(ElementA element); void visit(ElementB element); } class ConcreteVisitor implements Visitor { /*实现各元素的处理方法*/ }
三、设计原则(SOLID)
设计模式的基础是面向对象设计原则:
- 单一职责原则(SRP):一个类只负责一个功能领域。
- 开闭原则(OCP):对扩展开放,对修改关闭。
- 里氏替换原则(LSP):子类必须能替换父类。
- 接口隔离原则(ISP):客户端不应依赖不需要的接口。
- 依赖倒置原则(DIP):依赖抽象而非具体实现。
四、设计模式的应用与陷阱
正确应用场景
- 识别问题:明确代码痛点(如对象创建复杂、模块耦合度高)。
- 选择模式:根据问题类型匹配模式(创建型/结构型/行为型)。
- 适度使用:避免过度设计,简单代码优于复杂模式。
常见陷阱
- 单例滥用:导致全局状态污染,难以测试。
- 过度抽象:增加代码复杂度,降低可读性。
- 模式误用:如用工厂模式创建简单对象。
五、学习路线与资源
学习路径
- 入门:理解设计原则(SOLID) → 学习常用模式(如工厂、观察者、策略)。
- 进阶:掌握23种GoF模式 → 分析框架源码(如Spring、JDK)。
- 实战:在项目中重构代码应用模式 → 总结优化经验。
推荐资源
- 书籍:
- 《Head First设计模式》(入门首选)
- 《设计模式:可复用面向对象软件的基础》(GoF经典)
- 《重构:改善既有代码的设计》
设计模式是软件工程中的“内功心法”,深入理解并合理运用能显著提升代码质量。但切记:没有银弹,结合具体场景灵活选择才是王道。