24种设计模式

一、创建型模式 1 单例模式(Singleton pattern) 确保一个类只有一个实例,并提供该实例的全局访问点 1)饿汉模式 这种方式比较常用,但容易

一、创建型模式

1. 单例模式(Singleton pattern)

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

1)饿汉模式

这种方式比较常用,但容易产生垃圾对象

优点:没有加锁,执行效率会提高。

缺点:类加载时就初始化,浪费内存。

public class Singleton {
    private static Singleton instance = new Singleton();
    private Singleton() {}
    public static Singleton getInstance() {
        return instance;
    }
}

2)懒汉模式,双检锁

在懒汉式基础上加入双重检验锁,保证线程安全和性能

public class Singleton {
    private volatile static Singleton instance = null;
    private Singleton() {}
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

3)静态内部类

使用静态内部类来实现懒汉式单例模式,静态内部类的加载是在程序中调用静态内部类的时候加载的,保证线程安全和性能

public class Singleton {
    private Singleton() {}
    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }
    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

4)枚举

使用枚举来实现单例模式,保证线程安全和防止反射攻击。

1)将已经有的class转换成枚举单例

@Data
public class Person {
    private String name;
    private int age;
}

public enum PersonEnum {
    INSTANCE;
    private Person instance;
    private PersonEnum(){
        instance = new Person();
    }
    public Person getInstance() {
        return instance;
    }
}

Person person = PersonEnum.INSTANCE.getInstance()

2)直接新建枚举类

public enum PersonSingleton {
    INSTANCE;
    private String name;
    public String getName() {
        return name;
    }
}

Person person = PersonSingleton.INSTANCE

2. 原型模式(Prototype)

允许通过复制现有对象来创建新对象,而不是通过实例化类来创建新对象。常用在需要创建大量相似对象时使用,通常涉及到实现浅拷贝和深拷贝。

@Data
abstract class Shape implements Cloneable {
    private String id;
    protected String type;

    public abstract void draw();

    @Override
    public Object clone() {
        Object clone = null;
        try {
            clone = super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return clone;
    }
}

class Circle extends Shape {
    public Circle() {
        type = "Circle";
    }

    @Override
    public void draw() {
        System.out.println("Inside Circle::draw() method.");
    }
}

class Square extends Shape {
    public Square() {
        type = "Square";
    }

    @Override
    public void draw() {
        System.out.println("Inside Square::draw() method.");
    }
}

class ShapeCache {
    private static Map<String, Shape> shapeMap = new HashMap<>();

    public static Shape getShape(String shapeId) {
        Shape cachedShape = shapeMap.get(shapeId);
        return (Shape) cachedShape.clone();
    }
    
    public static void loadCache() {
        Circle circle = new Circle();
        circle.setId("1");
        shapeMap.put(circle.getId(), circle);
        Square square = new Square();
        square.setId("2");
        shapeMap.put(square.getId(), square);
    }
}

class PrototypePatternDemo {
    public static void main(String[] args) {
        ShapeCache.loadCache();
        Shape clonedShape = ShapeCache.getShape("1");
        System.out.println("Shape : " + clonedShape.getType());
        Shape clonedShape2 = ShapeCache.getShape("2");
        System.out.println("Shape : " + clonedShape2.getType());
    }
}

3. 工厂模式(Factory Method)

定义创建对象的接口,由子类实现不同效果。通常用于创建单个对象。

abstract class Animal {
    public abstract void sound();
}

class Cat extends Animal {
    @Override
    public void sound() {
        System.out.println("喵喵喵");
    }
}

class Dog extends Animal {
    @Override
    public void sound() {
        System.out.println("汪汪汪");
    }
}

// 创建一个工厂类
class AnimalFactory {
    // 定义一个静态方法,根据传入的参数创建具体的产品类对象
    public static Animal createAnimal(String type) {
        if (type.equalsIgnoreCase("dog")) {
            return new Dog();
        } else if (type.equalsIgnoreCase("cat")) {
            return new Cat();
        } else {
            throw new IllegalArgumentException("Invalid animal type: " + type);
        }
    }
}

// 客户端代码
class Main {
    public static void main(String[] args) {
        // 使用工厂类创建不同的 Animal 对象
        Animal dog = AnimalFactory.createAnimal("dog");
        dog.sound();
        Animal cat = AnimalFactory.createAnimal("cat");
        cat.sound();
    }
}

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

比工厂模式更复杂,创建的是很多对象而不是一个对象,并且这些对象是相关的。

// 创建一个抽象产品类
abstract class Animal {
    public abstract void sound();
}

class Cat extends Animal {
    @Override
    public void sound() {
        System.out.println("喵喵喵");
    }
}

// 创建具体产品类,继承自 Animal 类
class Dog extends Animal {
    @Override
    public void sound() {
        System.out.println("汪汪汪");
    }
}

abstract class AnimalFactory {
    // 定义一个抽象方法,用于创建 Animal 对象
    public abstract Animal createAnimal();
}

class CatFactory extends AnimalFactory {
    @Override
    public Animal createAnimal() {
        return new Cat();
    }
}

// 创建具体工厂类,实现创建 Animal 对象的接口
class DogFactory extends AnimalFactory {
    @Override
    public Animal createAnimal() {
        return new Dog();
    }
}

// 客户端代码
class Main {
    public static void main(String[] args) {
        // 创建一个 Dog 对象
        AnimalFactory dogFactory = new DogFactory();
        Animal dog = dogFactory.createAnimal();
        dog.sound();

        // 创建一个 Cat 对象
        AnimalFactory catFactory = new CatFactory();
        Animal cat = catFactory.createAnimal();
        cat.sound();
    }
}

5. 建造者模式(Builder)

封装一个对象的构造过程,并允许按步骤构造。

@Data
class Car {
    private String make;
    private String model;
    private int year;
    private String engine;
    private int seats;

