设计模式
一,介绍
设计模式的分类
设计模式分为三大类:
创建型模式,共五种:工厂方法模式
、抽象工厂模式
、单例模式
、建造者模式
、原型模式
。
结构型模式,共七种:适配器模式
、装饰器模式
、代理模式
、外观模式
、桥接模式
、组合模式
、享元模式
。
行为型模式,共十一种:策略模式
、模板方法模式
、观察者模式
、迭代子模式
、责任链模式
、命令模式
、备忘录模式
、状态模式
、访问者模式
、中介者模式
、解释器模式
。
1.为什么要使用设计模式
代码组织和可读性:创建型设计模式提供了一种结构化的方式来组织代码,使得代码更加清晰、易读。它们定义了对象的创建和使用的规范,从而使代码逻辑更加明确,易于理解和维护。
对象创建的灵活性和可扩展性:创建型设计模式将对象创建的过程抽象出来,通过使用相应的模式,可以在不修改现有代码的情况下,改变对象的创建方式或者增加新的对象创建方式。这提供了一定的灵活性和可扩展性,使得系统更易于扩展和维护。
降低耦合度:创建型设计模式可以降低对象之间的耦合度。它们将对象的创建过程封装在一个单独的地方,使得对象之间的依赖关系减少到最小。这样,当需要更改某个具体类时,只需更改一个地方,而不必修改整个系统的代码。
代码重用:创建型设计模式可以促进代码的重用。通过使用工厂模式、原型模式等,可以复用已有的对象实例或者创建新的对象实例,避免了重复的对象创建过程。这样可以提高代码的效率和性能。
符合设计原则:创建型设计模式通常符合面向对象设计原则,如单一职责原则、开闭原则、依赖倒置原则等。它们强调将对象的创建和使用进行解耦,并提供了一种灵活的方式来管理对象的创建过程,使得系统更加可维护、可扩展。
总之,使用创建型设计模式可以帮助我们更好地组织和管理对象的创建过程,提高代码的可读性、可维护性和可扩展性。它们为我们提供了一些通用的解决方案,使得我们能够更加灵活地创建和使用对象,同时降低代码的耦合度,增强代码的可复用性和可扩展性。
1.创建型设计模式
当我们在设计Java应用程序时,经常会遇到需要创建对象的情况。创建型设计模式提供了一些通用的解决方案,帮助我们更好地组织和管理对象的创建过程,并提供灵活性和可扩展性
单例模式(Singleton Pattern): 单例模式确保一个类只有一个实例,并提供全局访问点。该模式常用于需要共享资源、控制资源访问、或限制某个类只能有一个实例的场景。
简单工厂模式(Simple Factory Pattern): 简单工厂模式通过一个工厂类根据特定参数来创建对象。使用简单工厂模式可以将对象的创建和使用分离,降低耦合度,使代码更具扩展性。
工厂方法模式(Factory Method Pattern): 工厂方法模式定义一个创建对象的接口,由子类决定实例化哪个类。与简单工厂模式不同的是,工厂方法模式将对象的实例化交给了子类,使得系统更加灵活,符合开闭原则。
抽象工厂模式(Abstract Factory Pattern): 抽象工厂模式提供一个接口用于创建相关或依赖对象的系列,而无需指定具体类。它隔离了具体类的实现细节,使得客户端可以与具体类的实例化过程解耦。
原型模式(Prototype Pattern): 原型模式通过复制现有对象来创建新的对象。它通过克隆或复制的方式来创建对象,避免了类似于new操作的开销,并且可以更加灵活地生成对象。
建造者模式(Builder Pattern): 建造者模式将一个复杂对象的构建过程和它的表示分离,使得同样的构建过程可以创建不同的表示。它将对象的构建步骤逐步细化,以创建复杂对象。
这些创建型设计模式都有各自的特点和适用场景,我们可以根据具体的需求选择合适的模式来创建对象。使用这些模式可以提高代码的可维护性、可读性和可扩展性,同时降低耦合度,增强代码的灵活性。
一,单例模式
在中,单例模式常见的实现方式有以下几种:
1. 饿汉式(Eager Initialization):
@Data
public class SingleExampleModeHungryHanStyle {// 在类加载时就创建实例private static SingleExampleModeHungryHanStyle instance = new SingleExampleModeHungryHanStyle();// 构造方法私有化,防止外部直接实例化private SingleExampleModeHungryHanStyle() {}// 提供获取实例的静态方法public static SingleExampleModeHungryHanStyle getInstance() {return instance;}// 可以在这里添加其他方法和属性// ...// 示例方法public void showMessage() {System.out.println("Hello, I am a singleton instance!");}
}
public static void main(String[] args) {
//todo SingleExampleModeHungryHanStyle 类的构造方法是私有的,所以外部无法直接实例化它。getInstance() 方法返回 Singleton 类的唯一实例,// 而且这个实例在类加载的时候就已经被创建了(饿汉式),因此可以通过 Singleton.getInstance() 来获取这个实例。// 获取单例实例SingleExampleModeHungryHanStyle singleton = SingleExampleModeHungryHanStyle.getInstance();// 调用示例方法singleton.showMessage();}
2. 懒汉式(Lazy Initialization):
public class SingleExampleModeLazyStyle {// 声明一个私有静态变量来保存单例实例private static SingleExampleModeLazyStyle instance;// 构造方法私有化,防止外部直接实例化private SingleExampleModeLazyStyle() {}// 提供获取实例的静态方法public static synchronized SingleExampleModeLazyStyle getInstance() {// 当 instance 为 null 时,创建新的实例if (instance == null) {instance = new SingleExampleModeLazyStyle();}return instance;}// 可以在这里添加其他方法和属性// ...// 示例方法public void showMessage() {System.out.println("Hello, I am a lazy singleton instance!");}
}
//todo SingleExampleModeLazyStyle 类的构造方法是私有的,所以外部无法直接实例化它。// getInstance() 方法通过检查 instance 是否为 null 来决定是否创建实例,这就是懒汉式的特点。// 需要注意的是,在多线程环境下,懒汉式的实现需要添加 synchronized 关键字来确保线程安全。// 获取单例实例SingleExampleModeLazyStyle singleton = SingleExampleModeLazyStyle.getInstance();// 调用示例方法singleton.showMessage();
3. 静态内部类方式(Static Inner Class):
/*** 单例模式-静态内部类*/
public class SingleExampleModeStaticInnerClass {// 私有化构造方法,防止外部直接实例化private SingleExampleModeStaticInnerClass() {}// 静态内部类,用于延迟加载单例实例private static class SingletonHolder {// 在静态内部类中创建单例实例private static final SingleExampleModeStaticInnerClass INSTANCE = new SingleExampleModeStaticInnerClass();}// 提供获取实例的静态方法public static SingleExampleModeStaticInnerClass getInstance() {return SingletonHolder.INSTANCE;}// 可以在这里添加其他方法和属性// ...// 示例方法public void showMessage() {System.out.println("Hello, I am a singleton instance created using static inner class!");}
}
//todo SingleExampleModeStaticInnerClass 类的构造方法是私有的,防止外部直接实例化。// 当 SingleExampleModeStaticInnerClass 类被加载时,静态内部类 SingletonHolder 不会被加载,// 直到调用 getInstance() 方法时才会加载 SingletonHolder 类。这种方式实现了延迟加载,// 同时由于静态内部类的加载是线程安全的,因此可以保证 Singleton 实例的线程安全性。// 获取单例实例SingleExampleModeStaticInnerClass singleton = SingleExampleModeStaticInnerClass.getInstance();// 调用示例方法singleton.showMessage();
4. 枚举方式(Enum):
/*** 单例模式-枚举类*/
public enum SingletonPatternEnumerationClass {// 定义单例的实例,这是一个枚举类型的常量,表示单例对象的唯一实例INSTANCE;// 可以在这里添加其他方法和属性// 示例方法public void showMessage() {System.out.println("Hello, I am a singleton instance created using enum!");}
}
//todo 在枚举中,INSTANCE 是一个枚举常量,代表了单例的唯一实例。由于枚举类型在 Java 中是线程安全的,// 并且枚举类型的构造方法只会被调用一次,因此通过枚举实现的单例模式是线程安全的且能够防止反序列化和反射攻击。// 在测试类 Main 中,我们获取了单例实例 singleton1 和 singleton2,然后通过比较它们的引用是否相等来验证单例模式的实现是否正确。//获取单例实例SingletonPatternEnumerationClass singleton1 = SingletonPatternEnumerationClass.INSTANCE;SingletonPatternEnumerationClass singleton2 = SingletonPatternEnumerationClass.INSTANCE;// 判断两个实例是否相等,预期输出为 trueSystem.out.println("singleton1 == singleton2: " + (singleton1 == singleton2));
5.双重检查锁(Double-Checked Locking)
/*** 单例模式-双重检查锁*/
public class SingleExampleDesignPatternDoubleCheckLock {// volatile关键字确保在多线程环境下singleton实例的可见性和顺序性private volatile static SingleExampleDesignPatternDoubleCheckLock instance;// 私有化构造方法,防止外部直接实例化对象private SingleExampleDesignPatternDoubleCheckLock() {}// 获取单例实例的方法public static SingleExampleDesignPatternDoubleCheckLock getInstance() {// 双重检查锁,提高效率并确保线程安全if (instance == null) {synchronized (SingleExampleDesignPatternDoubleCheckLock.class) {if (instance == null) {instance = new SingleExampleDesignPatternDoubleCheckLock();}}}return instance;}// 示例方法public void showMessage() {System.out.println("Hello, I am a singleton instance created using double-checked locking!");}
}
//todo 通过双重检查锁确保了线程安全性和懒加载。当 getInstance() 方法被调用时,// 会首先检查 instance 是否已经被实例化,如果没有,就进入同步块,再次检查 instance 是否为 null,如果为 null,// 则实例化一个新的 Singleton 对象。这种双重检查的方式可以避免多个线程同时进入同步块,提高了性能。// 在测试类 Main 中,我们获取了单例实例 singleton1 和 singleton2,然后通过比较它们的引用是否相等来验证单例模式的实现是否正确。//获取单例实例SingleExampleDesignPatternDoubleCheckLock singleton1 = SingleExampleDesignPatternDoubleCheckLock.getInstance();SingleExampleDesignPatternDoubleCheckLock singleton2 = SingleExampleDesignPatternDoubleCheckLock.getInstance();// 判断两个实例是否相等,预期输出为 trueSystem.out.println("singleton1 == singleton2: " + (singleton1 == singleton2));// 调用示例方法singleton1.showMessage();singleton2.showMessage();
二,工厂方法模式
1.工厂方法模式(Factory Method Pattern)
工厂方法模式(Factory Method Pattern)是一种创建型设计模式,用于创建对象的实例化过程。在工厂方法模式中,我们不直接实例化对象,而是定义一个创建对象的接口,让子类来决定实例化哪个类。这样做的好处是可以将对象的实例化延迟到子类中,从而实现了更好的松耦合性。
在工厂方法模式中,通常会有一个抽象的工厂类和多个具体的工厂子类,每个子类负责创建一种具体的对象。这些具体的工厂子类根据不同的情况来创建不同的对象,从而实现了对象的实例化过程的灵活性。
/***工厂接口*
**/
public interface Factory {Product createProduct();
}
/*** 抽象产品接口*/
public interface Product {void show();
}
/*** 具体工厂A,用于创建具体产品A*/
public class ConcreteFactoryA implements Factory {@Overridepublic Product createProduct() {return new ConcreteProductA();}
}
/*** 具体工厂B,用于创建具体产品B
*/
public class ConcreteFactoryB implements Factory {@Overridepublic Product createProduct() {return new ConcreteProductB();}
}
public class ConcreteProductA implements Product {@Overridepublic void show() {System.out.println("Concrete Product A");}
}
public class ConcreteProductB implements Product {@Overridepublic void show() {System.out.println("Concrete Product B");}
}
//todo 在这个示例中,我们首先定义了一个抽象产品接口 Product,它包含了一个 show() 方法。然后我们创建了两个具体产品类 ConcreteProductA 和 ConcreteProductB,它们分别实现了 Product 接口,并实现了各自的 show() 方法。// 接着,我们定义了一个工厂接口 Factory,它包含了一个 createProduct() 方法用于创建产品。然后我们创建了两个具体工厂类 ConcreteFactoryA 和 ConcreteFactoryB,它们分别实现了 Factory 接口,并实现了各自的 createProduct() 方法。// 在测试类 Main 中,我们分别使用具体工厂A和具体工厂B来创建产品,然后调用产品的 show() 方法展示产品的信息。这样,通过工厂方法模式,我们可以根据不同的工厂来创建不同的产品,实现了产品的解耦和扩展。//创建具体工厂AFactory factoryA = new ConcreteFactoryA();// 工厂A生产产品AProduct productA = factoryA.createProduct();// 调用产品A的方法productA.show();// 创建具体工厂BFactory factoryB = new ConcreteFactoryB();// 工厂B生产产品BProduct productB = factoryB.createProduct();// 调用产品B的方法productB.show();
注意,工厂方法模式适用于需要扩展产品族的情况,如果只需创建单一产品,可以考虑使用简单工厂模式。
三,抽象工厂模式
1.介绍
抽象工厂模式可以看作是工厂方法模式的扩展。工厂方法模式只能创建单个产品族中的产品对象,而抽象工厂模式则可以创建多个产品族中的产品对象。
在工厂方法模式中,我们定义了一个抽象的工厂接口,具体的工厂类实现了这个接口,分别负责创建属于自己产品线的产品对象。每个产品对象也都需要实现对应的抽象产品接口。客户端代码通过工厂接口调用具体的工厂类来获得所需的产品对象。
在抽象工厂模式中,我们定义了一个抽象工厂接口,具体的工厂类同样实现这个接口,不同的是,每个工厂类负责创建多个产品族中的产品对象。也就是说,每个工厂类不仅要定义生产一种产品的抽象方法,还会定义生产不同产品族的抽象方法。同样地,每个产品对象都需要实现对应的抽象产品接口。
// 抽象产品A
public interface AbstractProductA {void use();
}
// 具体产品A1
public class ConcreteProductA1 implements AbstractProductA {@Overridepublic void use() {System.out.println("使用具体产品A1");}
}
// 具体产品A2
public class ConcreteProductA2 implements AbstractProductA {@Overridepublic void use() {System.out.println("使用具体产品A2");}
}
// 抽象产品B
public interface AbstractProductB {void eat();
}
// 具体产品B1
public class ConcreteProductB1 implements AbstractProductB {@Overridepublic void eat() {System.out.println("吃具体产品B1");}
}
// 具体产品B2
public class ConcreteProductB2 implements AbstractProductB {@Overridepublic void eat() {System.out.println("吃具体产品B2");}
}
// 抽象工厂接口
public interface AbstractFactory {AbstractProductA createProductA();AbstractProductB createProductB();
}
// 具体工厂1
public class ConcreteFactory1 implements AbstractFactory {@Overridepublic AbstractProductA createProductA() {return new ConcreteProductA1();}@Overridepublic AbstractProductB createProductB() {return new ConcreteProductB1();}
}
// 具体工厂2
public class ConcreteFactory2 implements AbstractFactory {@Overridepublic AbstractProductA createProductA() {return new ConcreteProductA2();}@Overridepublic AbstractProductB createProductB() {return new ConcreteProductB2();}
}
// 客户端
public public class Client {public static void main(String[] args) {AbstractFactory factory1 = new ConcreteFactory1();AbstractProductA productA1 = factory1.createProductA();AbstractProductB productB1 = factory1.createProductB();productA1.use();productB1.eat();AbstractFactory factory2 = new ConcreteFactory2();AbstractProductA productA2 = factory2.createProductA();AbstractProductB productB2 = factory2.createProductB();productA2.use();productB2.eat();}
}
四,建造者模式
1,介绍
建造者模式的基本思想是将一个复杂对象的构建过程分解成若干个简单的步骤,然后用一个统一的接口来表示这些步骤,从而使得同样的构建过程可以构建不同的表示。在建造者模式中,指挥者类负责协调各个构建者来完成对象的构建,客户端只需要与指挥者类进行交互即可。
建造者模式(Builder Pattern)是一种创建型设计模式,它允许将复杂对象的构建过程与其表示相分离。通过使用相同的构建过程可以创建不同的表示。
// 电脑类
public class Computer {// 电脑的属性private String cpu;private String gpu;private int ramSize;private int storageSize;// 构造函数私有化,防止外部直接创建对象private Computer() {}// Getter方法public String getCpu() {return cpu;}public String getGpu() {return gpu;}public int getRamSize() {return ramSize;}public int getStorageSize() {return storageSize;}// 内部Builder类用于构建Computer对象public static class Builder {private Computer computer;// Builder的构造函数,用于创建新的Computer对象public Builder() {computer = new Computer();}// 设置CPUpublic Builder setCpu(String cpu) {computer.cpu = cpu;return this;}// 设置GPUpublic Builder setGpu(String gpu) {computer.gpu = gpu;return this;}// 设置内存大小public Builder setRamSize(int ramSize) {computer.ramSize = ramSize;return this;}// 设置存储大小public Builder setStorageSize(int storageSize) {computer.storageSize = storageSize;return this;}// 构建Computer对象public Computer build() {return computer;}}
}
//todo 我们定义了一个Computer类,它具有属性cpu、gpu、ramSize和storageSize。然后我们定义了一个Builder内部类,用于构建Computer对象。通过在Builder类中设置各种属性,并最终调用build()方法来构建Computer对象。// 在Main类中,我们展示了如何使用建造者模式来创建不同配置的电脑对象。我们首先创建一个Builder对象,然后使用该对象设置电脑的各种属性,最后调用build()方法来获取最终的Computer对象。//创建一个Builder对象Computer.Builder builder = new Computer.Builder();// 使用Builder对象设置属性Computer computer = builder.setCpu("Intel i9").setGpu("NVIDIA RTX 3080").setRamSize(32).setStorageSize(2000).build();// 输出电脑配置信息System.out.println("CPU: " + computer.getCpu());System.out.println("GPU: " + computer.getGpu());System.out.println("RAM Size: " + computer.getRamSize() + "GB");System.out.println("Storage Size: " + computer.getStorageSize() + "GB");
五.原型模式
1.介绍
原型模式是一种创建型设计模式,它允许创建复杂对象的副本,同时又能保持其结构不变。在原型模式中,通过拷贝来创建新的对象,而不是通过new来创建。这样可以避免在代码中显式调用构造函数,从而提高代码灵活性和可维护性。
package com.example.myexcel.designPatterns;// 实现Cloneable接口的原型类
public class Shape implements Cloneable {private String type;// 构造函数public Shape(String type) {this.type = type;}// Getter和Setter方法public String getType() {return type;}public void setType(String type) {this.type = type;}// 重写clone()方法,实现浅拷贝@Overridepublic Object clone() throws CloneNotSupportedException {return super.clone();}
}
//todo 我们定义了一个Shape类,它实现了Cloneable接口。Shape类具有一个type属性,表示形状的类型。我们重写了clone()方法来实现浅拷贝。在Main类中,我们创建了一个原型对象shape1,然后通过调用clone()方法来创建一个克隆对象shape2。最后,我们修改了克隆对象的type属性,并输出了原型对象和克隆对象的类型,以验证原型模式的使用。// 需要注意的是,这里实现的是浅拷贝,如果Shape类中有引用类型的属性,需要考虑深拷贝的实现方式。//创建原型对象Shape shape1 = new Shape("Circle");try {// 克隆原型对象Shape shape2 = (Shape) shape1.clone();// 修改克隆对象的属性shape2.setType("Square");// 输出原型对象和克隆对象的类型System.out.println("Original object type: " + shape1.getType());System.out.println("Cloned object type: " + shape2.getType());} catch (CloneNotSupportedException e) {e.printStackTrace();}
2.结构型设计模式
一,适配器模式
1.介绍
适配器模式(Adapter Pattern)是一种结构型设计模式,用于将一个类的接口转换成客户端所期望的另一个接口。适配器模式通常用于解决两个不兼容接口之间的兼容性问题。
1.类适配器模式
// 目标接口
public interface Target {void request();
}
// 需要适配的类
public class Adaptee {public void specificRequest() {System.out.println("Adaptee's specific request");}
}
//todo Target是目标接口,Adaptee是需要适配的类。ClassAdapter是适配器类,它继承了Adaptee类并实现了Target接口。在ClassAdapter中,通过调用specificRequest()方法来实现request()方法。Target adapter = new ClassAdapter();adapter.request();
2.对象适配器模式
// 对象适配器
public class ObjectAdapter implements Target {private Adaptee adaptee;public ObjectAdapter(Adaptee adaptee) {this.adaptee = adaptee;}@Overridepublic void request() {adaptee.specificRequest();}
}
//todo 在对象适配器模式中,适配器类持有一个需要适配的对象,在适配器类中调用该对象的方法来实现目标接口。在这个示例中,ObjectAdapter持有一个Adaptee对象,并在request()方法中调用了Adaptee的specificRequest()方法。Adaptee adaptee = new Adaptee();Target adapter = new ObjectAdapter(adaptee);adapter.request();
通过适配器模式,我们可以使得原本不兼容的接口能够协同工作,达到代码复用和解耦的目的。
二,桥接模式
1.介绍
桥接模式(Bridge Pattern)是一种结构型设计模式,它将抽象和实现解耦,使它们可以独立地变化。桥接模式通过组合而不是继承的方式实现了这种解耦。
// 实现部分接口
public interface Implementor {void operationImpl();
}
// 具体实现类 A
public class ConcreteImplementorA implements Implementor {@Overridepublic void operationImpl() {System.out.println("具体实现类 A 的操作");}
}
// 具体实现类 B
public class ConcreteImplementorB implements Implementor {@Overridepublic void operationImpl() {System.out.println("具体实现类 B 的操作");}
}
// 抽象部分类
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() {System.out.println("扩展抽象部分类的操作");implementor.operationImpl();}
}
通过桥接模式,我们可以将抽象和实现解耦,使它们可以独立变化。这样一来,如果需要新增其他的具体实现类,只需要扩展相应的实现接口和具体实现类即可,不需要修改原有的代码,符合开闭原则。
三,组合模式
1.介绍
组合模式是一种结构型设计模式,它将对象组合成树形结构以表示"部分-整体"的层次结构,使得客户端可以统一使用单个对象和组合对象。
// 组合模式中的抽象构件
public interface Component {void operation();
}
// 组合模式中的叶子构件
public class Leaf implements Component {private String name;public Leaf(String name) {this.name = name;}@Overridepublic void operation() {System.out.println("Leaf " + name + " 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 component : children) {component.operation();}}
}
//todo 我们定义了Component接口作为组合模式中的抽象构件,包含了operation()方法。Leaf类表示叶子构件,它实现了Component接口并实现了具体的操作。Composite类表示复合构件,它包含了一个List<Component>用于存储子构件,并实现了operation()方法来递归调用所有子构件的操作。////在测试类Main中,我们创建了叶子构件和复合构件,并将它们按照树形结构组合起来。最后,调用顶层复合构件的operation()方法,所有子构件的操作都会被依次执行。////组合模式使得客户端可以统一处理单个对象和组合对象,从而简化了代码结构,并且方便地增加、删除和组织对象// 创建叶子构件Leaf leaf1 = new Leaf("1");Leaf leaf2 = new Leaf("2");// 创建复合构件Composite composite1 = new Composite();Composite composite2 = new Composite();// 将叶子构件添加到复合构件中composite1.add(leaf1);composite2.add(leaf2);// 创建顶层复合构件Composite composite = new Composite();composite.add(composite1);composite.add(composite2);// 调用顶层复合构件的操作方法,递归执行所有子构件的操作composite.operation();
四,装饰模式
1.介绍
装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许你动态地将新功能添加到对象中,同时保持了与原始对象接口的一致性。
// 定义一个接口
public interface Component {void operation();
}
// 具体实现类
public class ConcreteComponent implements Component {@Overridepublic void operation() {System.out.println("执行具体对象的操作");}
}
// 装饰器抽象类
public abstract class Decorator implements Component {protected Component component;public Decorator(Component component) {this.component = component;}@Overridepublic void operation() {if (component != null) {component.operation();}}
}
// 具体装饰器类A
public class ConcreteDecoratorA extends Decorator {public ConcreteDecoratorA(Component component) {super(component);}@Overridepublic void operation() {super.operation();addedBehavior();}private void addedBehavior() {System.out.println("为具体对象A扩展的功能");}
}
// 具体装饰器类B
public class ConcreteDecoratorB extends Decorator {public ConcreteDecoratorB(Component component) {super(component);}@Overridepublic void operation() {super.operation();addedBehavior();}private void addedBehavior() {System.out.println("为具体对象B扩展的功能");}
}
// 客户端代码
public class Client {public static void main(String[] args) {// 创建具体对象Component component = new ConcreteComponent();// 使用具体装饰器A包装具体对象Component decoratorA = new ConcreteDecoratorA(component);decoratorA.operation();// 使用具体装饰器B包装具体对象Component decoratorB = new ConcreteDecoratorB(component);decoratorB.operation();}
}
通过装饰器模式,我们可以灵活地组合各个装饰器对象,动态地添加新的功能到对象中,同时保持了与原始对象接口的一致性,符合开闭原则。
五,外观模式
1.介绍
外观设计模式(Facade Pattern)是一种结构型设计模式,它提供了一个统一的接口,用来访问子系统中的一群接口。它定义了一个高层接口,使得客户端更容易地使用子系统。
// 子系统类 A
public class SubSystemA {public void operationA() {System.out.println("子系统类 A 的操作");}
}// 子系统类 B
class SubSystemB {public void operationB() {System.out.println("子系统类 B 的操作");}
}// 子系统类 C
class SubSystemC {public void operationC() {System.out.println("子系统类 C 的操作");}
}// 外观类
class Facade {private SubSystemA subsystemA;private SubSystemB subsystemB;private SubSystemC subsystemC;public Facade() {this.subsystemA = new SubSystemA();this.subsystemB = new SubSystemB();this.subsystemC = new SubSystemC();}public void operation() {System.out.println("外观类的操作");subsystemA.operationA();subsystemB.operationB();subsystemC.operationC();}public static void main(String[] args) {//todo SubSystemA、SubSystemB、SubSystemC 是子系统类,它们分别封装了子系统的一部分功能。//Facade 是外观类,它包含了对子系统类的引用,并提供了一个统一的接口 operation,客户端通过这个接口来访问子系统的功能。//在客户端代码中,只需要创建外观类的对象,并调用其统一的接口方法,而不需要直接与子系统类交互,从而实现了对子系统的屏蔽和解耦。Facade facade = new Facade();facade.operation();}
}
通过外观设计模式,客户端可以更容易地访问子系统中的一群接口,而不必知道底层子系统的具体实现,从而实现了松耦合和高内聚。
六,享元模式
1.介绍
享元设计模式(Flyweight Pattern)是一种结构型设计模式,它旨在通过共享尽可能多的对象来有效地支持大量细粒度对象的复用。
享元设计模式通过将对象的状态分为内部状态和外部状态来实现对象的共享。内部状态是指可以被共享的对象的状态,而外部状态是不可共享的对象的状态。
// 享元接口
interface Flyweight {void operation();
}// 具体享元类
class ConcreteFlyweight implements Flyweight {private String intrinsicState;public ConcreteFlyweight(String intrinsicState) {this.intrinsicState = intrinsicState;}@Overridepublic void operation() {System.out.println("具体享元对象:" + intrinsicState);}
}// 享元工厂类
class FlyweightFactory {private HashMap<String, Flyweight> flyweights = new HashMap<>();// 获取享元对象public Flyweight getFlyweight(String key) {if (flyweights.containsKey(key)) {return flyweights.get(key);} else {Flyweight flyweight = new ConcreteFlyweight(key);flyweights.put(key, flyweight);return flyweight;}}
}// 客户端class Client {public static void main(String[] args) {//todo Flyweight: 享元接口,定义了享元对象的操作方法 operation()。//ConcreteFlyweight: 具体享元类,实现了 Flyweight 接口,包含了享元对象的内部状态,并实现了操作方法。//FlyweightFactory: 享元工厂类,负责管理和提供享元对象。它维护一个享元对象的池子(通常是一个哈希表),根据外部状态来返回享元对象,如果不存在则创建新的享元对象并加入池子中。//Client: 客户端代码,使用享元工厂来获取享元对象,并调用其操作方法。//在示例中,我们创建了一个享元工厂 FlyweightFactory,它维护了一个哈希表用于存储享元对象。客户端通过享元工厂获取享元对象,并调用其操作方法。对于相同的 key,享元工厂只会返回同一个享元对象,从而实现了对象的共享。FlyweightFactory factory = new FlyweightFactory();Flyweight flyweight1 = factory.getFlyweight("key1");flyweight1.operation();Flyweight flyweight2 = factory.getFlyweight("key2");flyweight2.operation();Flyweight flyweight3 = factory.getFlyweight("key1");flyweight3.operation();// 对于相同的 key,享元工厂只会返回同一个对象,而不会创建新的对象System.out.println(flyweight1 == flyweight3); // true}
}
通过享元设计模式,我们可以有效地复用细粒度对象,并减少内存消耗。当多个对象共享一些相似的状态时,可以使用享元模式来减少对象的数量,提高系统的性能。
七,代理模式
1.介绍
代理设计模式是一种结构型设计模式,它允许通过提供一个代理对象来控制对另一个对象的访问。这种模式可以用于实现许多功能,例如远程代理、虚拟代理、保护代理等。
// 接口
interface Subject {void request();
}// 具体主题类
class RealSubject implements Subject {@Overridepublic void request() {System.out.println("RealSubject: 处理请求");}
}// 代理类
class Proxy implements Subject {private RealSubject realSubject;public Proxy() {this.realSubject = new RealSubject();}@Overridepublic void request() {System.out.println("Proxy: 调用代理对象");// 在调用目标对象之前或之后可以执行一些额外的操作realSubject.request();}
}// 客户端
class Clients {public static void main(String[] args) {//todo Subject 是主题接口,定义了客户端与目标对象之间的接口。//RealSubject 是具体的主题类,实现了 Subject 接口,是真正执行请求的对象。//Proxy 是代理类,实现了 Subject 接口,包含一个对 RealSubject 对象的引用,在调用目标对象之前或之后可以执行一些额外的操作。//在客户端代码中,通过创建代理对象来访问目标对象,客户端只需与代理对象交互,而不需要直接与目标对象交互。//代理模式的核心思想是通过一个代理对象来控制对其他对象的访问,可以在不改变目标对象的情况下增加一些额外的功能。这种设计模式可以用于实现访问控制、延迟加载、日志记录等功能。Subject proxy = new Proxy();proxy.request();}
}
3.行为型设计模式
一,访问者模式
1.介绍
访问者模式(Visitor Pattern)是一种行为型设计模式,它能够对不同的对象结构进行遍历,并在不修改这些对象的前提下定义新的操作。通过使用访问者模式,我们可以将数据结构与作用于数据结构上的操作分离开来,从而使得操作集合可以独立变化而不影响数据结构。
// 抽象元素接口
interface Element {void accept(Visitor visitor);
}// 具体元素类 A
class ConcreteElementA implements Element {@Overridepublic void accept(Visitor visitor) {visitor.visit(this);}public String operationA() {return "具体元素类 A 的操作";}
}// 具体元素类 B
class ConcreteElementB implements Element {@Overridepublic void accept(Visitor visitor) {visitor.visit(this);}public String operationB() {return "具体元素类 B 的操作";}
}// 抽象访问者接口
interface Visitor {void visit(ConcreteElementA element);void visit(ConcreteElementB element);
}// 具体访问者类
class ConcreteVisitor implements Visitor {@Overridepublic void visit(ConcreteElementA element) {System.out.println("具体访问者访问:" + element.operationA());}@Overridepublic void visit(ConcreteElementB element) {System.out.println("具体访问者访问:" + element.operationB());}
}// 对象结构类
class ObjectStructure {private Element[] elements;public ObjectStructure() {elements = new Element[]{new ConcreteElementA(), new ConcreteElementB()};}public void accept(Visitor visitor) {for (Element element : elements) {element.accept(visitor);}}
}// 客户端
class Client1 {public static void main(String[] args) {//todo Element 是抽象元素接口,定义了一个 accept 方法,用于接受访问者的访问。//ConcreteElementA 和 ConcreteElementB 是具体元素类,实现了 Element 接口,并分别实现了自己的操作方法。//Visitor 是抽象访问者接口,定义了多个 visit 方法,用于访问不同类型的具体元素。//ConcreteVisitor 是具体访问者类,实现了 Visitor 接口,针对不同的具体元素实现了相应的访问方法。//ObjectStructure 是对象结构类,用于存储元素对象,并提供一个 accept 方法,用于接受访问者的访问。//在客户端代码中,通过创建具体的访问者对象和对象结构对象,并调用对象结构的 accept 方法来实现对元素的访问。//访问者模式的核心思想是将操作从元素类中分离出来,封装到访问者类中,使得可以在不改变元素类的情况下定义新的操作。这种设计模式可以用于处理数据结构与操作之间的解耦,从而提高系统的灵活性和可扩展性。ObjectStructure objectStructure = new ObjectStructure();Visitor visitor = new ConcreteVisitor();objectStructure.accept(visitor);}
}
二,模板方法
1.介绍
模板方法模式(Template Method Pattern)是一种行为型设计模式,它定义了一个算法的骨架,将某些步骤的具体实现延迟到子类中。在模板方法模式中,将通用的算法逻辑放在抽象类中,而具体的实现细节由子类来完成。
// 抽象类定义了一个模板方法,其中包含了算法的骨架,将某些步骤延迟到子类中实现
abstract class AbstractClass {// 模板方法,定义了算法的骨架public final void templateMethod() {step1();step2();step3();hook();}// 抽象方法,由子类实现abstract void step1();// 抽象方法,由子类实现abstract void step2();// 具体方法,已经有默认实现,子类可以选择性地覆盖void step3() {System.out.println("AbstractClass: Step 3 (default implementation)");}// 钩子方法,子类可以选择性地覆盖void hook() {System.out.println("AbstractClass: Hook (default implementation)");}
}// 具体子类A
class ConcreteClassA extends AbstractClass {@Overridevoid step1() {System.out.println("ConcreteClassA: Step 1");}@Overridevoid step2() {System.out.println("ConcreteClassA: Step 2");}@Overridevoid hook() {System.out.println("ConcreteClassA: Hook");}
}// 具体子类B
class ConcreteClassB extends AbstractClass {@Overridevoid step1() {System.out.println("ConcreteClassB: Step 1");}@Overridevoid step2() {System.out.println("ConcreteClassB: Step 2");}@Overridevoid step3() {System.out.println("ConcreteClassB: Step 3 (overridden)");}
}// 客户端代码
class Client2 {public static void main(String[] args) {//todo AbstractClass: 抽象类定义了一个模板方法 templateMethod(),其中包含了算法的骨架,以及一些具体方法和钩子方法。其中,step1() 和 step2() 是抽象方法,需要由子类实现;step3() 和 hook() 是具体方法,已经有默认实现,子类可以选择性地覆盖。//ConcreteClassA、ConcreteClassB: 具体子类实现了抽象类中的抽象方法,并根据需要覆盖了具体方法和钩子方法。//Client: 客户端代码创建具体子类对象,并调用模板方法 templateMethod(),从而执行算法的骨架。在示例中,我们创建了两个具体子类对象,并调用其模板方法,展示了不同子类的行为差异。AbstractClass classA = new ConcreteClassA();classA.templateMethod();System.out.println();AbstractClass classB = new ConcreteClassB();classB.templateMethod();}
}
需要注意的是,模板方法模式将通用的算法逻辑放在抽象类中,而具体的实现细节由子类来完成。这样可以提高代码的可复用性和可扩展性,同时也将算法的变化封装在子类中,使得子类可以更自由地进行扩展和变化。
三,策略模式
1.介绍
策略模式(Strategy Pattern)是一种行为型设计模式,它定义了一系列算法,并将每个算法封装在独立的策略类中,使得它们可以互相替换。通过使用策略模式,可以使得算法的变化独立于使用算法的客户端。
// 策略接口,定义了所有支持的算法的公共接口
interface Strategy {int doOperation(int num1, int num2);
}// 具体策略A
class ConcreteStrategyAdd implements Strategy {@Overridepublic int doOperation(int num1, int num2) {return num1 + num2;}
}// 具体策略B
class ConcreteStrategySubtract implements Strategy {@Overridepublic int doOperation(int num1, int num2) {return num1 - num2;}
}// 具体策略C
class ConcreteStrategyMultiply implements Strategy {@Overridepublic 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);}
}// 客户端代码
class Client3 {public static void main(String[] args) {//todo Strategy: 策略接口,定义了所有支持的算法的公共接口 doOperation()。//ConcreteStrategyAdd、ConcreteStrategySubtract、ConcreteStrategyMultiply: 具体策略类,实现了策略接口,并提供了具体的算法实现。//Context: 上下文类,持有一个策略对象,并在需要时调用策略对象的方法来执行算法。客户端通过上下文对象与具体的策略进行交互,实现了解耦。//Client: 客户端代码,创建上下文对象并选择具体的策略,然后调用上下文对象的方法执行算法。//在示例中,我们定义了三种不同的算法:加法、减法和乘法,并分别实现了对应的具体策略类。通过上下文类 Context,我们可以在运行时选择不同的策略来执行不同的算法,从而实现了算法的独立性和灵活性。// 创建上下文对象,选择使用具体的策略Context context = new Context(new ConcreteStrategyAdd());// 使用策略进行操作System.out.println("10 + 5 = " + context.executeStrategy(10, 5));// 切换策略context = new Context(new ConcreteStrategySubtract());// 使用新的策略进行操作System.out.println("10 - 5 = " + context.executeStrategy(10, 5));// 切换策略context = new Context(new ConcreteStrategyMultiply());// 使用新的策略进行操作System.out.println("10 * 5 = " + context.executeStrategy(10, 5));}
}
策略模式通过将算法封装在独立的策略类中,使得它们可以独立变化和互相替换。这样可以提高代码的灵活性和可维护性,同时也将算法的变化从客户端代码中解耦出来,使得客户端可以更加专注于业务逻辑。
四,状态模式
1.介绍
状态模式(State Pattern)是一种行为型设计模式,它允许对象在其内部状态发生改变时改变它的行为。通过使用状态模式,可以将一个对象的状态从其行为中分离出来,使得对象可以根据状态来改变其行为。
// 策略接口,定义了所有支持的算法的公共接口
interface Strategy {int doOperation(int num1, int num2);
}// 具体策略A
class ConcreteStrategyAdd implements Strategy {@Overridepublic int doOperation(int num1, int num2) {return num1 + num2;}
}// 具体策略B
class ConcreteStrategySubtract implements Strategy {@Overridepublic int doOperation(int num1, int num2) {return num1 - num2;}
}// 具体策略C
class ConcreteStrategyMultiply implements Strategy {@Overridepublic int doOperation(int num1, int num2) {return num1 * num2;}
}// 上下文类,使用策略的类
class Context1 {private Strategy strategy;public Context1(Strategy strategy) {this.strategy = strategy;}// 执行策略public int executeStrategy(int num1, int num2) {return strategy.doOperation(num1, num2);}
}// 客户端代码
class Client3 {public static void main(String[] args) {//todo Strategy: 策略接口,定义了所有支持的算法的公共接口 doOperation()。//ConcreteStrategyAdd、ConcreteStrategySubtract、ConcreteStrategyMultiply: 具体策略类,实现了策略接口,并提供了具体的算法实现。//Context: 上下文类,持有一个策略对象,并在需要时调用策略对象的方法来执行算法。客户端通过上下文对象与具体的策略进行交互,实现了解耦。//Client: 客户端代码,创建上下文对象并选择具体的策略,然后调用上下文对象的方法执行算法。//在示例中,我们定义了三种不同的算法:加法、减法和乘法,并分别实现了对应的具体策略类。通过上下文类 Context,我们可以在运行时选择不同的策略来执行不同的算法,从而实现了算法的独立性和灵活性。// 创建上下文对象,选择使用具体的策略Context1 context1 = new Context1(new ConcreteStrategyAdd());// 使用策略进行操作System.out.println("10 + 5 = " + context1.executeStrategy(10, 5));// 切换策略context1 = new Context1(new ConcreteStrategySubtract());// 使用新的策略进行操作System.out.println("10 - 5 = " + context1.executeStrategy(10, 5));// 切换策略context1 = new Context1(new ConcreteStrategyMultiply());// 使用新的策略进行操作System.out.println("10 * 5 = " + context1.executeStrategy(10, 5));}
}
状态模式通过将状态封装在独立的状态类中,使得状态可以独立变化和互相替换。这样可以提高代码的灵活性和可维护性,同时也将状态的变化从客户端代码中解耦出来,使得客户端可以更加专注于业务逻辑。
五,观察者模式
1.介绍
观察者模式(Observer Pattern)是一种行为型设计模式,它定义了一种一对多的依赖关系,其中一个对象(称为主题或可观察者)状态发生变化时会自动通知其他依赖该对象的对象(称为观察者),使得观察者可以更新自己的状态。
// 主题接口
interface Subject {void registerObserver(Observer observer);void removeObserver(Observer observer);void notifyObservers();
}// 具体主题
class ConcreteSubject implements Subject {private List<Observer> observers = new ArrayList<>();private int state;public int getState() {return state;}public void setState(int state) {this.state = state;notifyObservers();}@Overridepublic void registerObserver(Observer observer) {observers.add(observer);}@Overridepublic void removeObserver(Observer observer) {observers.remove(observer);}@Overridepublic void notifyObservers() {for (Observer observer : observers) {observer.update();}}
}// 观察者接口
interface Observer {void update();
}// 具体观察者
class ConcreteObserver implements Observer {private ConcreteSubject subject;public ConcreteObserver(ConcreteSubject subject) {this.subject = subject;subject.registerObserver(this);}@Overridepublic void update() {System.out.println("Observer updated, state is: " + subject.getState());}
}// 测试类
class Main {public static void main(String[] args) {//todo 在这个示例中,我们定义了主题接口Subject和观察者接口Observer,并分别实现了具体主题ConcreteSubject和具体观察者ConcreteObserver。主题维护了一个观察者列表,并提供了注册、移除和通知观察者的方法。当主题的状态发生改变时,它会遍历观察者列表,通知所有观察者进行更新。////在测试类Main中,我们创建了一个具体主题ConcreteSubject和两个具体观察者ConcreteObserver,并将观察者注册到主题中。然后,改变主题的状态,观察者会收到通知并进行更新操作。////观察者模式可以实现对象之间的松耦合,当一个对象的状态发生变化时,其他依赖于它的对象都会得到通知,从而实现对象间的协作。ConcreteSubject subject = new ConcreteSubject();// 创建两个具体观察者,并将它们注册到主题中ConcreteObserver observer1 = new ConcreteObserver(subject);ConcreteObserver observer2 = new ConcreteObserver(subject);// 改变主题的状态,触发观察者的更新subject.setState(10);}
}
六,备忘录模式
1.介绍
备忘录模式(Memento Pattern)是一种行为型设计模式,它允许你保存和恢复一个对象的内部状态,而不会破坏其封装性。备忘录有三个角色:原始对象、备忘录和负责人。
// 备忘录类
class Memento {private String state;public Memento(String state) {this.state = state;}public String getState() {return state;}
}// 原发器类
class Originator {private String state;public void setState(String state) {System.out.println("设置状态为:" + state);this.state = state;}public String getState() {return state;}public Memento saveStateToMemento() {return new Memento(state);}public void getStateFromMemento(Memento memento) {state = memento.getState();System.out.println("恢复状态为:" + state);}
}// 负责人类
class Caretaker {private Memento memento;public void setMemento(Memento memento) {this.memento = memento;}public Memento getMemento() {return memento;}
}// 客户端
class Client01 {public static void main(String[] args) {//todo Memento 是备忘录类,用于存储原发器对象的内部状态。//Originator 是原发器类,它有一个可以改变状态的方法 setState(),以及可以将当前状态保存到备忘录的方法 saveStateToMemento() 和从备忘录中恢复状态的方法 getStateFromMemento()。//Caretaker 是负责人类,负责保存备忘录对象,但不对备忘录对象的内容进行操作。//在客户端代码中,首先创建原发器对象和负责人对象,然后设置原发器的状态,并保存备忘录;接着修改原发器的状态,并再次保存备忘录;最后通过负责人对象来获取备忘录,并恢复原发器的状态。// 创建原发器对象Originator originator = new Originator();// 创建负责人对象Caretaker caretaker = new Caretaker();// 设置原发器状态,并保存备忘录originator.setState("状态1");caretaker.setMemento(originator.saveStateToMemento());// 修改原发器状态,并保存备忘录originator.setState("状态2");caretaker.setMemento(originator.saveStateToMemento());// 恢复原发器状态originator.getStateFromMemento(caretaker.getMemento());}
}
七,中介这模式
1.介绍
中介者模式(Mediator Pattern)是一种行为型设计模式,它能够减少对象之间的依赖关系,使得对象不需要显示地相互引用,从而使耦合性降低,系统易于扩展。
// 中介者接口
interface Mediator {void send(String message, Colleague colleague);
}// 具体中介者类
class ConcreteMediator implements Mediator {private ColleagueA colleagueA;private ColleagueB colleagueB;public void setColleagueA(ColleagueA colleagueA) {this.colleagueA = colleagueA;}public void setColleagueB(ColleagueB colleagueB) {this.colleagueB = colleagueB;}@Overridepublic void send(String message, Colleague colleague) {if (colleague == colleagueA) {colleagueB.receive(message);} else if (colleague == colleagueB) {colleagueA.receive(message);}}
}// 抽象同事类
abstract class Colleague {protected Mediator mediator;public Colleague(Mediator mediator) {this.mediator = mediator;}abstract void send(String message);abstract void receive(String message);
}// 具体同事类 A
class ColleagueA extends Colleague {public ColleagueA(Mediator mediator) {super(mediator);}@Overridevoid send(String message) {mediator.send(message, this);}@Overridevoid receive(String message) {System.out.println("同事A收到消息:" + message);}
}// 具体同事类 B
class ColleagueB extends Colleague {public ColleagueB(Mediator mediator) {super(mediator);}@Overridevoid send(String message) {mediator.send(message, this);}@Overridevoid receive(String message) {System.out.println("同事B收到消息:" + message);}
}// 客户端
class Client002 {public static void main(String[] args) {//todo Mediator 是中介者接口,定义了一个发送消息的方法 send,用于将消息发送给其他同事对象。//ConcreteMediator 是具体中介者类,它持有对各个同事对象的引用,并实现了中介者接口的方法,在收到某个同事对象的消息后,转发给其他同事对象。//Colleague 是抽象同事类,持有对中介者对象的引用,并定义了发送消息和接收消息的抽象方法。//ColleagueA 和 ColleagueB 是具体同事类,它们实现了抽象同事类中的方法,并在发送消息时调用中介者对象的方法进行消息的转发。//在客户端代码中,首先创建一个具体中介者对象,并创建两个具体同事对象,然后将它们注册到中介者对象中,最后通过其中一个同事对象发送消息,观察消息的传递过程。//中介者模式的核心思想是将对象之间的交互封装到中介者对象中,从而解耦了对象之间的直接交互关系,使得各个对象可以独立地改变自己的行为,而不会影响到其他对象。这种设计模式可以用于实现一些复杂的交互场景,例如聊天室、飞机调度系统等。ConcreteMediator mediator = new ConcreteMediator();ColleagueA colleagueA = new ColleagueA(mediator);ColleagueB colleagueB = new ColleagueB(mediator);mediator.setColleagueA(colleagueA);mediator.setColleagueB(colleagueB);colleagueA.send("Hello, colleague B!");colleagueB.send("Hi, colleague A!");}
}
八,迭代器模式
1.介绍
迭代器模式(Iterator Pattern)是一种行为型设计模式,它提供了一种访问聚合对象(如列表、集合)中元素的统一方式,而无需暴露该对象的内部表示。
// 迭代器接口
interface Iterator<T> {boolean hasNext();T next();
}// 具体迭代器实现类
class ConcreteIterator<T> implements Iterator<T> {private List<T> list;private int position;public ConcreteIterator(List<T> list) {this.list = list;this.position = 0;}@Overridepublic boolean hasNext() {return position < list.size();}@Overridepublic T next() {if (!hasNext()) {throw new IndexOutOfBoundsException("No more elements");}return list.get(position++);}
}// 聚合接口
interface Aggregate<T> {Iterator<T> createIterator();
}// 具体聚合实现类
class ConcreteAggregate<T> implements Aggregate<T> {private List<T> list;public ConcreteAggregate() {this.list = new ArrayList<>();}public void add(T element) {list.add(element);}@Overridepublic Iterator<T> createIterator() {return new ConcreteIterator<>(list);}
}// 客户端代码
class Client003 {public static void main(String[] args) {//todo Iterator 接口定义了迭代器的基本操作,包括判断是否还有下一个元素和获取下一个元素。//ConcreteIterator 是具体的迭代器实现类,它内部维护了一个列表以及当前迭代的位置,实现了迭代器接口的方法。//Aggregate 接口定义了聚合对象的基本操作,其中最重要的是创建迭代器的方法 createIterator()。//ConcreteAggregate 是具体的聚合实现类,它内部维护了一个列表,并实现了创建迭代器的方法,返回一个具体迭代器对象。//在客户端代码中,首先创建一个具体聚合对象 ConcreteAggregate,然后向其中添加元素。接着调用 createIterator() 方法获取迭代器对象,通过迭代器顺序访问聚合对象中的各个元素。//迭代器模式的核心思想是将对集合元素的访问和遍历操作封装到一个迭代器对象中,使得客户端代码不依赖于集合对象的具体实现方式,从而提高了代码的灵活性和可维护性。ConcreteAggregate<String> aggregate = new ConcreteAggregate<>();aggregate.add("Item 1");aggregate.add("Item 2");aggregate.add("Item 3");Iterator<String> iterator = aggregate.createIterator();while (iterator.hasNext()) {System.out.println(iterator.next());}}
}
九,解析器模式
1.介绍
解释器模式(Interpreter Pattern)是一种行为型设计模式,它用于解释和执行特定语言的语法或表达式。该模式通过定义一个语言文法,并使用解释器来解释该语言的表达式,从而进行相应的操作。
// 抽象表达式接口
interface Expression {boolean interpret(String context);
}// 终结符表达式类
class TerminalExpression implements Expression {private String data;public TerminalExpression(String data) {this.data = data;}@Overridepublic 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;}@Overridepublic boolean interpret(String context) {return expr1.interpret(context) || expr2.interpret(context);}
}// 非终结符表达式类
class AndExpression implements Expression {private Expression expr1;private Expression expr2;public AndExpression(Expression expr1, Expression expr2) {this.expr1 = expr1;this.expr2 = expr2;}@Overridepublic boolean interpret(String context) {return expr1.interpret(context) && expr2.interpret(context);}
}// 解释器客户端class Client004 {// 规则:John 和 Marry 是男性public static Expression getMaleExpression() {Expression john = new TerminalExpression("John");Expression marry = new TerminalExpression("Marry");return new OrExpression(john, marry);}// 规则:Julie 是女性public static Expression getFemaleExpression() {return new TerminalExpression("Julie");}public static void main(String[] args) {//todo Expression 是抽象表达式接口,定义了一个 interpret 方法,用于解释给定的上下文。//TerminalExpression 是终结符表达式类,表示语言中的最小单位,它实现了抽象表达式接口,并且用于解释基本的表达式。//OrExpression 和 AndExpression 是非终结符表达式类,表示复杂的语法规则,它们包含了多个终结符表达式,实现了抽象表达式接口,并且用于解释复杂的表达式。//在客户端代码中,通过组合各种表达式来构建语言的语法规则,然后通过解释器来解释给定的上下文,从而判断该上下文是否符合语法规则。//解析器模式适用于需要解释语言语法规则的场景,例如编译器、解释器等。通过构建解释器类的层次结构,可以灵活地表示复杂的语法规则,并且通过解释器来解释表达式,从而实现语言的解释和执行。Expression maleExpression = getMaleExpression();Expression femaleExpression = getFemaleExpression();System.out.println("John is male? " + maleExpression.interpret("John"));System.out.println("Julie is male? " + maleExpression.interpret("Julie"));System.out.println("Julie is female? " + femaleExpression.interpret("Julie"));}
}
十,命令模式
1.介绍
命令模式(Command Pattern)是一种行为型设计模式,它将请求封装成一个对象,使得可以用不同的请求对客户进行参数化,并且能够将请求排队或记录请求日志,以及支持可撤销的操作。
// 命令接口,声明执行命令的方法
interface Command {void execute();
}// 具体命令类,实现了命令接口,包含了一个接收者对象,在接收者对象上调用命令
class ConcreteCommand implements Command {private Receiver receiver;public ConcreteCommand(Receiver receiver) {this.receiver = receiver;}@Overridepublic void execute() {receiver.action();}
}// 接收者类,知道如何实施与执行一个请求相关的操作
class Receiver {public void action() {System.out.println("Receiver: Executing action");}
}// 调用者类,要求命令执行请求
class Invoker {private Command command;public void setCommand(Command command) {this.command = command;}public void executeCommand() {command.execute();}
}// 客户端代码
class Client005 {public static void main(String[] args) {//todo Command: 命令接口,声明了执行命令的方法 execute()。//ConcreteCommand: 具体命令类,实现了命令接口,持有一个接收者对象,在调用 execute() 方法时会调用接收者对象的方法来执行具体操作。//Receiver: 接收者类,知道如何实施与执行一个请求相关的操作,即具体的操作方法 action()。//Invoker: 调用者类,持有一个命令对象,通过 setCommand() 方法设置具体的命令对象,并通过 executeCommand() 方法执行命令。//客户端代码:创建接收者对象、具体命令对象和调用者对象,并设置具体命令对象,最后执行命令。//在示例中,我们通过命令模式将请求封装成了具体的命令对象 ConcreteCommand,并将接收者对象传递给具体的命令对象。通过调用者对象 Invoker,我们可以在运行时决定执行哪个具体的命令,并执行该命令。这样做的好处是可以实现请求的发送者和接收者之间的解耦。// 创建接收者对象Receiver receiver = new Receiver();// 创建具体命令对象,将接收者对象传递给它Command command = new ConcreteCommand(receiver);// 创建调用者对象,并设置具体命令对象Invoker invoker = new Invoker();invoker.setCommand(command);// 执行命令invoker.executeCommand();}
}
十一,责任链模式
1.介绍
责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它通过将请求发送者和接收者解耦,从而使得多个对象都有机会处理这个请求。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。
在责任链模式中,通常将每个处理者看作一个链表中的节点,每个节点都包含了处理请求的方法以及后继节点的引用。当请求来临时,它会首先被送到链表的第一个节点进行处理;如果这个节点不能处理它,那么该请求就会被转发给链表中的下一个节点,直到有一个节点能够处理它为止。在实际应用中,可以根据需要动态地增加或删除节点,从而灵活地定制处理链。
// 抽象处理器类
abstract class Handler {protected Handler successor;public void setSuccessor(Handler successor) {this.successor = successor;}public abstract void handleRequest(int request);
}// 具体处理器类A
class ConcreteHandlerA extends Handler {@Overridepublic void handleRequest(int request) {if (request < 10) {System.out.println("ConcreteHandlerA handles the request: " + request);} else if (successor != null) {successor.handleRequest(request);}}
}// 具体处理器类B
class ConcreteHandlerB extends Handler {@Overridepublic void handleRequest(int request) {if (request >= 10 && request < 20) {System.out.println("ConcreteHandlerB handles the request: " + request);} else if (successor != null) {successor.handleRequest(request);}}
}// 具体处理器类C
class ConcreteHandlerC extends Handler {@Overridepublic void handleRequest(int request) {if (request >= 20) {System.out.println("ConcreteHandlerC handles the request: " + request);} else if (successor != null) {successor.handleRequest(request);}}
}// 客户端类class Client006 {public static void main(String[] args) {//todo Handler 是抽象处理器类,定义了一个处理请求的方法 handleRequest 和一个设置下一个处理器的方法 setSuccessor。//ConcreteHandlerA、ConcreteHandlerB、ConcreteHandlerC 是具体处理器类,实现了抽象处理器类中的处理请求方法。每个具体处理器类负责处理特定范围的请求,如果自己无法处理,则将请求传递给下一个处理器。//在客户端类中,构建了一个责任链,并设置了处理器之间的关系。然后发送多个请求,每个请求都由责任链中的第一个处理器开始处理,如果某个处理器能够处理该请求,则结束处理,否则将请求传递给下一个处理器。//责任链模式的优点是将请求的发送者和接收者解耦,使得多个对象都有机会处理请求,增强了系统的灵活性。同时,责任链模式也有缺点,如果责任链过长或者处理器之间的关系不清晰,可能会导致请求处理不当或性能下降。////在实际应用中,责任链模式常用于请求的过滤、日志记录、权限验证等场景。// 构建责任链Handler handlerA = new ConcreteHandlerA();Handler handlerB = new ConcreteHandlerB();Handler handlerC = new ConcreteHandlerC();handlerA.setSuccessor(handlerB);handlerB.setSuccessor(handlerC);// 发送请求int[] requests = {5, 12, 25};for (int request : requests) {handlerA.handleRequest(request);}}
}