Java设计模式基础知识

Java设计模式基础知识

一、什么是设计模式?

设计模式是软件开发中被反复使用的、经过总结的、可复用的解决方案。它们是对软件设计中常见问题的最佳实践总结。设计模式不是代码,而是一种模板,描述了如何解决在不同情况下重复发生的问题。

设计模式的主要目的是:

  • 提高代码的可重用性
  • 提高代码的可维护性
  • 提高代码的可扩展性
  • 提高代码的可读性
  • 降低代码的耦合度

二、设计模式的分类

设计模式通常分为三大类:

  1. 创建型模式:关注对象的创建过程。

    • 单例模式(Singleton)
    • 工厂模式(Factory Method)
    • 抽象工厂模式(Abstract Factory)
    • 建造者模式(Builder)
    • 原型模式(Prototype)
  2. 结构型模式:关注类和对象的组合。

    • 适配器模式(Adapter)
    • 桥接模式(Bridge)
    • 组合模式(Composite)
    • 装饰者模式(Decorator)
    • 外观模式(Facade)
    • 享元模式(Flyweight)
    • 代理模式(Proxy)
  3. 行为型模式:关注对象之间的交互。

    • 观察者模式(Observer)
    • 策略模式(Strategy)
    • 命令模式(Command)
    • 责任链模式(Chain of Responsibility)
    • 状态模式(State)
    • 访问者模式(Visitor)
    • 中介者模式(Mediator)
    • 迭代器模式(Iterator)
    • 备忘录模式(Memento)
    • 模板方法模式(Template Method)
    • 解释器模式(Interpreter)

三、常用设计模式详解

1. 单例模式(Singleton)

确保一个类只有一个实例,并提供一个全局访问点。

应用场景

  • 数据库连接池
  • 线程池
  • 缓存
  • 日志记录器
  • 配置管理器

实现方式

  1. 懒汉式(线程不安全)
  2. 懒汉式(线程安全,同步方法)
  3. 懒汉式(线程安全,双重检查锁定)
  4. 饿汉式
  5. 静态内部类
  6. 枚举

代码示例

// 懒汉式(线程安全,双重检查锁定)
public class Singleton {
    
    
    private volatile static Singleton instance;
    
    private Singleton() {
    
    }
    