    public Car(String make, String model, int year, String engine, int seats) {
        this.make = make;
        this.model = model;
        this.year = year;
        this.engine = engine;
        this.seats = seats;
    }
}

@Data
class CarBuilder {
    private String make;
    private String model;
    private int year;
    private String engine;
    private int seats;

    public Car build() {
        return new Car(make, model, year, engine, seats);
    }
}

二、结构型

6、适配器模式(Adapter pattern)

将一个接口转换成另一个接口。

// 源接口
class Adaptee {
    public void specificRequest() {
        System.out.println("Adaptee's specific request");
    }
}

interface Target {
    public void request();
}

// 适配器类
class Adapter implements Target {
    private Adaptee adaptee;

    public Adapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }

    public void request() {
        adaptee.specificRequest();
    }
}

// 客户端代码
class Client {
    public static void main(String[] args) {
        Adaptee adaptee = new Adaptee();
        Target target = new Adapter(adaptee);
        target.request();
    }
}

7、组合模式(composite pattern)

允许你将对象组合成树形结构来表现"整体/部分"层次结构。组合能让客户以一致的方式处理个别对象以及对象组合。可以实现树形结构遍历效果。

interface IComponent {
    void display();
}

// Component.java
abstract class Component implements IComponent {
    protected String name;

    public Component(String name) {
        this.name = name;
    }

    public abstract void add(IComponent component);

    public abstract void remove(IComponent component);

}

// Composite.java
class Composite extends Component {
    private List<IComponent> children = new ArrayList<>();

    public Composite(String name) {
        super(name);
    }

    @Override
    public void add(IComponent component) {
        children.add(component);
    }

    @Override
    public void remove(IComponent component) {
        children.remove(component);
    }

    @Override
    public void display() {
        System.out.println("Composite: " + name);
        for (IComponent component : children) {
            component.display();
        }
    }
}

// Leaf.java
class Leaf implements IComponent {
    private String name;

    public Leaf(String name) {
        this.name = name;
    }

    @Override
    public void display() {
        System.out.println("Leaf: " + name);
    }
}

// Client.java
class Client {
    public static void main(String[] args) {
        Component root = new Composite("root");
        Component branch1 = new Composite("branch1");
        Component branch2 = new Composite("branch2");
        IComponent leaf1 = new Leaf("leaf1");
        IComponent leaf2 = new Leaf("leaf2");
        IComponent leaf3 = new Leaf("leaf3");
        root.add(branch1);
        root.add(branch2);
        branch1.add(leaf1);
        branch2.add(leaf2);
        branch2.add(leaf3);
        root.display();
    }
}

8、装饰者模式(decorator pattern)

允许您在不影响同一类的其他对象的行为的情况下,静态或动态地向单个对象添加行为

interface Pizza {
    public String getDescription();

    public double getCost();
}

// 具体组件
class PlainPizza implements Pizza {
    public String getDescription() {
        return "薄饼";
    }

    public double getCost() {
        return 4.00;
    }
}

// 装饰器
abstract class ToppingDecorator implements Pizza {
    protected Pizza pizza;

    public ToppingDecorator(Pizza pizza) {
        this.pizza = pizza;
    }

    public String getDescription() {
        return pizza.getDescription();
    }

    public double getCost() {
        return pizza.getCost();
    }
}

// 具体装饰器
class Cheese extends ToppingDecorator {
    public Cheese(Pizza pizza) {
        super(pizza);
    }

