Java 23种设计模式详解
本文由 简悦 SimpRead 转码, 原文地址 blog.csdn.net
Java 中的 23 种设计模式详解
设计模式是软件开发中的最佳实践,帮助开发者在面对复杂设计问题时提供有效的解决方案。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;
}
// 使用浅拷贝
@Override
public 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 Data
clonedPrototype.setData("Modified Data");
System.out.println(prototype.getData()); // 输出: Prototype Data
System.out.println(clonedPrototype.getData()); // 输出: Modified Data
}
}
1.3 建造者模式(Builder Pattern)
定义:使用多个简单的对象一步一步构建一个复杂的对象。
原理:定义一个建造者接口和具体建造者类,通过建造者类来创建复杂对象。
优点:
- 解耦:将复杂对象的构建与表示解耦。
- 灵活性:可以根据需要创建不同表示的复杂对象。
Java 示例:
// 产品类
public class Product {
private String partA;
private String partB;
// 构造函数
public Product(String partA, String partB) {
this.partA = partA;
this.partB = partB;
}
@Override
public 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;
@Override
public void buildPartA() {
partA = "Part A";
}
@Override
public void buildPartB() {
partB = "Part B";
}
@Override
public 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)
定义:定义一个创建对象的接口,但由子类决定实例化哪个类。
原理:将对象的创建逻辑放在子类中,而不是在客户端代码中。
优点:
- 灵活性:可以在运行时决定创建对象的类型。
- 符合开闭原则:对扩展开放,对修改关闭。
Java 示例:
// 产品接口
public interface Product {
void operation();
}
// 具体产品A
public class ConcreteProductA implements Product {
@Override
public void operation() {
System.out.println("ConcreteProductA operation");
}
}
// 具体产品B
public class ConcreteProductB implements Product {
@Override
public void operation() {
System.out.println("ConcreteProductB operation");
}
}
// 工厂接口
public abstract class Creator {
public abstract Product factoryMethod();
}
// 具体工厂A
public class ConcreteCreatorA extends Creator {
@Override
public Product factoryMethod() {
return new ConcreteProductA();
}
}
// 具体工厂B
public class ConcreteCreatorB extends Creator {
@Override
public 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)
定义:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
原理:通过定义多个工厂接口,每个接口负责创建一组相关的对象。
优点:
- 一致性:确保创建的一系列对象具有一致性。
- 扩展性:易于扩展产品系列,而不影响现有代码。
Java 示例:
// 产品A接口
public interface ProductA {
void operationA();
}
// 产品B接口
public interface ProductB {
void operationB();
}
// 具体产品A1
public class ConcreteProductA1 implements ProductA {
@Override
public void operationA() {
System.out.println("ConcreteProductA1 operationA");
}
}
// 具体产品B1
public class ConcreteProductB1 implements ProductB {
@Override
public void operationB() {
System.out.println("ConcreteProductB1 operationB");
}
}
// 具体产品A2
public class ConcreteProductA2 implements ProductA {
@Override
public void operationA() {
System.out.println("ConcreteProductA2 operationA");
}
}
// 具体产品B2
public class ConcreteProductB2 implements ProductB {
@Override
public void operationB() {
System.out.println("ConcreteProductB2 operationB");
}
}
// 抽象工厂接口
public interface AbstractFactory {
ProductA createProductA();
ProductB createProductB();
}
// 具体工厂1
public class ConcreteFactory1 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ConcreteProductA1();
}
@Override
public ProductB createProductB() {
return new ConcreteProductB1();
}
}
// 具体工厂2
public class ConcreteFactory2 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ConcreteProductA2();
}
@Override
public 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;
}
@Override
public 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)
定义:将抽象部分与实现部分分离,使它们可以独立地变化。
原理:通过定义抽象类和实现类,将它们的变化解耦。
优点:
- 解耦:抽象和实现的解耦,使得它们可以独立变化。
- 灵活性:可以独立地扩展抽象和实现。
Java 示例:
// 实现接口
public interface Implementor {
void operation();
}
// 具体实现A
public class ConcreteImplementorA implements Implementor {
@Override
public void operation() {
System.out.println("ConcreteImplementorA operation");
}
}
// 具体实现B
public class ConcreteImplementorB implements Implementor {
@Override
public 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);
}
@Override
public 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 设计模式之桥接模式(Bridge Pattern)
2.3 组合模式(Composite Pattern)
定义:将对象组合成树形结构以表示部分 - 整体层次结构,使得客户端对单个对象和组合对象的使用具有一致性。
原理:通过定义一个组件接口,将叶子节点和容器节点统一处理。
优点:
- 一致性:对单个对象和组合对象的一致性操作。
- 简化客户端代码:客户端代码可以统一处理叶子节点和容器节点。
Java 示例:
import java.util.ArrayList;
import java.util.List;
// 组件接口
public interface Component {
void operation();
}
// 叶子节点
public class Leaf implements Component {
@Override
public 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);
}
@Override
public 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 示例:
// 组件接口
public interface Component {
void operation();
}
// 具体组件
public class ConcreteComponent implements Component {
@Override
public void operation() {
System.out.println("ConcreteComponent operation");
}
}
// 装饰器抽象类
public abstract class Decorator implements Component {
protected Component component;
public Decorator(Component component) {
this.component = component;
}
@Override
public void operation() {
component.operation();
}
}
// 具体装饰器
public class ConcreteDecorator extends Decorator {
public ConcreteDecorator(Component component) {
super(component);
}
@Override
public 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)
定义:为子系统中的一组接口提供一个一致的界面,使得子系统更容易使用。
原理:通过定义一个外观类来封装子系统的复杂性,提供简化的接口。
优点:
- 简化使用:提供简单的接口来访问复杂的子系统。
- 解耦:将客户端与子系统解耦。
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 interface
Flyweight {
void operation(String extrinsicState);
}
// 具体享元类
public class ConcreteFlyweight implements Flyweight {
private String intrinsicState;
public ConcreteFlyweight(String intrinsicState) {
this.intrinsicState = intrinsicState;
}
@Override
public 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)
定义:为其他对象提供一种代理以控制对这个对象的访问。
原理:通过定义代理类来控制对真实对象的访问。
优点:
- 控制访问:可以在代理中实现对真实对象的控制。
- 增强功能:可以在代理中增加额外的功能,如延迟加载。
Java 示例:
// 抽象主题接口
public interface Subject {
void request();
}
// 真实主题类
public class RealSubject implements Subject {
@Override
public void request() {
System.out.println("RealSubject request");
}
}
// 代理类
public class Proxy implements Subject {
private RealSubject realSubject;
@Override
public 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)
定义:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。
原理:通过定义处理请求的链,并逐步将请求传递给链中的各个对象,直到找到合适的处理者。
优点:
- 解耦:发送者和接收者解耦。
- 灵活性:可以动态地添加或修改处理者。
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 {
@Override
public 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 {
@Override
public 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"); // 处理请求A
handlerA.handleRequest("B"); // 处理请求B
handlerA.handleRequest("C"); // 无处理者
}
}
3.2 命令模式(Command Pattern)
定义:将请求封装成一个对象,从而使你能够用不同的请求对客户进行参数化、队列化请求、以及支持可撤销操作。
原理:通过定义命令接口和具体命令类,将请求封装为对象,并将其传递给调用者。
优点:
- 解耦:发送者和接收者解耦。
- 灵活性:可以动态地创建、撤销请求。
Java 示例:
// 命令接口
public interface Command {
void execute();
}
// 具体命令类
public class ConcreteCommand implements Command {
private Receiver receiver;
public ConcreteCommand(Receiver receiver) {
this.receiver = receiver;
}
@Override
public 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;
}
@Override
public boolean hasNext() {
return position < items.size();
}
@Override
public 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)
定义:定义一个对象来封装一组对象之间的交互,使得对象之间的耦合松散,从而使得它们可以独立地改变。
原理:通过定义中介者接口和具体中介者类来协调对象之间的交互。
优点:
- 降低耦合:将对象间的交互集中在中介者中。
- 易于维护:中介者可以集中处理复杂的交互逻辑。
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;
}
@Override
public 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);
}
@Override
public 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);
}
@Override
public 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)
定义:给定一个语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。
原理:通过定义解释器类和表达式类,将文法规则和解释逻辑分开。
优点:
- 易于扩展:可以通过增加新的终结符和非终结符来扩展语法。
- 灵活性:可以定义复杂的语言规则。
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;
}
@Override
public 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;
}
@Override
public 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 {
@Override
public void handle(Context context) {
System.out.println("Handling state A");
context.setState(new ConcreteStateB()); // 切换到状态B
}
}
// 具体状态B
public class ConcreteStateB implements State {
@Override
public 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(); // 处理状态A
context.request(); // 处理状态B
}
}
3.8 策略模式(Strategy Pattern)
定义:定义一系列算法,将每一个算法封装起来,并使它们可以相互替换。策略模式让算法独立于使用它的客户而独立变化。
原理:通过定义策略接口和具体策略类,将算法封装为对象,并在运行时选择使用。
优点:
- 灵活性:可以动态选择算法。
- 易于扩展:可以新增策略而不影响现有代码。
Java 示例:
// 策略接口
public interface Strategy {
void execute();
}
// 具体策略A
public class ConcreteStrategyA implements Strategy {
@Override
public void execute() {
System.out.println("Executing strategy A");
}
}
// 具体策略B
public class ConcreteStrategyB implements Strategy {
@Override
public 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(); // 执行策略A
context.setStrategy(new ConcreteStrategyB());
context.executeStrategy(); // 执行策略B
}
}
3.9 模板方法模式(Template Method Pattern)
定义:定义一个操作中的算法的骨架,将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下重新定义算法中的某些步骤。
原理:通过定义模板方法在父类中,并将一些步骤的实现延迟到子类中。
优点:
- 复用性:将公共算法逻辑放在父类中。
- 灵活性:子类可以改变某些步骤的实现而不改变算法结构。
Java 示例:
// 抽象类
public abstract class AbstractClass {
// 模板方法
public final void templateMethod() {
step1();
step2();
step3();
}
// 具体步骤1
private void step1() {
System.out.println("Step 1");
}
// 具体步骤2,留给子类实现
protected abstract void step2();
// 具体步骤3
private void step3() {
System.out.println("Step 3");
}
}
// 具体类A
public class ConcreteClassA extends AbstractClass {
@Override
protected void step2() {
System.out.println("ConcreteClassA Step 2");
}
}
// 具体类B
public class ConcreteClassB extends AbstractClass {
@Override
protected void step2() {
System.out.println("ConcreteClassB Step 2");
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
AbstractClass concreteClassA = new ConcreteClassA();
concreteClass
A.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 {
@Override
public void visit(ConcreteElementA elementA) {
System.out.println("Visitor A visiting Element A");
}
@Override
public void visit(ConcreteElementB elementB) {
System.out.println("Visitor A visiting Element B");
}
}
// 具体访问者B
public class ConcreteVisitorB implements Visitor {
@Override
public void visit(ConcreteElementA elementA) {
System.out.println("Visitor B visiting Element A");
}
@Override
public 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 {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
// 具体元素B
public class ConcreteElementB implements Element {
@Override
public 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 elements
Visitor visitorB = new ConcreteVisitorB();
structure.accept(visitorB); // Visitor B visiting elements
}
}
3.11 观察者模式(Observer Pattern)
定义:定义对象之间的一对多依赖,使得当一个对象改变状态时,所有依赖于它的对象都得到通知并被自动更新。
原理:通过定义观察者接口和被观察者类来实现一对多的通知机制。
优点:
- 解耦:观察者和被观察者之间的解耦。
- 动态更新:自动更新所有观察者。
Java 示例:
import java.util.ArrayList;
import
java.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<>();
@Override
public void addObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public 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;
}
@Override
public 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!");
}
}
这些设计模式是解决常见设计问题的通用方案。每种模式都有其独特的应用场景和优点,通过合理运用这些模式,可以使软件系统更加灵活、可维护和可扩展。