    public static Singleton getInstance() {
    
    
        if (instance == null) {
    
    
            synchronized (Singleton.class) {
    
    
                if (instance == null) {
    
    
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

// 静态内部类(推荐)
public class Singleton {
    
    
    private Singleton() {
    
    }
    
    private static class SingletonHolder {
    
    
        private static final Singleton INSTANCE = new Singleton();
    }
    
    public static Singleton getInstance() {
    
    
        return SingletonHolder.INSTANCE;
    }
}

// 枚举(最简单)
public enum Singleton {
    
    
    INSTANCE;
    
    public void doSomething() {
    
    
        // 业务方法
    }
}

2. 工厂模式(Factory Method)

定义一个创建对象的接口,让子类决定实例化哪一个类。

应用场景

  • 需要创建的对象类型不确定
  • 需要将对象的创建与使用分离
  • 需要为不同的客户端创建不同的对象

代码示例

// 产品接口
public interface Product {
    
    
    void use();
}

// 具体产品A
public class ConcreteProductA implements Product {
    
    
    public void use() {
    
    
        System.out.println("Using Product A");
    }
}

// 具体产品B
public class ConcreteProductB implements Product {
    
    
    public void use() {
    
    
        System.out.println("Using Product B");
    }
}

// 工厂接口
public abstract class Creator {
    
    
    public abstract Product factoryMethod();
    
    // 模板方法
    public void anOperation() {
    
    
        Product product = factoryMethod();
        product.use();
    }
}

// 具体工厂A
public class ConcreteCreatorA extends Creator {
    
    
    public Product factoryMethod() {
    
    
        return new ConcreteProductA();
    }
}

// 具体工厂B
public class ConcreteCreatorB extends Creator {
    
    
    public Product factoryMethod() {
    
    
        return new ConcreteProductB();
    }
}

// 客户端代码
public class Client {
    
    
    public static void main(String[] args) {
    
    
        Creator creatorA = new ConcreteCreatorA();
        creatorA.anOperation(); // 输出: Using Product A
        
        Creator creatorB = new ConcreteCreatorB();
        creatorB.anOperation(); // 输出: Using Product B
    }
}

3. 抽象工厂模式(Abstract Factory)

提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们的具体类。

应用场景

  • 需要创建一系列相关对象
  • 系统需要独立于产品的创建、组合和表示
  • 系统需要配置多个产品系列中的一个

代码示例

// 抽象产品A
public interface AbstractProductA {
    
    
    void operationA();
}

// 抽象产品B
public interface AbstractProductB {
    
    
    void operationB();
}

// 具体产品A1
public class ConcreteProductA1 implements AbstractProductA {
    
    
    public void operationA() {
    
    
        System.out.println("ConcreteProductA1: operationA");
    }
}

// 具体产品A2
public class ConcreteProductA2 implements AbstractProductA {
    
    
    public void operationA() {
    
    
        System.out.println("ConcreteProductA2: operationA");
    }
}

// 具体产品B1
public class ConcreteProductB1 implements AbstractProductB {
    
    
    public void operationB() {
    
    
        System.out.println("ConcreteProductB1: operationB");
    }
}

// 具体产品B2
public class ConcreteProductB2 implements AbstractProductB {
    
    
    public void operationB() {
    
    
        System.out.println("ConcreteProductB2: operationB");
    }
}

// 抽象工厂
public interface AbstractFactory {
    
    
    AbstractProductA createProductA();
    AbstractProductB createProductB();
}

// 具体工厂1
public class ConcreteFactory1 implements AbstractFactory {
    
    
    public AbstractProductA createProductA() {
    
    
        return new ConcreteProductA1();
    }
    
    public AbstractProductB createProductB() {
    
    
        return new ConcreteProductB1();
    }
}

// 具体工厂2
public class ConcreteFactory2 implements AbstractFactory {
    
    
    public AbstractProductA createProductA() {
    
    
        return new ConcreteProductA2();
    }
    
    public AbstractProductB createProductB() {
    
    
        return new ConcreteProductB2();
    }
}

// 客户端代码
public class Client {
    
    
    public static void main(String[] args) {
    
    
        AbstractFactory factory1 = new ConcreteFactory1();
        AbstractProductA productA1 = factory1.createProductA();
        AbstractProductB productB1 = factory1.createProductB();
        productA1.operationA(); // 输出: ConcreteProductA1: operationA
        productB1.operationB(); // 输出: ConcreteProductB1: operationB
        
        AbstractFactory factory2 = new ConcreteFactory2();
        AbstractProductA productA2 = factory2.createProductA();
        AbstractProductB productB2 = factory2.createProductB();
        productA2.operationA(); // 输出: ConcreteProductA2: operationA
        productB2.operationB(); // 输出: ConcreteProductB2: operationB
    }
}

4. 建造者模式(Builder)

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

应用场景

  • 需要生成的对象具有复杂的内部结构
  • 需要生成的对象内部属性本身相互依赖
  • 需要对象的生成过程与表示分离

代码示例

// 产品
public class Product {
    
    
    private String partA;
    private String partB;
    private String partC;
    
    public void setPartA(String partA) {
    
    
        this.partA = partA;
    }
    
    public void setPartB(String partB) {
    
    
        this.partB = partB;
    }
    
    public void setPartC(String partC) {
    
    
        this.partC = partC;
    }
    
    public void show() {
    
    
        System.out.println("Product parts: " + partA + ", " + partB + ", " + partC);
    }
}

// 抽象建造者
public abstract class Builder {
    
    
    protected Product product = new Product();
    
    public abstract void buildPartA();
    public abstract void buildPartB();
    public abstract void buildPartC();
    
    public Product getResult() {
    
    
        return product;
    }
}

// 具体建造者1
public class ConcreteBuilder1 extends Builder {
    
    
    public void buildPartA() {
    
    
        product.setPartA("Part A1");
    }
    
    public void buildPartB() {
    
    
        product.setPartB("Part B1");
    }
    
    public void buildPartC() {
    
    
        product.setPartC("Part C1");
    }
}

// 具体建造者2
public class ConcreteBuilder2 extends Builder {
    
    
    public void buildPartA() {
    
    
        product.setPartA("Part A2");
    }
    
    public void buildPartB() {
    
    
        product.setPartB("Part B2");
    }
    
    public void buildPartC() {
    
    
        product.setPartC("Part C2");
    }
}

// 指挥者
public class Director {
    
    
    public void construct(Builder builder) {
    
    
        builder.buildPartA();
        builder.buildPartB();
        builder.buildPartC();
    }
}

// 客户端代码
public class Client {
    
    
    public static void main(String[] args) {
    
    
        Director director = new Director();
        
        Builder builder1 = new ConcreteBuilder1();
        director.construct(builder1);
        Product product1 = builder1.getResult();
        product1.show(); // 输出: Product parts: Part A1, Part B1, Part C1
        
        Builder builder2 = new ConcreteBuilder2();
        director.construct(builder2);
        Product product2 = builder2.getResult();
        product2.show(); // 输出: Product parts: Part A2, Part B2, Part C2
    }
}

5. 原型模式(Prototype)

用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。

应用场景

  • 当一个系统应该独立于它的产品创建、构成和表示时
  • 当要实例化的类是在运行时刻指定时
  • 当需要避免创建一个与产品类层次平行的工厂类层次时
  • 当一个类的实例只能有几个不同状态组合中的一种时

代码示例

// 原型接口
public interface Prototype extends Cloneable {
    
    
    Prototype clone();
}

// 具体原型
public class ConcretePrototype implements Prototype {
    
    
    private String id;
    private String type;
    
    public ConcretePrototype(String id, String type) {
    
    
        this.id = id;
        this.type = type;
    }
    
    public String getId() {
    
    
        return id;
    }
    
    public void setId(String id) {
    
    
        this.id = id;
    }
    
    public String getType() {
    
    
        return type;
    }
    
    public void setType(String type) {
    
    
        this.type = type;
    }
    
    public Prototype clone() {
    
    
        return new ConcretePrototype(this.id, this.type);
    }
    
    public String toString() {
    
    
        return "ConcretePrototype{id='" + id + "', type='" + type + "'}";
    }
}

// 客户端代码
public class Client {
    
    
    public static void main(String[] args) {
    
    
        ConcretePrototype prototype = new ConcretePrototype("1", "Type A");
        System.out.println(prototype); // 输出: ConcretePrototype{id='1', type='Type A'}
        
        ConcretePrototype clone = (ConcretePrototype) prototype.clone();
        clone.setId("2");
        System.out.println(clone); // 输出: ConcretePrototype{id='2', type='Type A'}
        
        System.out.println(prototype); // 输出: ConcretePrototype{id='1', type='Type A'}
    }
}

6. 适配器模式(Adapter)

将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

应用场景

  • 想使用一个已经存在的类,但其接口不符合你的需求
  • 想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作
  • 需要统一多个类的接口时

代码示例

// 目标接口
public interface Target {
    
    
    void request();
}

// 适配者
public class Adaptee {
    
    
    public void specificRequest() {
    
    
        System.out.println("Adaptee: specificRequest");
    }
}

// 类适配器
public class ClassAdapter extends Adaptee implements Target {
    
    
    public void request() {
    
    
        specificRequest();
    }
}

// 对象适配器
public class ObjectAdapter implements Target {
    
    
    private Adaptee adaptee;
    
    public ObjectAdapter(Adaptee adaptee) {
    
    
        this.adaptee = adaptee;
    }
    
    public void request() {
    
    
        adaptee.specificRequest();
    }
}

// 客户端代码
public class Client {
    
    
    public static void main(String[] args) {
    
    
        // 使用类适配器
        Target classAdapter = new ClassAdapter();
        classAdapter.request(); // 输出: Adaptee: specificRequest
        
        // 使用对象适配器
        Adaptee adaptee = new Adaptee();
        Target objectAdapter = new ObjectAdapter(adaptee);
        objectAdapter.request(); // 输出: Adaptee: specificRequest
    }
}

7. 桥接模式(Bridge)

将抽象部分与它的实现部分分离,使它们都可以独立地变化。

应用场景

  • 需要在多个维度上扩展一个类
  • 需要在运行时切换不同实现
  • 一个类存在多个独立变化的维度,且这些维度都需要进行扩展

代码示例

// 实现者接口
public interface Implementor {
    
    
    void operationImpl();
}

// 具体实现者A
public class ConcreteImplementorA implements Implementor {
    
    
    public void operationImpl() {
    
    
        System.out.println("ConcreteImplementorA: operationImpl");
    }
}

// 具体实现者B
public class ConcreteImplementorB implements Implementor {
    
    
    public void operationImpl() {
    
    
        System.out.println("ConcreteImplementorB: operationImpl");
    }
}

// 抽象类
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);
    }
    
    public void operation() {
    
    
        System.out.println("RefinedAbstraction: operation");
        implementor.operationImpl();
    }
}

// 客户端代码
public class Client {
    
    
    public static void main(String[] args) {
    
    
        Implementor implementorA = new ConcreteImplementorA();
        Abstraction abstractionA = new RefinedAbstraction(implementorA);
        abstractionA.operation();
        // 输出:
        // RefinedAbstraction: operation
        // ConcreteImplementorA: operationImpl
        
        Implementor implementorB = new ConcreteImplementorB();
        Abstraction abstractionB = new RefinedAbstraction(implementorB);
        abstractionB.operation();
        // 输出:
        // RefinedAbstraction: operation
        // ConcreteImplementorB: operationImpl
    }
}

8. 组合模式(Composite)

将对象组合成树形结构以表示"部分/整体"的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

应用场景

  • 表示对象的部分-整体层次结构
  • 希望用户忽略组合对象与单个对象的不同,用户统一地使用组合结构中的所有对象

代码示例

// 组件接口
public interface Component {
    
    
    void operation();
    void add(Component component);
    void remove(Component component);
    Component getChild(int index);
}

// 叶子节点
public class Leaf implements Component {
    
    
    private String name;
    
    public Leaf(String name) {
    
    
        this.name = name;
    }
    
    public void operation() {
    
    
        System.out.println("Leaf " + name + ": operation");
    }
    
    public void add(Component component) {
    
    
        // 叶子节点不支持添加子节点
    }
    
    public void remove(Component component) {
    
    
        // 叶子节点不支持删除子节点
    }
    
    public Component getChild(int index) {
    
    
        // 叶子节点不支持获取子节点
        return null;
    }
}

// 复合节点
public class Composite implements Component {
    
    
    private List<Component> children = new ArrayList<>();
    private String name;
    
    public Composite(String name) {
    
    
        this.name = name;
    }
    
    public void operation() {
    
    
        System.out.println("Composite " + name + ": operation");
        for (Component child : children) {
    
    
            child.operation();
        }
    }
    
    public void add(Component component) {
    
    
        children.add(component);
    }
    
    public void remove(Component component) {
    
    
        children.remove(component);
    }
    
    public Component getChild(int index) {
    
    
        return children.get(index);
    }
}

// 客户端代码
public class Client {
    
    
    public static void main(String[] args) {
    
    
        Component leaf1 = new Leaf("1");
        Component leaf2 = new Leaf("2");
        Component leaf3 = new Leaf("3");
        
        Component composite1 = new Composite("1");
        composite1.add(leaf1);
        composite1.add(leaf2);
        
        Component composite2 = new Composite("2");
        composite2.add(leaf3);
        
        Component root = new Composite("root");
        root.add(composite1);
        root.add(composite2);
        
        root.operation();
        // 输出:
        // Composite root: operation
        // Composite 1: operation
        // Leaf 1: operation
        // Leaf 2: operation
        // Composite 2: operation
        // Leaf 3: operation
    }
}

9. 装饰者模式(Decorator)

动态地给一个对象添加一些额外的职责,就增加功能来说,装饰者模式比生成子类更为灵活。

应用场景

  • 需要动态地给一个对象添加功能,而且这些功能可以动态地撤销
  • 需要在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责
  • 需要给一个类增加一些基本功能的排列组合

代码示例

// 组件接口
public interface Component {
    
    
    void operation();
}

// 具体组件
public class ConcreteComponent implements Component {
    
    
    public void operation() {
    
    
        System.out.println("ConcreteComponent: operation");
    }
}

// 抽象装饰者
public abstract class Decorator implements Component {
    
    
    protected Component component;
    
    public Decorator(Component component) {
    
    
        this.component = component;
    }
    
    public void operation() {
    
    
        component.operation();
    }
}

// 具体装饰者A
public class ConcreteDecoratorA extends Decorator {
    
    
    public ConcreteDecoratorA(Component component) {
    
    
        super(component);
    }
    
    public void operation() {
    
    
        super.operation();
        System.out.println("ConcreteDecoratorA: added behavior");
    }
}

// 具体装饰者B
public class ConcreteDecoratorB extends Decorator {
    
    
    public ConcreteDecoratorB(Component component) {
    
    
        super(component);
    }
    
    public void operation() {
    
    
        super.operation();
        System.out.println("ConcreteDecoratorB: added behavior");
    }
}

// 客户端代码
public class Client {
    
    
    public static void main(String[] args) {
    
    
        Component component = new ConcreteComponent();
        component.operation();
        // 输出: ConcreteComponent: operation
        
        Component decoratorA = new ConcreteDecoratorA(component);
        decoratorA.operation();
        // 输出:
        // ConcreteComponent: operation
        // ConcreteDecoratorA: added behavior
        
        Component decoratorB = new ConcreteDecoratorB(decoratorA);
        decoratorB.operation();
        // 输出:
        // ConcreteComponent: operation
        // ConcreteDecoratorA: added behavior
        // ConcreteDecoratorB: added behavior
    }
}

10. 外观模式(Facade)

为子系统中的一组接口提供一个一致的界面。外观模式定义了一个高层接口,这个接口使得子系统更加容易使用。

应用场景

  • 需要为复杂子系统提供一个简单接口
  • 需要将子系统与客户端解耦
  • 需要构建一个层次结构的子系统

代码示例

// 子系统A
public class SubsystemA {
    
    
    public void operationA() {
    
    
        System.out.println("SubsystemA: operationA");
    }
}

// 子系统B
public class SubsystemB {
    
    
    public void operationB() {
    
    
        System.out.println("SubsystemB: operationB");
    }
}

// 子系统C
public class SubsystemC {
    
    
    public void operationC() {
    
    
        System.out.println("SubsystemC: operationC");
    }
}

// 外观
public class Facade {
    
    
    private SubsystemA subsystemA;
    private SubsystemB subsystemB;
    private SubsystemC subsystemC;
    
    public Facade() {
    
    
        subsystemA = new SubsystemA();
        subsystemB = new SubsystemB();
        subsystemC = new SubsystemC();
    }
    
    public void operation() {
    
    
        System.out.println("Facade: operation");
        subsystemA.operationA();
        subsystemB.operationB();
        subsystemC.operationC();
    }
}

// 客户端代码
public class Client {
    
    
    public static void main(String[] args) {
    
    
        Facade facade = new Facade();
        facade.operation();
        // 输出:
        // Facade: operation
        // SubsystemA: operationA
        // SubsystemB: operationB
        // SubsystemC: operationC
    }
}

11. 享元模式(Flyweight)

运用共享技术有效地支持大量细粒度对象的复用。

应用场景

  • 系统中存在大量相似的对象
  • 需要缓冲池的场景
  • 对象的大部分状态可以外部化,而且可以将这些外部状态传入对象中

代码示例

// 享元接口
public interface Flyweight {
    
    
    void operation(String extrinsicState);
}

// 具体享元
public class ConcreteFlyweight implements Flyweight {
    
    
    private String intrinsicState;
    
    public ConcreteFlyweight(String intrinsicState) {
    
    
        this.intrinsicState = intrinsicState;
    }
    
    public void operation(String extrinsicState) {
    
    
        System.out.println("ConcreteFlyweight: operation, intrinsicState=" + intrinsicState + ", extrinsicState=" + extrinsicState);
    }
}

// 享元工厂
public class FlyweightFactory {
    
    
    private Map<String, Flyweight> flyweights = new HashMap<>();
    
    public Flyweight getFlyweight(String key) {
    
    
        if (!flyweights.containsKey(key)) {
    
    
            flyweights.put(key, new ConcreteFlyweight(key));
        }
        return flyweights.get(key);
    }
    
    public int getFlyweightCount() {
    
    
        return flyweights.size();
    }
}

// 客户端代码
public class Client {
    
    
    public static void main(String[] args) {
    
    
        FlyweightFactory factory = new FlyweightFactory();
        
        Flyweight flyweight1 = factory.getFlyweight("A");
        flyweight1.operation("1");
        // 输出: ConcreteFlyweight: operation, intrinsicState=A, extrinsicState=1
        
        Flyweight flyweight2 = factory.getFlyweight("B");
        flyweight2.operation("2");
        // 输出: ConcreteFlyweight: operation, intrinsicState=B, extrinsicState=2
        
        Flyweight flyweight3 = factory.getFlyweight("A");
        flyweight3.operation("3");
        // 输出: ConcreteFlyweight: operation, intrinsicState=A, extrinsicState=3
        
        System.out.println("Flyweight count: " + factory.getFlyweightCount());
        // 输出: Flyweight count: 2
    }
}

12. 代理模式(Proxy)

为其他对象提供一种代理以控制对这个对象的访问。

应用场景

  • 远程代理:为一个位于不同的地址空间的对象提供一个本地的代理对象
  • 虚拟代理:根据需要创建开销很大的对象
  • 保护代理:控制对原始对象的访问
  • 智能引用:在访问对象时执行一些附加操作

代码示例

// 抽象主题
public interface Subject {
    
    
    void request();
}

// 真实主题
public class RealSubject implements Subject {
    
    
    public void request() {
    
    
        System.out.println("RealSubject: request");
    }
}

// 代理
public class Proxy implements Subject {
    
    
    private RealSubject realSubject;
    
    public Proxy() {
    
    
        // 延迟加载
    }
    
    public void request() {
    
    
        if (realSubject == null) {
    
    
            realSubject = new RealSubject();
        }
        System.out.println("Proxy: before request");
        realSubject.request();
        System.out.println("Proxy: after request");
    }
}

// 客户端代码
public class Client {
    
    
    public static void main(String[] args) {
    
    
        Subject proxy = new Proxy();
        proxy.request();
        // 输出:
        // Proxy: before request
        // RealSubject: request
        // Proxy: after request
    }
}

13. 观察者模式(Observer)

定义对象间的一对多依赖,当一个对象状态改变时,所有依赖于它的对象都会得到通知并自动更新。

应用场景

  • 当一个对象状态改变需要通知其他对象,而不知道具体有多少对象需要通知
  • 当一个对象改变导致其他对象也需要改变,而不知道具体有多少对象需要改变

代码示例

import java.util.ArrayList;
import java.util.List;

// 主题接口
public interface Subject {
    
    
    void attach(Observer observer);
    void detach(Observer observer);
    void notifyObservers();
}

// 观察者接口
public interface Observer {
    
    
    void update(String state);
}

// 具体主题
public class ConcreteSubject implements Subject {
    
    
    private List<Observer> observers = new ArrayList<>();
    private String state;
    
    public String getState() {
    
    
        return state;
    }
    
    public void setState(String state) {
    
    
        this.state = state;
        notifyObservers();
    }
    
    public void attach(Observer observer) {
    
    
        observers.add(observer);
    }
    
    public void detach(Observer observer) {
    
    
        observers.remove(observer);
    }
    
    public void notifyObservers() {
    
    
        for (Observer observer : observers) {
    
    
            observer.update(state);
        }
    }
}

// 具体观察者A
public class ConcreteObserverA implements Observer {
    
    
    public void update(String state) {
    
    
        System.out.println("ConcreteObserverA: update, state=" + state);
    }
}

// 具体观察者B
public class ConcreteObserverB implements Observer {
    
    
    public void update(String state) {
    
    
        System.out.println("ConcreteObserverB: update, state=" + state);
    }
}

// 客户端代码
public class Client {
    
    
    public static void main(String[] args) {
    
    
        ConcreteSubject subject = new ConcreteSubject();
        
        Observer observerA = new ConcreteObserverA();
        Observer observerB = new ConcreteObserverB();
        
        subject.attach(observerA);
        subject.attach(observerB);
        
        subject.setState("state1");
        // 输出:
        // ConcreteObserverA: update, state=state1
        // ConcreteObserverB: update, state=state1
        
        subject.detach(observerA);
        
        subject.setState("state2");
        // 输出:
        // ConcreteObserverB: update, state=state2
    }
}

14. 策略模式(Strategy)

定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换,使得算法可以独立于使用它的客户而变化。

应用场景

  • 系统需要动态地在几种算法中选择一种
  • 系统中有多个类,它们的区别仅在于它们的行为
  • 需要屏蔽算法规则的复杂性

代码示例

// 策略接口
public interface Strategy {
    
    
    void algorithmInterface();
}

// 具体策略A
public class ConcreteStrategyA implements Strategy {
    
    
    public void algorithmInterface() {
    
    
        System.out.println("ConcreteStrategyA: algorithmInterface");
    }
}

// 具体策略B
public class ConcreteStrategyB implements Strategy {
    
    
    public void algorithmInterface() {
    
    
        System.out.println("ConcreteStrategyB: algorithmInterface");
    }
}

// 具体策略C
public class ConcreteStrategyC implements Strategy {
    
    
    public void algorithmInterface() {
    
    
        System.out.println("ConcreteStrategyC: algorithmInterface");
    }
}

// 上下文
public class Context {
    
    
    private Strategy strategy;
    
    public Context(Strategy strategy) {
    
    
        this.strategy = strategy;
    }
    
    public void setStrategy(Strategy strategy) {
    
    
        this.strategy = strategy;
    }
    
    public void contextInterface() {
    
    
        strategy.algorithmInterface();
    }
}

// 客户端代码
public class Client {
    
    
    public static void main(String[] args) {
    
    
        Context context = new Context(new ConcreteStrategyA());
        context.contextInterface();
        // 输出: ConcreteStrategyA: algorithmInterface
        
        context.setStrategy(new ConcreteStrategyB());
        context.contextInterface();
        // 输出: ConcreteStrategyB: algorithmInterface
        
        context.setStrategy(new ConcreteStrategyC());
        context.contextInterface();
        // 输出: ConcreteStrategyC: algorithmInterface
    }
}

15. 命令模式(Command)

将一个请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。

应用场景

  • 需要将请求发送者和接收者解耦
  • 需要支持命令的排队执行、记录日志、撤销/重做等操作
  • 需要支持宏命令(组合命令)

代码示例

// 命令接口
public interface Command {
    
    
    void execute();
    void undo();
}

// 具体命令A
public class ConcreteCommandA implements Command {
    
    
    private Receiver receiver;
    
    public ConcreteCommandA(Receiver receiver) {
    
    
        this.receiver = receiver;
    }
    
    public void execute() {
    
    
        receiver.actionA();
    }
    
    public void undo() {
    
    
        receiver.undoActionA();
    }
}

// 具体命令B
public class ConcreteCommandB implements Command {
    
    
    private Receiver receiver;
    
    public ConcreteCommandB(Receiver receiver) {
    
    
        this.receiver = receiver;
    }
    
    public void execute() {
    
    
        receiver.actionB();
    }
    
    public void undo() {
    
    
        receiver.undoActionB();
    }
}

// 接收者
public class Receiver {
    
    
    public void actionA() {
    
    
        System.out.println("Receiver: actionA");
    }
    
    public void undoActionA() {
    
    
        System.out.println("Receiver: undoActionA");
    }
    
    public void actionB() {
    
    
        System.out.println("Receiver: actionB");
    }
    
    public void undoActionB() {
    
    
        System.out.println("Receiver: undoActionB");
    }
}

// 调用者
public class Invoker {
    
    
    private Command command;
    
    public void setCommand(Command command) {
    
    
        this.command = command;
    }
    
    public void executeCommand() {
    
    
        command.execute();
    }
    
    public void undoCommand() {
    
    
        command.undo();
    }
}

// 客户端代码
public class Client {
    
    
    public static void main(String[] args) {
    
    
        Receiver receiver = new Receiver();
        
        Command commandA = new ConcreteCommandA(receiver);
        Command commandB = new ConcreteCommandB(receiver);
        
        Invoker invoker = new Invoker();
        
        invoker.setCommand(commandA);
        invoker.executeCommand();
        // 输出: Receiver: actionA
        
        invoker.undoCommand();
        // 输出: Receiver: undoActionA
        
        invoker.setCommand(commandB);
        invoker.executeCommand();
        // 输出: Receiver: actionB
        
        invoker.undoCommand();
        // 输出: Receiver: undoActionB
    }
}

四、设计模式的选择与应用

4.1 如何选择合适的设计模式

  1. 考虑设计模式解决的问题:每个设计模式都有其特定的应用场景和解决的问题。
  2. 考虑设计模式的意图:理解设计模式的意图,看是否与你的需求匹配。
  3. 考虑设计模式的适用性:评估设计模式是否适用于你的系统。
  4. 考虑设计模式的后果:了解使用设计模式可能带来的影响。

4.2 设计模式的组合使用

在实际应用中,常常需要组合使用多个设计模式来解决复杂问题。例如:

  • 组合模式 + 迭代器模式:遍历组合结构
  • 观察者模式 + 状态模式:状态变化时通知观察者
  • 策略模式 + 工厂模式:创建不同的策略对象

4.3 设计模式的优缺点

优点

  • 提高代码的可重用性
  • 提高代码的可维护性
  • 提高代码的可扩展性
  • 提高代码的可读性
  • 降低代码的耦合度

缺点

  • 增加系统的复杂度
  • 可能产生过多的类和对象
  • 可能影响系统的性能
  • 可能使代码难以理解

五、总结

设计模式是软件开发中的重要工具,能够帮助开发者更高效地解决常见问题。掌握设计模式可以提高代码的可维护性和可扩展性。在实际开发中,应该根据具体需求选择合适的设计模式,并注意设计模式的组合使用。

设计模式不是银弹,不能解决所有问题。过度使用设计模式可能导致代码复杂化,应该在实际应用中权衡利弊,选择最适合的解决方案。