    public String getDescription() {
        return pizza.getDescription() + ",马苏里拉奶酪";
    }

    public double getCost() {
        return pizza.getCost() + 0.50;
    }
}

// 具体装饰器
class Pepperoni extends ToppingDecorator {
    public Pepperoni(Pizza pizza) {
        super(pizza);
    }

    public String getDescription() {
        return pizza.getDescription() + ",意大利辣香肠";
    }

    public double getCost() {
        return pizza.getCost() + 1.00;
    }
}

// 客户端代码
class PizzaShop {
    public static void main(String[] args) {
        Pizza pizza = new PlainPizza();
        pizza = new Cheese(pizza);
        pizza = new Pepperoni(pizza);
        System.out.println(pizza.getDescription());
        System.out.println("成本:$" + pizza.getCost());
    }
}

9、外观模式(Facade pattern)

它提供了一个统一的接口,用来访问子系统中的一群接口,从而让子系统更容易使用。

class CPU {
    public void processData() {
        System.out.println("正在处理数据...");
    }
}

class Memory {
    public void load() {
        System.out.println("正在加载内存...");
    }
}

class HardDrive {
    public void readData() {
        System.out.println("正在读取硬盘数据...");
    }
}

// 外观类
class ComputerFacade {
    private CPU cpu;
    private Memory memory;
    private HardDrive hardDrive;

    public ComputerFacade() {
        cpu = new CPU();
        memory = new Memory();
        hardDrive = new HardDrive();
    }

    public void start() {
        System.out.println("启动计算机...");
        cpu.processData();
        memory.load();
        hardDrive.readData();
        System.out.println("计算机启动完毕!");
    }
}

// 客户端代码
class FacadePatternDemo {
    public static void main(String[] args) {
        ComputerFacade computer = new ComputerFacade();
        computer.start();
    }
}

10、享元模式(Flyweight Pattern)

通过创建一个享元工厂来管理共享对象,并在需要时返回已经存在的对象,从而减少对象的创建和销毁次数

interface Shape {
    void draw();
}

// 具体享元类
@Data
class Circle implements Shape {
    private String color;
    private int x;
    private int y;
    private int radius;

    public Circle(String color) {
        this.color = color;
    }

    @Override
    public void draw() {
        System.out.println("画了一个" + color + "的圆,半径为" + radius + ",位置为(" + x + "," + y + ")");
    }
}

// 享元工厂类
class ShapeFactory {
    private static final Map<String, Shape> circleMap = new HashMap<>();

    public static Shape getCircle(String color) {
        Circle circle = (Circle) circleMap.get(color);
        if (circle == null) {
            circle = new Circle(color);
            circleMap.put(color, circle);
            System.out.println("创建了一个" + color + "的圆");
        }
        return circle;
    }
}

// 客户端代码
class FlyweightPatternDemo {
    private static final String[] colors = {"红色", "绿色", "蓝色", "黄色", "黑色"};

    public static void main(String[] args) {
        for (int i = 0; i < 20; i++) {
            Circle circle = (Circle) ShapeFactory.getCircle(getRandomColor());
            circle.setX(getRandomX());
            circle.setY(getRandomY());
            circle.setRadius(100);
            circle.draw();
        }
    }

    private static String getRandomColor() {
        return colors[(int) (Math.random() * colors.length)];
    }

    private static int getRandomX() {
        return (int) (Math.random() * 100);
    }

    private static int getRandomY() {
        return (int) (Math.random() * 100);
    }
}

11、代理模式(Proxy pattern)

提供了间接访问目标对象的一种方式;即通过代理对象访问目标对象。可以在不改变原有目标对象的基础上,对目标对象增加额外的扩展功能。

1)静态代理

被代理对象与代理对象需要实现相同的接口或者是继承相同父类,因此要定义一个接口或抽象类。

//代理接口
interface IHello {
    String hi(String key);
}

//代理接口实现类
class HelloImpl implements IHello {
    @Override
    public String hi(String key) {
        String str = "hello:" + key;
        System.out.println("HelloImpl! " + str);
        return str;
    }
}

//静态代理类
class HelloStaticProxy implements IHello {
    private IHello hello;

    public HelloStaticProxy(IHello hello) {
        this.hello = hello;
    }

    @Override
    public String hi(String key) {
        System.out.println(">>> static proxy start");
        String result = hello.hi(key);
        System.out.println(">>> static proxy end");
        return result;
    }
}

class DemoTest {
    public static void main(String[] args) {
        IHello helloProxy = new HelloStaticProxy(new HelloImpl());
        helloProxy.hi("world");
    }
}

2)jdk动态代理

