1. 设计模式全景概述
设计模式是软件开发中针对常见问题的经典解决方案,它们不是具体代码实现,而是经过验证的最佳实践模板。23种设计模式最早由GoF(Gang of Four)在《设计模式:可复用面向对象软件的基础》一书中系统提出,至今仍是软件工程领域的基石知识。
这些模式分为三大类:创建型(5种)、结构型(7种)和行为型(11种)。创建型模式处理对象创建机制,结构型模式处理类和对象的组合,行为型模式处理对象间的交互和职责分配。掌握这些模式能显著提升代码的可维护性、可扩展性和复用性。
提示:设计模式不是银弹,过度使用会导致代码过度设计。应根据实际场景合理选择。
2. 创建型模式详解
2.1 单例模式(Singleton)
确保一个类只有一个实例,并提供全局访问点。适用于需要控制资源(如数据库连接池)或共享配置的场景。
java复制public class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
常见实现方式:
- 饿汉式:类加载时就初始化(线程安全但可能浪费资源)
- 懒汉式:首次调用时初始化(需处理线程安全问题)
- 双重检查锁:兼顾性能和线程安全
- 静态内部类:利用类加载机制保证线程安全
注意:在分布式系统中,单例可能需要在每个JVM中都创建实例,此时需要考虑集群环境下的单例实现。
2.2 工厂方法模式(Factory Method)
定义一个创建对象的接口,但让子类决定实例化哪个类。工厂方法使类的实例化延迟到子类。
适用场景:
- 创建逻辑复杂,需要封装
- 需要支持多种产品类型
- 希望解耦客户端代码和具体实现
java复制interface Product {
void use();
}
class ConcreteProductA implements Product {
public void use() {
System.out.println("Using Product A");
}
}
abstract class Creator {
public abstract Product factoryMethod();
public void someOperation() {
Product product = factoryMethod();
product.use();
}
}
class ConcreteCreatorA extends Creator {
public Product factoryMethod() {
return new ConcreteProductA();
}
}
2.3 抽象工厂模式(Abstract Factory)
提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
与工厂方法的区别:
- 工厂方法:创建单一产品
- 抽象工厂:创建产品族
java复制interface GUIFactory {
Button createButton();
Checkbox createCheckbox();
}
class WinFactory implements GUIFactory {
public Button createButton() {
return new WinButton();
}
public Checkbox createCheckbox() {
return new WinCheckbox();
}
}
class MacFactory implements GUIFactory {
public Button createButton() {
return new MacButton();
}
public Checkbox createCheckbox() {
return new MacCheckbox();
}
}
2.4 建造者模式(Builder)
将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。
适用场景:
- 对象包含多个组成部分
- 需要不同的对象表示
- 创建过程需要分步骤进行
java复制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("16GB")
.build();
2.5 原型模式(Prototype)
通过复制现有对象来创建新对象,而不是通过new关键字。
实现方式:
- 浅拷贝:复制基本类型字段,引用类型字段共享
- 深拷贝:完全复制所有字段
java复制class Prototype implements Cloneable {
private String field;
private List<String> list;
@Override
public Prototype clone() {
try {
Prototype clone = (Prototype) super.clone();
clone.list = new ArrayList<>(this.list); // 深拷贝list
return clone;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
}
3. 结构型模式详解
3.1 适配器模式(Adapter)
将一个类的接口转换成客户希望的另一个接口,使原本不兼容的类可以一起工作。
实现方式:
- 类适配器:通过继承实现
- 对象适配器:通过组合实现
java复制// 目标接口
interface Target {
void request();
}
// 需要适配的类
class Adaptee {
void specificRequest() {
System.out.println("Specific request");
}
}
// 适配器
class Adapter implements Target {
private Adaptee adaptee;
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
public void request() {
adaptee.specificRequest();
}
}
3.2 桥接模式(Bridge)
将抽象部分与实现部分分离,使它们可以独立变化。
适用场景:
- 避免抽象和实现之间的永久绑定
- 抽象和实现都应能通过子类化扩展
- 实现部分的改动不应影响客户端代码
java复制// 实现部分接口
interface Implementor {
void operationImpl();
}
// 具体实现A
class ConcreteImplementorA implements Implementor {
public void operationImpl() {
System.out.println("Implementation A");
}
}
// 抽象部分
abstract class Abstraction {
protected Implementor implementor;
public Abstraction(Implementor implementor) {
this.implementor = implementor;
}
public abstract void operation();
}
// 扩展抽象部分
class RefinedAbstraction extends Abstraction {
public RefinedAbstraction(Implementor implementor) {
super(implementor);
}
public void operation() {
implementor.operationImpl();
}
}
3.3 组合模式(Composite)
将对象组合成树形结构以表示"部分-整体"的层次结构,使得用户对单个对象和组合对象的使用具有一致性。
java复制interface Component {
void operation();
void add(Component c);
void remove(Component c);
Component getChild(int i);
}
class Leaf implements Component {
public void operation() {
System.out.println("Leaf operation");
}
public void add(Component c) {
throw new UnsupportedOperationException();
}
public void remove(Component c) {
throw new UnsupportedOperationException();
}
public Component getChild(int i) {
throw new UnsupportedOperationException();
}
}
class Composite implements Component {
private List<Component> children = new ArrayList<>();
public void operation() {
for (Component child : children) {
child.operation();
}
}
public void add(Component c) {
children.add(c);
}
public void remove(Component c) {
children.remove(c);
}
public Component getChild(int i) {
return children.get(i);
}
}
3.4 装饰器模式(Decorator)
动态地给一个对象添加一些额外的职责,就增加功能来说,装饰器模式比生成子类更为灵活。
java复制interface Component {
void operation();
}
class ConcreteComponent implements Component {
public void operation() {
System.out.println("Basic operation");
}
}
abstract class Decorator implements Component {
protected Component component;
public Decorator(Component component) {
this.component = component;
}
public void operation() {
component.operation();
}
}
class ConcreteDecoratorA extends Decorator {
public ConcreteDecoratorA(Component component) {
super(component);
}
public void operation() {
super.operation();
addedBehavior();
}
private void addedBehavior() {
System.out.println("Added behavior A");
}
}
3.5 外观模式(Facade)
为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
java复制class SubsystemA {
void operationA() {
System.out.println("Subsystem A operation");
}
}
class SubsystemB {
void operationB() {
System.out.println("Subsystem B operation");
}
}
class Facade {
private SubsystemA subsystemA;
private SubsystemB subsystemB;
public Facade() {
subsystemA = new SubsystemA();
subsystemB = new SubsystemB();
}
public void operation() {
subsystemA.operationA();
subsystemB.operationB();
}
}
3.6 享元模式(Flyweight)
运用共享技术有效地支持大量细粒度的对象。
实现要点:
- 内部状态:可以共享的部分
- 外部状态:不可共享的部分
java复制class Flyweight {
private String intrinsicState;
public Flyweight(String intrinsicState) {
this.intrinsicState = intrinsicState;
}
public void operation(String extrinsicState) {
System.out.println("Intrinsic: " + intrinsicState);
System.out.println("Extrinsic: " + extrinsicState);
}
}
class FlyweightFactory {
private Map<String, Flyweight> flyweights = new HashMap<>();
public Flyweight getFlyweight(String key) {
if (!flyweights.containsKey(key)) {
flyweights.put(key, new Flyweight(key));
}
return flyweights.get(key);
}
}
3.7 代理模式(Proxy)
为其他对象提供一种代理以控制对这个对象的访问。
常见代理类型:
- 远程代理:为远程对象提供本地代表
- 虚拟代理:根据需要创建开销大的对象
- 保护代理:控制对原始对象的访问
- 智能引用:在访问对象时执行附加操作
java复制interface Subject {
void request();
}
class RealSubject implements Subject {
public void request() {
System.out.println("RealSubject request");
}
}
class Proxy implements Subject {
private RealSubject realSubject;
public void request() {
if (realSubject == null) {
realSubject = new RealSubject();
}
preRequest();
realSubject.request();
postRequest();
}
private void preRequest() {
System.out.println("Pre request");
}
private void postRequest() {
System.out.println("Post request");
}
}
4. 行为型模式详解
4.1 责任链模式(Chain of Responsibility)
使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。
java复制abstract class Handler {
protected Handler successor;
public void setSuccessor(Handler successor) {
this.successor = successor;
}
public abstract void handleRequest(Request request);
}
class ConcreteHandlerA extends Handler {
public void handleRequest(Request request) {
if (canHandle(request)) {
// 处理请求
} else if (successor != null) {
successor.handleRequest(request);
}
}
private boolean canHandle(Request request) {
// 判断是否能处理
return true;
}
}
4.2 命令模式(Command)
将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
java复制interface Command {
void execute();
}
class ConcreteCommand implements Command {
private Receiver receiver;
public ConcreteCommand(Receiver receiver) {
this.receiver = receiver;
}
public void execute() {
receiver.action();
}
}
class Receiver {
public void action() {
System.out.println("Receiver action");
}
}
class Invoker {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void executeCommand() {
command.execute();
}
}
4.3 解释器模式(Interpreter)
给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
适用场景:
- 需要解释执行的语言
- 文法比较简单
- 效率不是关键问题
java复制interface Expression {
boolean interpret(String context);
}
class TerminalExpression implements Expression {
private String data;
public TerminalExpression(String data) {
this.data = data;
}
public boolean interpret(String context) {
return context.contains(data);
}
}
class OrExpression implements Expression {
private Expression expr1;
private Expression expr2;
public OrExpression(Expression expr1, Expression expr2) {
this.expr1 = expr1;
this.expr2 = expr2;
}
public boolean interpret(String context) {
return expr1.interpret(context) || expr2.interpret(context);
}
}
4.4 迭代器模式(Iterator)
提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。
java复制interface Iterator<T> {
boolean hasNext();
T next();
}
interface Aggregate<T> {
Iterator<T> createIterator();
}
class ConcreteAggregate<T> implements Aggregate<T> {
private List<T> items = new ArrayList<>();
public Iterator<T> createIterator() {
return new ConcreteIterator<T>(this);
}
public int size() {
return items.size();
}
public T get(int index) {
return items.get(index);
}
public void add(T item) {
items.add(item);
}
}
class ConcreteIterator<T> implements Iterator<T> {
private ConcreteAggregate<T> aggregate;
private int index = 0;
public ConcreteIterator(ConcreteAggregate<T> aggregate) {
this.aggregate = aggregate;
}
public boolean hasNext() {
return index < aggregate.size();
}
public T next() {
if (hasNext()) {
return aggregate.get(index++);
}
throw new NoSuchElementException();
}
}
4.5 中介者模式(Mediator)
用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
java复制interface Mediator {
void notify(Component sender, String event);
}
class ConcreteMediator implements Mediator {
private ComponentA componentA;
private ComponentB componentB;
public void setComponentA(ComponentA componentA) {
this.componentA = componentA;
}
public void setComponentB(ComponentB componentB) {
this.componentB = componentB;
}
public void notify(Component sender, String event) {
if (sender == componentA && event.equals("A")) {
componentB.reactOnA();
} else if (sender == componentB && event.equals("B")) {
componentA.reactOnB();
}
}
}
abstract class Component {
protected Mediator mediator;
public Component(Mediator mediator) {
this.mediator = mediator;
}
}
class ComponentA extends Component {
public ComponentA(Mediator mediator) {
super(mediator);
}
public void doA() {
System.out.println("ComponentA does A");
mediator.notify(this, "A");
}
public void reactOnB() {
System.out.println("ComponentA reacts on B");
}
}
4.6 备忘录模式(Memento)
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
java复制class Originator {
private String state;
public void setState(String state) {
this.state = state;
}
public String getState() {
return state;
}
public Memento saveStateToMemento() {
return new Memento(state);
}
public void getStateFromMemento(Memento memento) {
state = memento.getState();
}
}
class Memento {
private String state;
public Memento(String state) {
this.state = state;
}
public String getState() {
return state;
}
}
class CareTaker {
private List<Memento> mementoList = new ArrayList<>();
public void add(Memento state) {
mementoList.add(state);
}
public Memento get(int index) {
return mementoList.get(index);
}
}
4.7 观察者模式(Observer)
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
java复制interface Subject {
void registerObserver(Observer o);
void removeObserver(Observer o);
void notifyObservers();
}
interface Observer {
void update(float temp, float humidity, float pressure);
}
class WeatherData implements Subject {
private List<Observer> observers;
private float temperature;
private float humidity;
private float pressure;
public WeatherData() {
observers = new ArrayList<>();
}
public void registerObserver(Observer o) {
observers.add(o);
}
public void removeObserver(Observer o) {
observers.remove(o);
}
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(temperature, humidity, pressure);
}
}
public void measurementsChanged() {
notifyObservers();
}
public void setMeasurements(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
}
class CurrentConditionsDisplay implements Observer {
private float temperature;
private float humidity;
private Subject weatherData;
public CurrentConditionsDisplay(Subject weatherData) {
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
public void update(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
display();
}
public void display() {
System.out.println("Current conditions: " + temperature + "F degrees and " + humidity + "% humidity");
}
}
4.8 状态模式(State)
允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。
java复制interface State {
void handle(Context context);
}
class ConcreteStateA implements State {
public void handle(Context context) {
System.out.println("State A handling");
context.setState(new ConcreteStateB());
}
}
class ConcreteStateB implements State {
public void handle(Context context) {
System.out.println("State B handling");
context.setState(new ConcreteStateA());
}
}
class Context {
private State state;
public Context(State state) {
this.state = state;
}
public void setState(State state) {
this.state = state;
}
public void request() {
state.handle(this);
}
}
4.9 策略模式(Strategy)
定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
java复制interface Strategy {
int doOperation(int num1, int num2);
}
class OperationAdd implements Strategy {
public int doOperation(int num1, int num2) {
return num1 + num2;
}
}
class OperationSubtract implements Strategy {
public int doOperation(int num1, int num2) {
return num1 - num2;
}
}
class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public int executeStrategy(int num1, int num2) {
return strategy.doOperation(num1, num2);
}
}
4.10 模板方法模式(Template Method)
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
java复制abstract class AbstractClass {
// 模板方法
public final void templateMethod() {
primitiveOperation1();
primitiveOperation2();
concreteOperation();
hook();
}
// 基本方法 - 抽象方法
protected abstract void primitiveOperation1();
// 基本方法 - 抽象方法
protected abstract void primitiveOperation2();
// 基本方法 - 具体方法
private void concreteOperation() {
// 实现代码
}
// 基本方法 - 钩子方法
protected void hook() {}
}
class ConcreteClass extends AbstractClass {
protected void primitiveOperation1() {
// 实现代码
}
protected void primitiveOperation2() {
// 实现代码
}
protected void hook() {
// 可选覆盖
}
}
4.11 访问者模式(Visitor)
表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
java复制interface Element {
void accept(Visitor visitor);
}
class ConcreteElementA implements Element {
public void accept(Visitor visitor) {
visitor.visit(this);
}
public String operationA() {
return "ConcreteElementA";
}
}
interface Visitor {
void visit(ConcreteElementA element);
void visit(ConcreteElementB element);
}
class ConcreteVisitor implements Visitor {
public void visit(ConcreteElementA element) {
System.out.println("Visitor processing " + element.operationA());
}
public void visit(ConcreteElementB element) {
System.out.println("Visitor processing " + element.operationB());
}
}
5. 设计模式应用实践
5.1 模式选择指南
选择设计模式时考虑以下因素:
- 问题本质:明确要解决的问题是什么
- 变化点:识别系统中哪些部分可能会变化
- 解耦需求:需要降低哪些组件间的耦合度
- 复用性:如何提高代码的复用性
- 扩展性:系统未来可能的扩展方向
常见场景与模式对应:
- 对象创建复杂 → 工厂、建造者
- 需要统一接口 → 适配器、外观
- 算法可替换 → 策略
- 状态影响行为 → 状态
- 一对多通知 → 观察者
5.2 模式组合使用
实际项目中常组合使用多个模式:
-
MVC架构:
- 观察者模式(Model-View关系)
- 策略模式(Controller的可替换算法)
- 组合模式(View的层次结构)
-
复杂对象创建:
- 抽象工厂创建产品族
- 建造者构造复杂对象
- 原型模式克隆已有配置
5.3 反模式与滥用
常见设计模式误用:
- 过度设计:在不必要的地方使用模式
- 模式嵌套过深:导致代码难以理解
- 违反单一职责:一个类承担过多模式角色
- 忽视简单方案:能用简单代码解决却硬套模式
经验法则:当模式能真正解决痛点时才使用,而不是为了使用模式而使用。
5.4 性能考量
设计模式对性能的影响:
- 享元模式:减少对象数量,节省内存
- 代理模式:增加间接访问的开销
- 装饰器模式:多层嵌套可能影响性能
- 观察者模式:通知所有观察者需要时间
优化建议:
- 对于性能敏感部分,权衡模式带来的抽象代价
- 考虑延迟初始化(如虚拟代理)
- 使用对象池管理享元对象
- 异步处理观察者通知
6. 设计模式面试精要
6.1 高频面试题解析
-
单例模式的线程安全实现
- 双重检查锁的volatile必要性
- 静态内部类实现原理
- 枚举单例的优势
-
工厂方法与抽象工厂区别
- 工厂方法:单一产品层次结构
- 抽象工厂:产品族创建
- 抽象工厂常使用工厂方法实现
-
装饰器与代理模式区别
- 装饰器:增强功能
- 代理:控制访问
- 结构相似但意图不同
-
观察者模式的推拉模型
- 推模型:主题将详细数据发送给观察者
- 拉模型:观察者从主题拉取所需数据
- 各有利弊,根据场景选择
6.2 设计题目思路
-
设计停车场系统
- 状态模式:车辆进出状态
- 策略模式:计费策略
- 观察者模式:空位通知
-
设计咖啡店订单系统
- 装饰器模式:添加配料
- 工厂方法:创建不同咖啡
- 命令模式:订单处理
-
设计电梯控制系统
- 状态模式:电梯运行状态
- 责任链:楼层请求处理
- 观察者:楼层显示更新
6.3 代码审查要点
审查设计模式实现时关注:
- 单一职责:每个类/方法只做一件事
- 开闭原则:对扩展开放,对修改关闭
- 依赖倒置:依赖抽象而非具体实现
- 接口隔离:客户端不应依赖不需要的接口
- 迪米特法则:最少知识原则
常见坏味道:
- 模式类承担过多职责
- 模式嵌套过深难以理解
- 违反里氏替换原则
- 过度使用继承而非组合
7. 设计模式演进趋势
7.1 函数式编程影响
现代语言对设计模式的影响:
- 策略模式 → 函数作为参数
java复制
Collections.sort(list, (a, b) -> a.compareTo(b)); - 模板方法 → 高阶函数
- 观察者模式 → 响应式流(RxJava等)
7.2 微服务架构中的模式
分布式系统中的模式应用:
- 服务发现 → 抽象工厂
- 熔断机制 → 状态模式
- API网关 → 外观模式
- 事件溯源 → 观察者+备忘录
7.3 领域驱动设计结合
DDD中的模式应用:
- 聚合根 → 组合模式
- 领域事件 → 观察者
- 规约模式 → 策略
- 工厂 → 领域对象创建
7.4 设计模式新趋势
- 模式组合:更复杂的模式交互
- 模式简化:语言特性替代传统实现
- 并发模式:响应式、Actor模型
- 云原生模式:Sidecar、Adapter微服务模式
个人体会:设计模式的核心思想比具体实现更重要。随着语言演进,模式实现方式在变,但其背后的设计原则永恒。
