Java 中的 23 种设计模式详解
Java中的23种设计模式
文章目录
- Java中的23种设计模式
- 一、创建型模式(Creational Patterns)
- 1.1 单例模式(Singleton Pattern)
- 1.2 原型模式(Prototype Pattern)
- 1.3 建造者模式(Builder Pattern)
- 1.4 工厂方法模式(Factory Method Pattern)
- 1.5 抽象工厂模式(Abstract Factory Pattern)
- 二、结构型模式(Structural Patterns)
- 2.1 适配器模式(Adapter Pattern)
- 2.2 桥接模式(Bridge Pattern)
- 2.3 组合模式(Composite Pattern)
- 2.4 装饰器模式(Decorator Pattern)
- 2.5 外观模式(Facade Pattern)
- 2.6 享元模式(Flyweight Pattern)
- 2.7 代理模式(Proxy Pattern)
- 三、行为型模式(Behavioral Patterns)
- 3.1 责任链模式(Chain of Responsibility Pattern)
- 3.2 命令模式(Command Pattern)
- 3.3 迭代器模式(Iterator Pattern)
- 3.4 中介者模式(Mediator Pattern)
- 3.5 备忘录模式(Memento Pattern)
- 3.6 解释器模式(Interpreter Pattern)
- 3.7 状态模式(State Pattern)
- 3.8 策略模式(Strategy Pattern)
- 3.9 模板方法模式(Template Method Pattern)
- 3.10 访问者模式(Visitor Pattern)
- 3.11 观察者模式(Observer Pattern)
- 总结
设计模式是软件开发中的最佳实践,帮助开发者在面对复杂设计问题时提供有效的解决方案。GoF(Gang of Four)在其经典著作《设计模式:可复用面向对象软件的基础》中定义了 23 种设计模式。。本文将详细介绍23种经典设计模式,包括创建型模式、结构型模式和行为型模式,提供每种模式的定义、原理、优点、Java示例代码以及详细注释。
一、创建型模式(Creational Patterns)
创建型模式关注于对象的创建,提供了更灵活的对象创建方式。
1.1 单例模式(Singleton Pattern)
核心思想:确保一个类只有一个实例,并提供一个全局访问点。
实现方式:通过私有化构造函数和提供一个静态方法来获取实例。
应用场景:数据库连接池、配置管理类、日志记录器。
优点:
- 控制实例数量:保证只有一个实例。
- 提供全局访问点:方便在全局范围内访问该实例。
Java 示例:
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;}
}
双重检查(Double-Check) 概念对于多线程开发者来说不会陌生,进行了两次if (instance == null)
检查,这样就可以保证线程安全。实例化代码只需执行一次,后面再次访问时,判断if (instance == null)
,直接return实例化对象。
更多拓展:
Java 设计模式之单例模式
1.2 原型模式(Prototype Pattern)
核心思想:通过复制现有的实例来创建新实例,而不是通过构造函数。
实现方式:实现 Cloneable
接口并重写 clone()
方法来复制对象。
应用场景:游戏角色复制、避免重复初始化开销。
优点:
- 减少创建新对象的开销:通过复制现有对象创建新对象。
- 动态配置对象:可以在运行时配置对象状态。
Java 示例:
// 原型接口
public interface Prototype extends Cloneable {Prototype clone();
}// 具体原型类
public class ConcretePrototype implements Prototype {private String data;public ConcretePrototype(String data) {this.data = data;}// 使用浅拷贝@Overridepublic Prototype clone() {try {return (Prototype) super.clone();} catch (CloneNotSupportedException e) {// 处理克隆不支持异常return null;}}public String getData() {return data;}public void setData(String data) {this.data = data;}
}// 客户端代码
public class Client {public static void main(String[] args) {ConcretePrototype prototype = new ConcretePrototype("Prototype Data");ConcretePrototype clonedPrototype = (ConcretePrototype) prototype.clone();System.out.println(clonedPrototype.getData()); // 输出: Prototype DataclonedPrototype.setData("Modified Data");System.out.println(prototype.getData()); // 输出: Prototype DataSystem.out.println(clonedPrototype.getData()); // 输出: Modified Data}
}
⚠️ 注意:示例中的
String
是不可变类型,修改字符串时实际上是创建了新对象,因此不会影响原对象。但如果字段是可变对象(如集合、数组、自定义类),浅拷贝可能会导致引用共享,带来潜在副作用,此时应考虑使用深拷贝。
1.3 建造者模式(Builder Pattern)
核心思想:使用多个简单的对象一步一步构建一个复杂的对象。
实现方式:定义一个建造者接口和具体建造者类,通过建造者类来创建复杂对象。
应用场景:StringBuilder、AlertDialog.Builder。
优点:
- 解耦:将复杂对象的构建与表示解耦。
- 灵活性:可以根据需要创建不同表示的复杂对象。
Java 示例:
// 产品类
public class Product {private String partA;private String partB;// 构造函数public Product(String partA, String partB) {this.partA = partA;this.partB = partB;}@Overridepublic String toString() {return "Product [partA=" + partA + ", partB=" + partB + "]";}
}// 建造者接口
public interface Builder {void buildPartA();void buildPartB();Product getResult();
}// 具体建造者类
public class ConcreteBuilder implements Builder {private String partA;private String partB;@Overridepublic void buildPartA() {partA = "Part A";}@Overridepublic void buildPartB() {partB = "Part B";}@Overridepublic Product getResult() {return new Product(partA, partB);}
}// 指导者类
public class Director {private Builder builder;public Director(Builder builder) {this.builder = builder;}public void construct() {builder.buildPartA();builder.buildPartB();}
}// 客户端代码
public class Client {public static void main(String[] args) {Builder builder = new ConcreteBuilder();Director director = new Director(builder);director.construct();Product product = builder.getResult();System.out.println(product);}
}
1.4 工厂方法模式(Factory Method Pattern)
核心思想:定义一个创建对象的接口,但由子类决定实例化哪个类。
实现方式:将对象的创建逻辑放在子类中,而不是在客户端代码中。
应用场景:日志记录器(文件/数据库日志)、跨平台 UI 组件。
优点:
- 灵活性:可以在运行时决定创建对象的类型。
- 符合开闭原则:对扩展开放,对修改关闭。
Java 示例:
// 产品接口
public interface Product {void operation();
}// 具体产品A
public class ConcreteProductA implements Product {@Overridepublic void operation() {System.out.println("ConcreteProductA operation");}
}// 具体产品B
public class ConcreteProductB implements Product {@Overridepublic void operation() {System.out.println("ConcreteProductB operation");}
}// 工厂接口
public abstract class Creator {public abstract Product factoryMethod();
}// 具体工厂A
public class ConcreteCreatorA extends Creator {@Overridepublic Product factoryMethod() {return new ConcreteProductA();}
}// 具体工厂B
public class ConcreteCreatorB extends Creator {@Overridepublic Product factoryMethod() {return new ConcreteProductB();}
}// 客户端代码
public class Client {public static void main(String[] args) {Creator creator = new ConcreteCreatorA();Product product = creator.factoryMethod();product.operation();}
}
更多拓展:
Java 设计模式之工厂模式
1.5 抽象工厂模式(Abstract Factory Pattern)
核心思想:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
实现方式:通过定义多个工厂接口,每个接口负责创建一组相关的对象。
应用场景:跨平台 UI 组件库(如 Windows/MacOS 风格的按钮和文本框)。
与工厂方法的区别:工厂方法关注单一产品,抽象工厂处理产品族。
优点:
- 一致性:确保创建的一系列对象具有一致性。
- 扩展性:易于扩展产品系列,而不影响现有代码。
Java 示例:
// 产品A接口
public interface ProductA {void operationA();
}// 产品B接口
public interface ProductB {void operationB();
}// 具体产品A1
public class ConcreteProductA1 implements ProductA {@Overridepublic void operationA() {System.out.println("ConcreteProductA1 operationA");}
}// 具体产品B1
public class ConcreteProductB1 implements ProductB {@Overridepublic void operationB() {System.out.println("ConcreteProductB1 operationB");}
}// 具体产品A2
public class ConcreteProductA2 implements ProductA {@Overridepublic void operationA() {System.out.println("ConcreteProductA2 operationA");}
}// 具体产品B2
public class ConcreteProductB2 implements ProductB {@Overridepublic void operationB() {System.out.println("ConcreteProductB2 operationB");}
}// 抽象工厂接口
public interface AbstractFactory {ProductA createProductA();ProductB createProductB();
}// 具体工厂1
public class ConcreteFactory1 implements AbstractFactory {@Overridepublic ProductA createProductA() {return new ConcreteProductA1();}@Overridepublic ProductB createProductB() {return new ConcreteProductB1();}
}// 具体工厂2
public class ConcreteFactory2 implements AbstractFactory {@Overridepublic ProductA createProductA() {return new ConcreteProductA2();}@Overridepublic ProductB createProductB() {return new ConcreteProductB2();}
}// 客户端代码
public class Client {public static void main(String[] args) {AbstractFactory factory = new ConcreteFactory1();ProductA productA = factory.createProductA();ProductB productB = factory.createProductB();productA.operationA();productB.operationB();}
}
二、结构型模式(Structural Patterns)
结构型模式关注如何将类或对象组合成更大的结构,以便更好地实现功能。
2.1 适配器模式(Adapter Pattern)
核心思想:将一个类的接口转换成客户希望的另一个接口。适配器模式使得原本接口不兼容的类可以合作。
实现方式:通过引入一个适配器类,将目标接口转换为适配者接口。
应用场景:旧系统改造、第三方库集成。
优点:
- 接口兼容:使得接口不兼容的类可以协作。
- 复用性:可以复用现有的类。
Java 示例:
// 目标接口
public interface Target {void request();
}// 适配者类
public class Adaptee {public void specificRequest() {System.out.println("SpecificRequest");}
}// 适配器类
public class Adapter implements Target {private Adaptee adaptee;public Adapter(Adaptee adaptee) {this.adaptee = adaptee;}@Overridepublic void request() {adaptee.specificRequest(); // 适配方法}
}// 客户端代码
public class Client {public static void main(String[] args) {Adaptee adaptee = new Adaptee();Target target = new Adapter(adaptee);target.request(); // 通过适配器调用}
}
2.2 桥接模式(Bridge Pattern)
核心思想:将抽象部分与实现部分分离,使它们可以独立地变化。
实现方式:通过定义抽象类和实现类,将它们的变化解耦。
应用场景:不同图形API(OpenGL/Vulkan)与形状(圆/方)的组合。
优点:
- 解耦:抽象和实现的解耦,使得它们可以独立变化。
- 灵活性:可以独立地扩展抽象和实现。
Java 示例:
// 实现接口
public interface Implementor {void operation();
}// 具体实现A
public class ConcreteImplementorA implements Implementor {@Overridepublic void operation() {System.out.println("ConcreteImplementorA operation");}
}// 具体实现B
public class ConcreteImplementorB implements Implementor {@Overridepublic void operation() {System.out.println("ConcreteImplementorB operation");}
}// 抽象类
public abstract class Abstraction {protected Implementor implementor;public Abstraction(Implementor implementor) {this.implementor = implementor;}public abstract void operation();
}// 扩展抽象类
public class RefinedAbstraction extends Abstraction {public RefinedAbstraction(Implementor implementor) {super(implementor);}@Overridepublic void operation() {implementor.operation(); // 委托给实现类}
}// 客户端代码
public class Client {public static void main(String[] args) {Implementor implementorA = new ConcreteImplementorA();Abstraction abstraction = new RefinedAbstraction(implementorA);abstraction.operation();Implementor implementorB = new ConcreteImplementorB();abstraction = new RefinedAbstraction(implementorB);abstraction.operation();}
}
更多拓展:
Java 设计模式之桥接模式
2.3 组合模式(Composite Pattern)
核心思想:将对象组合成树形结构以表示部分-整体层次结构,使得客户端对单个对象和组合对象的使用具有一致性。
实现方式:通过定义一个组件接口,将叶子节点和容器节点统一处理。
应用场景:文件系统(文件/文件夹统一处理)、UI 容器组件)。
优点:
- 一致性:对单个对象和组合对象的一致性操作。
- 简化客户端代码:客户端代码可以统一处理叶子节点和容器节点。
Java 示例:
import java.util.ArrayList;
import java.util.List;// 组件接口
public interface Component {void operation();
}// 叶子节点
public class Leaf implements Component {@Overridepublic void operation() {System.out.println("Leaf operation");}
}// 容器节点
public class Composite implements Component {private List<Component> children = new ArrayList<>();public void add(Component component) {children.add(component);}public void remove(Component component) {children.remove(component);}@Overridepublic void operation() {for (Component child : children) {child.operation();}}
}// 客户端代码
public class Client {public static void main(String[] args) {Composite root = new Composite();Component leaf1 = new Leaf();Component leaf2 = new Leaf();root.add(leaf1);root.add(leaf2);root.operation(); // 统一调用}
}
2.4 装饰器模式(Decorator Pattern)
核心思想:动态地给一个对象添加一些额外的职责。装饰器模式提供了比继承更灵活的扩展功能的方式。
实现方式:通过定义装饰器类来扩展被装饰对象的功能。
应用场景:Java I/O 流(BufferedInputStream 包装 FileInputStream)。
优点:
- 灵活性:可以动态地扩展对象的功能。
- 避免子类爆炸:通过装饰器而不是继承来扩展功能。
Java 示例:
// 组件接口
public interface Component {void operation();
}// 具体组件
public class ConcreteComponent implements Component {@Overridepublic void operation() {System.out.println("ConcreteComponent operation");}
}// 装饰器抽象类
public abstract class Decorator implements Component {protected Component component;public Decorator(Component component) {this.component = component;}@Overridepublic void operation() {component.operation();}
}// 具体装饰器
public class ConcreteDecorator extends Decorator {public ConcreteDecorator(Component component) {super(component);}@Overridepublic void operation() {super.operation();addedBehavior();}private void addedBehavior() {System.out.println("ConcreteDecorator addedBehavior");}
}// 客户端代码
public class Client {public static void main(String[] args) {Component component = new ConcreteComponent();Component decorator = new ConcreteDecorator(component);decorator.operation(); // 执行装饰后的操作}
}
2.5 外观模式(Facade Pattern)
核心思想:为子系统中的一组接口提供一个一致的界面,使得子系统更容易使用。
实现方式:通过定义一个外观类来封装子系统的复杂性,提供简化的接口。
应用场景:Spring 的 JdbcUtils 封装数据库操作细节。
优点:
- 简化使用:提供简单的接口来访问复杂的子系统。
- 解耦:将客户端与子系统解耦。
Java 示例:
// 子系统类A
public class SubsystemA {public void operationA() {System.out.println("SubsystemA operationA");}
}// 子系统类B
public class SubsystemB {public void operationB() {System.out.println("SubsystemB operationB");}
}// 外观类
public class Facade {private SubsystemA subsystemA;private SubsystemB subsystemB;public Facade() {subsystemA = new SubsystemA();subsystemB = new SubsystemB();}public void operation() {subsystemA.operationA();subsystemB.operationB();}
}// 客户端代码
public class Client {public static void main(String[] args) {Facade facade = new Facade();facade.operation(); // 通过外观类调用子系统}
}
2.6 享元模式(Flyweight Pattern)
核心思想:运用共享技术有效地支持大量细粒度的对象。
实现方式:通过将对象的共享部分与独享部分分开,将共享部分提取出来。
应用场景:棋类游戏的棋子对象复用、字符串常量池。
优点:
- 节省内存:通过共享来减少内存使用。
- 提高性能:减少对象创建和管理的开销。
Java 示例:
import java.util.HashMap;
import java.util.Map;// 享元接口
public interfaceFlyweight {void operation(String extrinsicState);
}// 具体享元类
public class ConcreteFlyweight implements Flyweight {private String intrinsicState;public ConcreteFlyweight(String intrinsicState) {this.intrinsicState = intrinsicState;}@Overridepublic void operation(String extrinsicState) {System.out.println("Intrinsic State: " + intrinsicState + ", Extrinsic State: " + extrinsicState);}
}// 享元工厂
public class FlyweightFactory {private Map<String, Flyweight> flyweights = new HashMap<>();public Flyweight getFlyweight(String key) {Flyweight flyweight = flyweights.get(key);if (flyweight == null) {flyweight = new ConcreteFlyweight(key);flyweights.put(key, flyweight);}return flyweight;}
}// 客户端代码
public class Client {public static void main(String[] args) {FlyweightFactory factory = new FlyweightFactory();Flyweight flyweight1 = factory.getFlyweight("A");Flyweight flyweight2 = factory.getFlyweight("B");flyweight1.operation("1");flyweight2.operation("2");}
}
2.7 代理模式(Proxy Pattern)
核心思想:为其他对象提供一种代理以控制对这个对象的访问。
实现方式:通过定义代理类来控制对真实对象的访问。
应用场景:AOP 实现、RPC 调用。
优点:
- 控制访问:可以在代理中实现对真实对象的控制。
- 增强功能:可以在代理中增加额外的功能,如延迟加载。
Java 示例:
// 抽象主题接口
public interface Subject {void request();
}// 真实主题类
public class RealSubject implements Subject {@Overridepublic void request() {System.out.println("RealSubject request");}
}// 代理类
public class Proxy implements Subject {private RealSubject realSubject;@Overridepublic void request() {if (realSubject == null) {realSubject = new RealSubject();}realSubject.request(); // 代理控制对真实主题的访问}
}// 客户端代码
public class Client {public static void main(String[] args) {Subject proxy = new Proxy();proxy.request(); // 通过代理访问真实主题}
}
三、行为型模式(Behavioral Patterns)
行为型模式关注对象之间的沟通和职责分配。
3.1 责任链模式(Chain of Responsibility Pattern)
核心思想:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。
实现方式:通过定义处理请求的链,并逐步将请求传递给链中的各个对象,直到找到合适的处理者。
应用场景:Servlet Filter、审批流程等。
优点:
- 解耦:发送者和接收者解耦。
- 灵活性:可以动态地添加或修改处理者。
Java 示例:
// 处理者接口
public abstract class Handler {protected Handler nextHandler;public void setNextHandler(Handler nextHandler) {this.nextHandler = nextHandler;}public abstract void handleRequest(String request);
}// 具体处理者A
public class ConcreteHandlerA extends Handler {@Overridepublic void handleRequest(String request) {if (request.equals("A")) {System.out.println("Handler A handling request A");} else if (nextHandler != null) {nextHandler.handleRequest(request);}}
}// 具体处理者B
public class ConcreteHandlerB extends Handler {@Overridepublic void handleRequest(String request) {if (request.equals("B")) {System.out.println("Handler B handling request B");} else if (nextHandler != null) {nextHandler.handleRequest(request);}}
}// 客户端代码
public class Client {public static void main(String[] args) {Handler handlerA = new ConcreteHandlerA();Handler handlerB = new ConcreteHandlerB();handlerA.setNextHandler(handlerB);handlerA.handleRequest("A"); // 处理请求AhandlerA.handleRequest("B"); // 处理请求BhandlerA.handleRequest("C"); // 无处理者}
}
3.2 命令模式(Command Pattern)
核心思想:将请求封装成一个对象,从而使你能够用不同的请求对客户进行参数化、队列化请求、以及支持可撤销操作。
实现方式:通过定义命令接口和具体命令类,将请求封装为对象,并将其传递给调用者。
应用场景:GUI 菜单操作、事务管理。
优点:
- 解耦:发送者和接收者解耦。
- 灵活性:可以动态地创建、撤销请求。
Java 示例:
// 命令接口
public interface Command {void execute();
}// 具体命令类
public class ConcreteCommand implements Command {private Receiver receiver;public ConcreteCommand(Receiver receiver) {this.receiver = receiver;}@Overridepublic void execute() {receiver.action(); // 将请求委托给接收者}
}// 接收者类
public class Receiver {public void action() {System.out.println("Receiver action");}
}// 调用者类
public class Invoker {private Command command;public void setCommand(Command command) {this.command = command;}public void invoke() {command.execute();}
}// 客户端代码
public class Client {public static void main(String[] args) {Receiver receiver = new Receiver();Command command = new ConcreteCommand(receiver);Invoker invoker = new Invoker();invoker.setCommand(command);invoker.invoke(); // 执行命令}
}
3.3 迭代器模式(Iterator Pattern)
核心思想:提供一种方法访问一个容器对象中各个元素,而又不暴露该对象的内部表示。
实现方式:通过定义迭代器接口和具体迭代器类来遍历集合对象中的元素。
应用场景:集合类、数据库查询结果等。
优点:
- 简化访问:提供统一的访问方式。
- 解耦:容器和迭代器解耦。
Java 示例:
import java.util.ArrayList;
import java.util.List;// 迭代器接口
public interface Iterator {boolean hasNext();Object next();
}// 具体迭代器类
public class ConcreteIterator implements Iterator {private List<Object> items;private int position;public ConcreteIterator(List<Object> items) {this.items = items;}@Overridepublic boolean hasNext() {return position < items.size();}@Overridepublic Object next() {return items.get(position++);}
}// 聚合类
public class Aggregate {private List<Object> items = new ArrayList<>();public void add(Object item) {items.add(item);}public Iterator iterator() {return new ConcreteIterator(items);}
}// 客户端代码
public class Client {public static void main(String[] args) {Aggregate aggregate = new Aggregate();aggregate.add("Item 1");aggregate.add("Item 2");Iterator iterator = aggregate.iterator();while (iterator.hasNext()) {System.out.println(iterator.next());}}
}
3.4 中介者模式(Mediator Pattern)
核心思想:定义一个对象来封装一组对象之间的交互,使得对象之间的耦合松散,从而使得它们可以独立地改变。
实现方式:通过定义中介者接口和具体中介者类来协调对象之间的交互。
应用场景:聊天室消息转发、MVC 控制器。
优点:
- 降低耦合:将对象间的交互集中在中介者中。
- 易于维护:中介者可以集中处理复杂的交互逻辑。
Java 示例:
// 中介者接口
public interface Mediator {void notify(Component sender, String event);
}// 具体中介者类
public 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;}@Overridepublic void notify(Component sender, String event) {if (sender == componentA) {componentB.handleEvent(event);} else if (sender == componentB) {componentA.handleEvent(event);}}
}// 组件接口
public abstract class Component {protected Mediator mediator;public Component(Mediator mediator) {this.mediator = mediator;}public abstract void handleEvent(String event);
}// 具体组件A
public class ComponentA extends Component {public ComponentA(Mediator mediator) {super(mediator);}@Overridepublic void handleEvent(String event) {System.out.println("ComponentA handling event: "+ event);}public void triggerEvent(String event) {mediator.notify(this, event);}
}// 具体组件B
public class ComponentB extends Component {public ComponentB(Mediator mediator) {super(mediator);}@Overridepublic void handleEvent(String event) {System.out.println("ComponentB handling event: " + event);}
}// 客户端代码
public class Client {public static void main(String[] args) {ConcreteMediator mediator = new ConcreteMediator();ComponentA componentA = new ComponentA(mediator);ComponentB componentB = new ComponentB(mediator);mediator.setComponentA(componentA);mediator.setComponentB(componentB);componentA.triggerEvent("Event A");componentB.handleEvent("Event B");}
}
3.5 备忘录模式(Memento Pattern)
核心思想:在不暴露对象内部状态的情况下,捕获一个对象的内部状态,并在该对象外部保存这个状态。可以在以后将对象恢复到保存的状态。
实现方式:通过定义备忘录类来保存对象的状态,并通过发起人类和恢复者类来实现状态的恢复。
应用场景:文本编辑器撤销功能、游戏存档。
优点:
- 状态恢复:可以在需要的时候恢复对象的状态。
- 封装性:不暴露对象的内部状态。
Java 示例:
// 备忘录类
public class Memento {private String state;public Memento(String state) {this.state = state;}public String getState() {return state;}
}// 发起人类
public 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();}
}// 管理者类
public class Caretaker {private Memento memento;public void saveMemento(Memento memento) {this.memento = memento;}public Memento retrieveMemento() {return memento;}
}// 客户端代码
public class Client {public static void main(String[] args) {Originator originator = new Originator();Caretaker caretaker = new Caretaker();originator.setState("State1");caretaker.saveMemento(originator.saveStateToMemento());originator.setState("State2");System.out.println("Current State: " + originator.getState());originator.getStateFromMemento(caretaker.retrieveMemento());System.out.println("Restored State: " + originator.getState());}
}
3.6 解释器模式(Interpreter Pattern)
核心思想:给定一个语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。
实现方式:通过定义解释器类和表达式类,将文法规则和解释逻辑分开。
应用场景:编译器、SQL 解析器、游戏规则引擎。
优点:
- 易于扩展:可以通过增加新的终结符和非终结符来扩展语法。
- 灵活性:可以定义复杂的语言规则。
Java 示例:
import java.util.HashMap;
import java.util.Map;// 表达式接口
public interface Expression {int interpret(Map<String, Integer> context);
}// 终结符表达式
public class NumberExpression implements Expression {private int number;public NumberExpression(int number) {this.number = number;}@Overridepublic int interpret(Map<String, Integer> context) {return number;}
}// 非终结符表达式
public class PlusExpression implements Expression {private Expression left;private Expression right;public PlusExpression(Expression left, Expression right) {this.left = left;this.right = right;}@Overridepublic int interpret(Map<String, Integer> context) {return left.interpret(context) + right.interpret(context);}
}// 客户端代码
public class Client {public static void main(String[] args) {Expression expression = new PlusExpression(new NumberExpression(5), new NumberExpression(3));Map<String, Integer> context = new HashMap<>();int result = expression.interpret(context);System.out.println("Result: " + result); // 输出结果 8}
}
3.7 状态模式(State Pattern)
核心思想:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
实现方式:通过定义状态接口和具体状态类,将对象的状态和行为分开,使得状态改变时可以改变行为。
应用场景:游戏状态机、自动售货机、线程状态等。
优点:
- 状态独立:每个状态都有自己的行为。
- 易于扩展:可以增加新的状态而不改变现有代码。
Java 示例:
// 状态接口
public interface State {void handle(Context context);
}// 具体状态A
public class ConcreteStateA implements State {@Overridepublic void handle(Context context) {System.out.println("Handling state A");context.setState(new ConcreteStateB()); // 切换到状态B}
}// 具体状态B
public class ConcreteStateB implements State {@Overridepublic void handle(Context context) {System.out.println("Handling state B");context.setState(new ConcreteStateA()); // 切换到状态A}
}// 上下文类
public 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);}
}// 客户端代码
public class Client {public static void main(String[] args) {Context context = new Context(new ConcreteStateA());context.request(); // 处理状态Acontext.request(); // 处理状态B}
}
3.8 策略模式(Strategy Pattern)
核心思想:定义一系列算法,将每一个算法封装起来,并使它们可以相互替换。策略模式让算法独立于使用它的客户而独立变化。
实现方式:通过定义策略接口和具体策略类,将算法封装为对象,并在运行时选择使用。
应用场景:算法选择、游戏策略、数据排序等。
优点:
- 灵活性:可以动态选择算法。
- 易于扩展:可以新增策略而不影响现有代码。
Java 示例:
// 策略接口
public interface Strategy {void execute();
}// 具体策略A
public class ConcreteStrategyA implements Strategy {@Overridepublic void execute() {System.out.println("Executing strategy A");}
}// 具体策略B
public class ConcreteStrategyB implements Strategy {@Overridepublic void execute() {System.out.println("Executing strategy B");}
}// 上下文类
public class Context {private Strategy strategy;public void setStrategy(Strategy strategy) {this.strategy = strategy;}public void executeStrategy() {strategy.execute();}
}// 客户端代码
public class Client {public static void main(String[] args) {Context context = new Context();context.setStrategy(new ConcreteStrategyA());context.executeStrategy(); // 执行策略Acontext.setStrategy(new ConcreteStrategyB());context.executeStrategy(); // 执行策略B}
}
3.9 模板方法模式(Template Method Pattern)
核心思想:定义一个操作中的算法的骨架,将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下重新定义算法中的某些步骤。
实现方式:通过定义模板方法在父类中,并将一些步骤的实现延迟到子类中。
应用场景:Servlet 的 service() 方法调度 doGet()/doPost()。
优点:
- 复用性:将公共算法逻辑放在父类中。
- 灵活性:子类可以改变某些步骤的实现而不改变算法结构。
Java 示例:
// 抽象类
public abstract class AbstractClass {// 模板方法public final void templateMethod() {step1();step2();step3();}// 具体步骤1private void step1() {System.out.println("Step 1");}// 具体步骤2,留给子类实现protected abstract void step2();// 具体步骤3private void step3() {System.out.println("Step 3");}
}// 具体类A
public class ConcreteClassA extends AbstractClass {@Overrideprotected void step2() {System.out.println("ConcreteClassA Step 2");}
}// 具体类B
public class ConcreteClassB extends AbstractClass {@Overrideprotected void step2() {System.out.println("ConcreteClassB Step 2");}
}// 客户端代码
public class Client {public static void main(String[] args) {AbstractClass concreteClassA = new ConcreteClassA();concreteClassA.templateMethod(); // 执行具体类A的模板方法AbstractClass concreteClassB = new ConcreteClassB();concreteClassB.templateMethod(); // 执行具体类B的模板方法}
}
3.10 访问者模式(Visitor Pattern)
核心思想:表示一个作用于某对象结构中的各元素的操作,它可以在不改变元素类的前提下定义作用于这些元素的新操作。
实现方式:通过定义访问者接口和具体访问者类,将操作和对象结构分离,使得可以在不改变对象结构的情况下增加新的操作。
应用场景:编译器语法树分析、复杂对象结构遍历。
优点:
- 扩展性:可以在不改变对象结构的情况下增加新的操作。
- 操作集中:操作被集中在访问者中,使得相关操作更易于维护。
Java 示例:
import java.util.ArrayList;
import java.util.List;// 访问者接口
public interface Visitor {void visit(ConcreteElementA elementA);void visit(ConcreteElementB elementB);
}// 具体访问者A
public class ConcreteVisitorA implements Visitor {@Overridepublic void visit(ConcreteElementA elementA) {System.out.println("Visitor A visiting Element A");}@Overridepublic void visit(ConcreteElementB elementB) {System.out.println("Visitor A visiting Element B");}
}// 具体访问者B
public class ConcreteVisitorB implements Visitor {@Overridepublic void visit(ConcreteElementA elementA) {System.out.println("Visitor B visiting Element A");}@Overridepublic void visit(ConcreteElementB elementB) {System.out.println("Visitor B visiting Element B");}
}// 元素接口
public interface Element {void accept(Visitor visitor);
}// 具体元素A
public class ConcreteElementA implements Element {@Overridepublic void accept(Visitor visitor) {visitor.visit(this);}
}// 具体元素B
public class ConcreteElementB implements Element {@Overridepublic void accept(Visitor visitor) {visitor.visit(this);}
}// 对象结构
public class ObjectStructure {private List<Element> elements = new ArrayList<>();public void addElement(Element element) {elements.add(element);}public void accept(Visitor visitor) {for (Element element : elements) {element.accept(visitor);}}
}// 客户端代码
public class Client {public static void main(String[] args) {ObjectStructure structure = new ObjectStructure();structure.addElement(new ConcreteElementA());structure.addElement(new ConcreteElementB());Visitor visitorA = new ConcreteVisitorA();structure.accept(visitorA); // Visitor A visiting elementsVisitor visitorB = new ConcreteVisitorB();structure.accept(visitorB); // Visitor B visiting elements}
}
3.11 观察者模式(Observer Pattern)
核心思想:定义对象之间的一对多依赖,使得当一个对象改变状态时,所有依赖于它的对象都得到通知并被自动更新。
实现方式:通过定义观察者接口和被观察者类来实现一对多的通知机制。
应用场景:事件驱动、消息订阅。
优点:
- 解耦:观察者和被观察者之间的解耦。
- 动态更新:自动更新所有观察者。
Java 示例:
import java.util.ArrayList;
importjava.util.List;// 观察者接口
public interface Observer {void update(String message);
}// 被观察者接口
public interface Subject {void addObserver(Observer observer);void removeObserver(Observer observer);void notifyObservers(String message);
}// 具体被观察者
public class ConcreteSubject implements Subject {private List<Observer> observers = new ArrayList<>();@Overridepublic void addObserver(Observer observer) {observers.add(observer);}@Overridepublic void removeObserver(Observer observer) {observers.remove(observer);}@Overridepublic void notifyObservers(String message) {for (Observer observer : observers) {observer.update(message);}}
}// 具体观察者
public class ConcreteObserver implements Observer {private String name;public ConcreteObserver(String name) {this.name = name;}@Overridepublic void update(String message) {System.out.println(name + " received: " + message);}
}// 客户端代码
public class Client {public static void main(String[] args) {ConcreteSubject subject = new ConcreteSubject();Observer observer1 = new ConcreteObserver("Observer1");Observer observer2 = new ConcreteObserver("Observer2");subject.addObserver(observer1);subject.addObserver(observer2);subject.notifyObservers("Hello Observers!");}
}
总结
设计模式是软件开发中的宝贵财富,它们为解决常见问题提供了标准化的解决方案。通过深入理解并灵活运用这些模式,你可以编写出更加健壮、可维护和可扩展的代码