jdk动态代理是基于接口的一种代理方式,目标对象一定要实现接口。原理是,利用反射机制,动态生成匿名类继承Proxy类并且实现了要代理的接口,由于java不支持多继承,所以JDK动态代理不能代理类

//代理接口
interface IHello {
    String hi(String key);
}

//代理接口实现类
class HelloImpl implements IHello {
    @Override
    public String hi(String key) {
        String str = "hello:" + key;
        System.out.println("HelloImpl! " + str);
        return str;
    }
}

//jdk动态代理类
class JdkProxy implements InvocationHandler {
    private Object target;

    public JdkProxy(Object target) {
        this.target = target;
    }

    //获取被代理接口实例对象
    public <T> T getProxy() {
        return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println(">>> JdkProxy start");
        Object result = method.invoke(target, args);
        System.out.println(">>> JdkProxy end");
        return result;
    }
}

class Demo2Test {
    public static void main(String[] args) {
        JdkProxy proxy = new JdkProxy(new HelloImpl());
        IHello helloProxy = proxy.getProxy();
        helloProxy.hi(" jdk proxy !");
    }
}

3)cglib动态代理

目标对象可以不用实现接口,不能针对final类进行代理。原理是,动态生成class继承目标对象。使用cglib必须引入对应的jar包

//目标类
class HelloImpl {
    public String hi(String key) {
        String str = "hello:" + key;
        System.out.println("HelloImpl! " + str);
        return str;
    }
}

//cglib代理类
class CglibProxy implements InvocationHandler {
    private Object target;

    public CglibProxy(Object target) {
        this.target = target;
    }

    //获取被代理接口实例对象
    public <T> T getProxy() {
        //1创建增强器对象
        Enhancer e = new Enhancer();
        //2设置增强器的类加载器
        e.setClassLoader(target.getClass().getClassLoader());
        //3设置代理对象父类类型
        e.setSuperclass(target.getClass());
        //4设置回调函数
        e.setCallback(this);
        //5创建代理对象
        return (T) e.create();
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println(">>> cglib start");
        Object obj = method.invoke(target, args);
        System.out.println(">>> cglib end");
        return obj;
    }
}

class Demo3Test {
    public static void main(String[] args) {
        HelloImpl hello = new HelloImpl();
        CglibProxy cglibProxy = new CglibProxy(hello);
        HelloImpl proxy = cglibProxy.getProxy();
        proxy.hi(" cglib ");
    }
}

12、桥接模式(Bridge pattern)

使用桥接模式通过将实现和抽象放在两个不同的类层次中而使它们可以独立改变。

// 首先,我们定义一个 Color 接口,它表示颜色:
interface Color {
    void applyColor();
}

// 然后,我们定义一个 Shape 抽象类,它包含了一个 Color 对象:
abstract class Shape {
    protected Color color;

    public Shape(Color color) {
        this.color = color;
    }

    public abstract void applyColor();
}

// 接下来,我们定义两个实现了 Color 接口的具体类:
class Red implements Color {
    @Override
    public void applyColor() {
        System.out.println("Applying red color");
    }
}

class Blue implements Color {
    @Override
    public void applyColor() {
        System.out.println("Applying blue color");
    }
}

// 最后,我们定义两个实现了 Shape 抽象类的具体类:
class Circle extends Shape {
    public Circle(Color color) {
        super(color);
    }

    @Override
    public void applyColor() {
        System.out.print("Circle applying color: ");
        color.applyColor();
    }
}

class Square extends Shape {
    public Square(Color color) {
        super(color);
    }

    @Override
    public void applyColor() {
        System.out.print("Square applying color: ");
        color.applyColor();
    }
}

// 现在,我们可以使用这些类来创建出对应的对象并调用它们的方法:
class Test {
    public static void main(String[] args) {
        Shape square = new Square(new Red());
        Shape circle = new Circle(new Blue());
        square.applyColor();
        circle.applyColor();
    }
}
三、行为型

13、责任链模式(Chain of responsibility pattern)

它允许将请求沿着处理链进行传递,直到有一个处理程序处理它为止

interface Handler {
    Handler setNextHandler(Handler nextHandler);

    void handleRequest(Request request);
}

// 创建抽象处理器类
abstract class AbstractHandler implements Handler {
    private Handler nextHandler;

    public Handler setNextHandler(Handler nextHandler) {
        this.nextHandler = nextHandler;
        return this.nextHandler;
    }

    public Handler getNextHandler() {
        return nextHandler;
    }
}

// 创建具体的处理器类
class ConcreteHandler1 extends AbstractHandler {
    public void handleRequest(Request request) {
        if (request.getType().equals("Type1")) {
            System.out.println("ConcreteHandler1 handles request " + request);
        } else {
            getNextHandler().handleRequest(request);
        }
    }
}

class ConcreteHandler2 extends AbstractHandler {
    public void handleRequest(Request request) {
        if (request.getType().equals("Type2")) {
            System.out.println("ConcreteHandler2 handles request " + request);
        } else {
            getNextHandler().handleRequest(request);
        }
    }
}

class ConcreteHandler3 extends AbstractHandler {
    public void handleRequest(Request request) {
        if (request.getType().equals("Type3")) {
            System.out.println("ConcreteHandler3 handles request " + request);
        } else {
            getNextHandler().handleRequest(request);
        }
    }
}

// 创建请求类
class Request {
    private String type;

    public Request(String type) {
        this.type = type;
    }

    public String getType() {
        return type;
    }

    public String toString() {
        return "Request [type=" + type + "]";
    }
}

// 客户端代码
class Client {
    public static void main(String[] args) {
        Handler handler1 = new ConcreteHandler1();
        Handler handler2 = new ConcreteHandler2();
        Handler handler3 = new ConcreteHandler3();
        handler1.setNextHandler(handler2)
                .setNextHandler(handler3);
        handler1.handleRequest(new Request("Type1"));
        handler1.handleRequest(new Request("Type2"));
        handler1.handleRequest(new Request("Type3"));
    }
}

14、命令模式(Command pattern)

它允许将请求封装为一个对象,从而使不同的请求可以使用不同的参数进行参数化,队列或日志请求,以及支持可撤销的操作。在Java中,命令模式的实现通常涉及一个命令接口和一个或多个具体命令类,这些类实现了命令接口,并在其execute()方法中定义了实际的命令逻辑。此外,命令模式还可能涉及一个调用者类,该类将一个或多个命令对象与接收者对象关联起来,并在需要时调用它们的execute()方法

interface Command {
    void execute(String[] args);
}

// 定义具体命令
class CreateFileCommand implements Command {
    public void execute(String[] args) {
        // 根据给定的名称和内容创建文件的代码
        System.out.println("创建文件 : " + String.join(", ", args));
    }
}

class DeleteFileCommand implements Command {
    public void execute(String[] args) {
        // 根据给定的名称删除文件的代码
        System.out.println("删除文件 : " + String.join(",", args));
    }
}

// 定义命令执行者
class CommandExecutor {
    private Map<String, Command> commands = new HashMap<>();

    public CommandExecutor() {
        // 将具体命令与命令名称关联起来
        commands.put("create", new CreateFileCommand());
        commands.put("delete", new DeleteFileCommand());
    }

    public void executeCommand(String commandName, String[] args) {
        // 查找对应的命令并执行
        Command command = commands.get(commandName);
        if (command != null) {
            command.execute(args);
        } else {
            System.out.println("Unknown command: " + commandName);
        }
    }
}

// 使用命令执行者执行命令
class Main {
    public static void main(String[] args) {
        CommandExecutor executor = new CommandExecutor();
        executor.executeCommand("create", new String[]{"file.txt", "Hello World!"});
        executor.executeCommand("delete", new String[]{"file.txt"});
        executor.executeCommand("unknown", new String[]{});
    }
}

15、解释器模式(Interpreter pattern)

使用解释器模式为语言创建解释器,通常由语言的语法和语法分析来定义。

interface Expression {
    int interpret(Context context);
}

// 终结符表达式
class NumberExpression implements Expression {
    private int value;

    public NumberExpression(int value) {
        this.value = value;
    }

    public int interpret(Context context) {
        return value;
    }
}

// 非终结符表达式
class AddExpression implements Expression {
    private Expression left;
    private Expression right;

    public AddExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    public int interpret(Context context) {
        return left.interpret(context) + right.interpret(context);
    }
}

// 上下文
class Context {
    private Map<String, Integer> variables = new HashMap<>();

    public void setVariable(String name, int value) {
        variables.put(name, value);
    }

    public int getVariable(String name) {
        return variables.get(name);
    }
}

// 解释器
class Interpreter {
    private Expression expression;

    public Interpreter(Expression expression) {
        this.expression = expression;
    }

    public int interpret(Context context) {
        return expression.interpret(context);
    }
}

// 使用解释器执行表达式
class Main {
    public static void main(String[] args) {
        // 创建上下文
        Context context = new Context();
        context.setVariable("a", 10);
        context.setVariable("b", 20);
        // 创建表达式
        Expression expression = new AddExpression(
                new NumberExpression(context.getVariable("a")),
                new NumberExpression(context.getVariable("b"))
        );
        // 创建解释器并执行表达式
        Interpreter interpreter = new Interpreter(expression);
        int result = interpreter.interpret(context);
        System.out.println("Result: " + result);
    }
}

16、迭代器模式(iterator pattern)

提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。适用于需要遍历集合对象的场景,例如数组、列表、树等

interface Iterator<T> {
    boolean hasNext();

    T next();
}

// 具体迭代器实现类
class ArrayIterator<T> implements Iterator<T> {
    private T[] array;
    private int currentIndex;

    public ArrayIterator(T[] array) {
        this.array = array;
        this.currentIndex = 0;
    }

    public boolean hasNext() {
        return currentIndex < array.length;
    }

    public T next() {
        if (!hasNext()) {
            throw new NoSuchElementException();
        }
        T element = array[currentIndex];
        currentIndex++;
        return element;
    }
}

// 使用迭代器遍历数组
class Main {
    public static void main(String[] args) {
        Integer[] array = {1, 2, 3, 4, 5};
        Iterator<Integer> iterator = new ArrayIterator<>(array);
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}

17、观察者模式(observer pattern)

与之类似的就是发布-订阅模式。在对象之间定义一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象都会收到通知,并自动更新。

// 抽象主题接口
interface Subject {
    void registerObserver(Observer observer);

    void removeObserver(Observer observer);

    void notifyObservers();
}

// 具体主题实现类
class WeatherStation implements Subject {
    private List<Observer> observers;
    private float temperature;
    private float humidity;
    private float pressure;

    public WeatherStation() {
        this.observers = new ArrayList<>();
    }

    public void registerObserver(Observer observer) {
        observers.add(observer);
    }

    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    public void notifyObservers() {
        System.out.println(">> 通知所有观察者 <<");
        for (Observer observer : observers) {
            System.out.println("------观察者:" + observer.name() + "-----------");
            observer.update(temperature, humidity, pressure);
        }
    }

    public void setMeasurements(float temperature, float humidity, float pressure) {
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        notifyObservers();
    }
}

// 抽象观察者接口
interface Observer {
    void update(float temperature, float humidity, float pressure);

    String name();
}

// 具体观察者实现类
class Display implements Observer {
    private float temperature;
    private float humidity;
    private float pressure;
    private String name;

    @Override
    public String name() {
        return this.name;
    }

    public Display(String name) {
        this.name = name;
    }

    public void update(float temperature, float humidity, float pressure) {
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        display();
    }

    public void display() {
        System.out.println("Temperature: " + temperature);
        System.out.println("Humidity: " + humidity);
        System.out.println("Pressure: " + pressure);
    }
}

// 使用观察者模式实现气象站
class Main {
    public static void main(String[] args) {
        WeatherStation weatherStation = new WeatherStation();
        Display display1 = new Display("01");
        Display display2 = new Display("02");
        weatherStation.registerObserver(display1);
        weatherStation.registerObserver(display2);
        weatherStation.setMeasurements(25.0f, 60.0f, 1013.0f);
        weatherStation.removeObserver(display2);
        weatherStation.setMeasurements(26.0f, 65.0f, 1012.0f);
    }
}

18、状态模式(State pattern)

允许对象在内部状态改变时改变它的行为。状态模式将状态封装成独立的类,并将请求委托给当前状态对象,从而实现状态的切换和状态行为的变化

interface State {
    void handle();
}

// 具体状态类1
class ConcreteState1 implements State {
    public void handle() {
        System.out.println("ConcreteState1 is handling.");
    }
}

// 具体状态类2
class ConcreteState2 implements State {
    public void handle() {
        System.out.println("ConcreteState2 is handling.");
    }
}

// 环境类
class Context {
    private State state;

    public void setState(State state) {
        this.state = state;
    }

    public void request() {
        state.handle();
    }
}

// 使用状态模式实现的客户端代码
class Main {
    public static void main(String[] args) {
        Context context = new Context();
        State state1 = new ConcreteState1();
        State state2 = new ConcreteState2();
        context.setState(state1);
        context.request();
        context.setState(state2);
        context.request();
    }
}

19、模板方法模式(Template pattern)

在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下, 重新定义算法中的某些步骤。

abstract class Game {
    abstract void initialize();

    abstract void startPlay();

    abstract void endPlay();

    // 模板方法
    public final void play() {
        // 初始化游戏
        initialize();
        // 开始游戏
        startPlay();
        // 结束游戏
        endPlay();
    }
}

class Cricket extends Game {
    @Override
    void endPlay() {
        System.out.println("Cricket Game Finished!");
    }

    @Override
    void initialize() {
        System.out.println("Cricket Game Initialized! Start playing.");
    }

    @Override
    void startPlay() {
        System.out.println("Cricket Game Started. Enjoy the game!");
    }
}

class Football extends Game {
    @Override
    void endPlay() {
        System.out.println("Football Game Finished!");
    }

    @Override
    void initialize() {
        System.out.println("Football Game Initialized! Start playing.");
    }

    @Override
    void startPlay() {
        System.out.println("Football Game Started. Enjoy the game!");
    }
}

class TemplatePatternDemo {
    public static void main(String[] args) {
        Game game = new Cricket();
        game.play();
        System.out.println();
        game = new Football();
        game.play();
    }
}

20、中介者模式(Mediator pattern)

允许对象之间通过中介者对象进行通信,从而避免对象之间的直接耦合。中介者模式将对象之间的复杂关系转化为中介者和对象之间的简单关系,从而提高了系统的灵活性和可维护性。

// Mediator接口定义了send()方法,用于处理对象之间的交互。
interface Mediator {
    void send(String message, Colleague colleague);
}

// Colleague抽象类表示对象,它包含一个Mediator对象,用于处理对象之间的通信。
abstract class Colleague {
    protected Mediator mediator;

    public Colleague(Mediator mediator) {
        this.mediator = mediator;
    }

    public abstract void receive(String message);

    public abstract void send(String message);
}

// ConcreteColleague1和ConcreteColleague2是具体的对象实现类,它们实现了Colleague抽象类中的方法。
class ConcreteColleague1 extends Colleague {
    public ConcreteColleague1(Mediator mediator) {
        super(mediator);
    }

    @Override
    public void receive(String message) {
        System.out.println("Colleague1 received message: " + message);
    }

    @Override
    public void send(String message) {
        System.out.println("Colleague1 sends message: " + message);
        mediator.send(message, this);
    }
}

class ConcreteColleague2 extends Colleague {
    public ConcreteColleague2(Mediator mediator) {
        super(mediator);
    }

    @Override
    public void receive(String message) {
        System.out.println("Colleague2 received message: " + message);
    }

    @Override
    public void send(String message) {
        System.out.println("Colleague2 sends message: " + message);
        mediator.send(message, this);
    }
}

// ConcreteMediator是具体的中介者实现类,它负责协调对象之间的通信。
class ConcreteMediator implements Mediator {
    private ConcreteColleague1 colleague1;
    private ConcreteColleague2 colleague2;

    public void setColleague1(ConcreteColleague1 colleague1) {
        this.colleague1 = colleague1;
    }

    public void setColleague2(ConcreteColleague2 colleague2) {
        this.colleague2 = colleague2;
    }

    @Override
    public void send(String message, Colleague colleague) {
        if (colleague == colleague1) {
            colleague2.receive(message);
        } else {
            colleague1.receive(message);
        }
    }
}

class MediatorPatternDemo {
    public static void main(String[] args) {
        ConcreteMediator mediator = new ConcreteMediator();
        ConcreteColleague1 colleague1 = new ConcreteColleague1(mediator);
        ConcreteColleague2 colleague2 = new ConcreteColleague2(mediator);
        mediator.setColleague1(colleague1);
        mediator.setColleague2(colleague2);
        colleague1.send("Hello, Colleague2.");
        colleague2.send("Hello, Colleague1.");
    }
}

21、备忘录模式(Memento pattern)

允许在不破坏封装性的情况下捕获和恢复对象的内部状态。备忘录模式通常用于需要撤销操作或恢复先前状态的情况下。该模式包括三个主要组件:原始对象、备忘录对象和负责管理备忘录对象的对象。

// Originator类表示原始对象,它包含需要保存的状态。
@Data
class Originator {
    private String state;

    // createMemento()方法创建备忘录对象,并将当前状态保存到备忘录对象中。
    public Memento createMemento() {
        return new Memento(state);
    }

    // restore()方法用于从备忘录对象中恢复先前的状态。
    public void restore(Memento memento) {
        state = memento.getState();
    }
}

// Memento类表示备忘录对象,它包含需要保存的状态。
@Data
class Memento {
    private String state;

    public Memento(String state) {
        this.state = state;
    }
}

// Caretaker类负责管理备忘录对象,它包含一个Memento对象。
@Data
class Caretaker {
    private Memento memento;
}

class MementoPatternDemo {
    public static void main(String[] args) {
        Originator originator = new Originator();
        Caretaker caretaker = new Caretaker();
        // 保存原始对象的状态到备忘录对象中
        originator.setState("State 1");
        caretaker.setMemento(originator.createMemento());
        // 修改原始对象的状态
        originator.setState("State 2");
        // 从备忘录对象中恢复先前的状态
        originator.restore(caretaker.getMemento());
        System.out.println("Current state: " + originator.getState());
    }
}

22、访问者模式(visitor pattern)

允许你在不修改对象结构的前提下定义新的操作。访问者模式将对象结构和操作分离开来,使得操作可以独立地应用于对象结构中的元素。在访问者模式中,有两个主要角色:访问者和元素。访问者定义了对元素进行操作的方法,而元素则提供了接受访问者的方法。

interface Expression {
    void accept(Visitor visitor);
}

class NumberExpression implements Expression {
    private int value;

    public NumberExpression(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }

    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

// 定义具体的元素类:加法表达式
class AdditionExpression implements Expression {
    private Expression left;
    private Expression right;

    public AdditionExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    public Expression getLeft() {
        return left;
    }

    public Expression getRight() {
        return right;
    }

    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

interface Visitor {
    void visit(NumberExpression expression);

    void visit(AdditionExpression expression);
}

// 定义具体的访问者类:打印访问者
class PrinterVisitor implements Visitor {
    public void visit(NumberExpression expression) {
        System.out.print(expression.getValue());
    }

    public void visit(AdditionExpression expression) {
        System.out.print("(");
        expression.getLeft().accept(this);
        System.out.print("+");
        expression.getRight().accept(this);
        System.out.print(")");
    }
}

class CalculatorVisitor implements Visitor {
    private int result;

    public void visit(NumberExpression expression) {
        result = expression.getValue();
    }

    public void visit(AdditionExpression expression) {
        expression.getLeft().accept(this);
        int leftValue = result;
        expression.getRight().accept(this);
        int rightValue = result;
        result = leftValue + rightValue;
    }

    public int getResult() {
        return result;
    }
}

class Client {
    public static void main(String[] args) {
        // 构建表达式树:1 + (2 + 3)
        Expression expression = new AdditionExpression(
                new NumberExpression(1),
                new AdditionExpression(
                        new NumberExpression(2),
                        new NumberExpression(3)
                )
        );
        // 计算表达式的值
        CalculatorVisitor calculator = new CalculatorVisitor();
        expression.accept(calculator);
        System.out.println("Result: " + calculator.getResult());
        // 打印表达式的字符串表示
        PrinterVisitor printer = new PrinterVisitor();
        expression.accept(printer);
    }
}

23、策略模式(strategy pattern)

允许您定义一系列算法,将每个算法封装起来,并使它们可以互换使用。这种模式使得算法可以独立于使用它们的客户端而变化。

策略模式通常由一个接口和多个实现该接口的类组成。客户端将使用该接口来调用算法,而不是直接调用实现类。这样,客户端就可以在运行时选择不同的算法实现,而不需要修改代码。

PaymentStrategy 接口定义了一种支付方式,并包含一个 pay 方法,该方法接受一个金额参数。我们创建了三个实现该接口的类,分别代表信用卡支付、PayPal支付和现金支付。 PaymentProcessor 类接受一个 PaymentStrategy 实例作为参数,并使用它来执行支付操作。在 main 方法中,我们创建了一个 PaymentProcessor 实例,并使用不同的支付方式来进行支付。

interface PaymentStrategy {
    void pay(double amount);
}

class CreditCardPayment implements PaymentStrategy {
    private String cardNumber;
    private String cvv;
    private String expiryDate;

    public CreditCardPayment(String cardNumber, String cvv, String expiryDate) {
        this.cardNumber = cardNumber;
        this.cvv = cvv;
        this.expiryDate = expiryDate;
    }

    public void pay(double amount) {
        System.out.println("Paying " + amount + " using credit card.");
    }
}

class PayPalPayment implements PaymentStrategy {
    private String email;
    private String password;

    public PayPalPayment(String email, String password) {
        this.email = email;
        this.password = password;
    }

    public void pay(double amount) {
        System.out.println("Paying " + amount + " using PayPal.");
    }
}

class CashPayment implements PaymentStrategy {
    public void pay(double amount) {
        System.out.println("Paying " + amount + " using cash.");
    }
}

class PaymentProcessor {
    private PaymentStrategy strategy;

    public PaymentProcessor(PaymentStrategy strategy) {
        this.strategy = strategy;
    }

    public void setStrategy(PaymentStrategy strategy) {
        this.strategy = strategy;
    }

    public void processPayment(double amount) {
        strategy.pay(amount);
    }
}

class PaymentSystem {
    public static void main(String[] args) {
        PaymentProcessor processor = new PaymentProcessor(new CreditCardPayment("1234 5678 9012 3456", "123", "12/23"));
        processor.processPayment(100.0);
        processor.setStrategy(new PayPalPayment("example@example.com", "password"));
        processor.processPayment(50.0);
        processor.setStrategy(new CashPayment());
        processor.processPayment(25.0);
    }
}