Java 设计模式

设计模式介绍

  • 代表了代码的最佳实践,被有经验的开发人员所使用
  • 设计模式是很多被反复使用并知晓,主要是对代码和经验的总结
  • 使用设计模式是为了重用代码,让代码更容易被他人理解,保证代码的可靠性
  • 对接口编程而不是对实现编程
  • 优先使用对象组合而不是继承关系

设计模式的七大原则

开闭原则

  • 对扩展开放,对修改关闭
    • 编写软件,比如类、模块、方法
  • 使用抽象进行构建,使用实现扩展细节
  • 面向抽象编程
  • 提高软件系统的可复用性和可维护性

依赖倒转原则

  • 依赖倒转原则是开闭原则的基础,针对接口进行编程
  • 依赖抽象,而不是具体的实现
  • 可以减少类之间的耦合性,提高系统稳定性,提高代码可读性和可维护性
  • 降低修改程序所造成的风险

单一职责原则

  • 一个类/接口/方法,只负责一项职责
  • 降低程序的复杂度,提高程序可维护性,降低了变更所带来的风险

接口隔离原则

  • 使用多个接口,而不是使用单一的接口
  • 尽量细化接口,接口中的方法尽量少
  • 符合低耦合的设计思想,提高了可扩展性和可维护性

迪米特原则

  • 一个对象应该对其他对象保持最少的了解,又被称为最少知道原则
  • 降低类鱼类之间的耦合关系
  • 强调只和朋友(成员变量/方法中输入或输出的参数)交流,不和陌生人说话

里氏替换原则

  • 里氏替换原则是继承复用的基石,也是对开闭原则的补充
  • 子类可以扩展父类的功能,但是不能修改父类的原有功能
  • 子类可以实现父类的抽象方法,但是不能覆盖父类原有的方法
  • 子类中可以增加自己特有的方法
  • 对子类的继承关系进行约束,也是开闭原则的补充
  • 可以增加程序的健壮性

合成复用原则

  • 尽量使用组合/聚合的方式,而不是使用继承关系达到软件复用的目的
  • 可以使系统更加灵活,降低类与类之间耦合度,一个类的变化对其他类造成的影响相对较小

设计模式类型

  • 创建型模式
    • 隐藏了创建对象的过程,通过逻辑方法创建对象,而不是通过 new 关键字进行创建
      • 简单工厂方法模式
      • 抽象工厂模式
      • 单例模式
      • 建造者模式
      • 原型模式
  • 结构性模式
    • 主要关注类和对象的组合关系
    • 继承概念被用来组合接口和定义组合对象,获得新的功能方式
      • 适配器模式
      • 桥接模式
      • 组合模式
      • 装饰模式
      • 外观模式
      • 享元模式
      • 代理模式
  • 行为型模式
    • 主要关注对象之间的通信
      • 责任链模式
      • 命令模式
      • 解释器模式
      • 迭代器模式
      • 中介者模式
      • 备忘录模式
      • 观察者模式
      • 状态模式
      • 策略模式
      • 模板方法模式
      • 访问者模式

简单工厂方法模式

  • 由一个工厂决定创建哪一种类型的产品实例
package creational.simpleFactory;  
  
public abstract class Course {  
    public abstract void make();  
}
package creational.simpleFactory;  
  
public class JavaCourse extends Course{  
    @Override  
    public void make() {  
        System.out.println("制作Java课程");  
    }  
}
package creational.simpleFactory;  
  
public class PythonCourse extends Course{  
    @Override  
    public void make() {  
        System.out.println("制作Python课程");  
    }  
}
package creational.simpleFactory;  
  
public class CourseFactory {  
    public Course getCourse(String course) {  
        if ("java".equalsIgnoreCase(course)) {  
            // 创建Java课程对象,并返回  
            return new JavaCourse();  
        } else if ("python".equalsIgnoreCase(course)) {  
            // 创建python课程对象,并返回  
            return new PythonCourse();  
        }  
        return null;  
    }  
}
package creational.simpleFactory;  
  
public class Test {  
    public static void main(String[] args) {  
        CourseFactory factory = new CourseFactory();  
        Course javaCourse = factory.getCourse("java");  
        javaCourse.make();  
        Course pythonCourse = factory.getCourse("python");  
        pythonCourse.make();  
    }  
}

image.png

工厂方法模式

  • 定义一个接口或一个抽象的工厂,让它的实现类(工厂)来决定创建哪一个实例对象
  • 根据每个工厂不同的方法来产生不同的不同的所需要的对象
  • 工厂方法模式生产的都是相同系列的对象,比如 Java 课程、Python 课程
package creational.factoryMethod;  
  
public abstract class Course {  
    public abstract void make();  
}
package creational.factoryMethod;  
  
public class JavaCourse extends Course {  
    @Override  
    public void make() {  
        System.out.println("制作Java课程");  
    }  
}
package creational.factoryMethod;  
  
public class PythonCourse extends Course {  
    @Override  
    public void make() {  
        System.out.println("制作Python课程");  
    }  
}
package creational.factoryMethod;  
  
public abstract class CourseFactory {  
    public abstract Course getCourse();  
}
package creational.factoryMethod;  
  
public class JavaCourseFactory extends CourseFactory{  
    @Override  
    public Course getCourse() {  
        return new JavaCourse();  
    }  
}
package creational.factoryMethod;  
  
public class PythonCourseFactory extends CourseFactory{  
    @Override  
    public Course getCourse() {  
        return new PythonCourse();  
    }  
}
package creational.factoryMethod;  
  
public class Test {  
    public static void main(String[] args) {  
        JavaCourseFactory javaCourseFactory = new JavaCourseFactory();  
        Course javaCourse = javaCourseFactory.getCourse();  
        javaCourse.make();  
        PythonCourseFactory pythonCourseFactory = new PythonCourseFactory();  
        Course pythonCourse = pythonCourseFactory.getCourse();  
        pythonCourse.make();  
    }  
}

image.png

抽象工厂模式

  • 同一个产品下的不同模块,比如汽车,需要将汽车分为不同的零部件去进行生产
  • 抽象工厂模式提供了创建一系列相关或互相依赖的对象的接口
package creational.abstractFactory;  
  
public abstract class CarDoorFactory {  
    public abstract void make();  
}
package creational.abstractFactory;  
  
public abstract class BasePlateFactory {  
    public abstract void make();  
}
package creational.abstractFactory;  
  
public abstract class FrameFactory {  
    public abstract void make();  
}
package creational.abstractFactory;  
  
public class CarDoor extends CarDoorFactory {  
    @Override  
    public void make() {  
        System.out.println("制作车门");  
    }  
}
package creational.abstractFactory;  
  
public class CarFrame extends FrameFactory {  
    @Override  
    public void make() {  
        System.out.println("制作车架");  
    }  
}
package creational.abstractFactory;  
  
public class CarBasePlate extends BasePlateFactory {  
    @Override  
    public void make() {  
        System.out.println("制作底盘");  
    }  
}
package creational.abstractFactory;  
  
public interface CarFactory {  
    // 车门  
    public CarDoor getCarDoor();  
    // 车架  
    public CarFrame getCarFrame();  
    // 底盘  
    public CarBasePlate getCarBasePlate();  
    // 生产汽车  
    public void make();  
}
package creational.abstractFactory;  
  
public class Car implements CarFactory{  
    private CarDoor carDoor = null;  
    private CarFrame carFrame = null;  
    private CarBasePlate carBasePlate = null;  
  
    @Override  
    public CarDoor getCarDoor() {  
        this.carDoor = new CarDoor();  
        return this.carDoor;  
    }  
  
    @Override  
    public CarFrame getCarFrame() {  
        this.carFrame = new CarFrame();  
        return this.carFrame;  
    }  
  
    @Override  
    public CarBasePlate getCarBasePlate() {  
        this.carBasePlate = new CarBasePlate();  
        return this.carBasePlate;  
    }  
  
    @Override  
    public void make() {  
        carDoor.make();  
        carFrame.make();  
        carBasePlate.make();  
        System.out.println("汽车生产完成");  
    }  
}
package creational.abstractFactory;  
  
public class Test {  
    public static void main(String[] args) {  
        Car car = new Car();  
        car.getCarDoor();  
        car.getCarBasePlate();  
        car.getCarFrame();  
        car.make();  
    }  
}

image.png

建造者模式

  • 将复杂对象的创建和属性赋值进行分离
  • 建造的过程和细节不需要知道,只需要通过构建者去进行操作即可
package creational.builder;  
  
public class Car {  
    private String basePlate;  
    private String frame;  
    private String door;  
  
    public String getBasePlate() {  
        return basePlate;  
    }  
  
    public void setBasePlate(String basePlate) {  
        this.basePlate = basePlate;  
    }  
  
    public String getFrame() {  
        return frame;  
    }  
  
    public void setFrame(String frame) {  
        this.frame = frame;  
    }  
  
    public String getDoor() {  
        return door;  
    }  
  
    public void setDoor(String door) {  
        this.door = door;  
    }  
  
    @Override  
    public String toString() {  
        return "Car{" +  
                "basePlate='" + basePlate + '\'' +  
                ", frame='" + frame + '\'' +  
                ", door='" + door + '\'' +  
                '}';  
    }  
}
package creational.builder;  
  
public abstract class Builder {  
    public abstract void buildBasePlate(String basePlate);  
    public abstract void buildFrame(String frame);  
    public abstract void buildDoor(String door);  
    public abstract Car makeCar();  
}
package creational.builder;  
  
public class CarBuilder extends Builder{  
    private Car car = new Car();  
  
    @Override  
    public void buildBasePlate(String basePlate) {  
        this.car.setBasePlate(basePlate);  
    }  
  
    @Override  
    public void buildFrame(String frame) {  
        this.car.setFrame(frame);  
    }  
  
    @Override  
    public void buildDoor(String door) {  
        this.car.setDoor(door);  
    }  
  
    @Override  
    public Car makeCar() {  
        return this.car;  
    }  
}
package creational.builder;  
  
public class Engineer {  
    private CarBuilder carBuilder;  
  
    public void setCarBuilder(CarBuilder carBuilder) {  
        this.carBuilder = carBuilder;  
    }  
  
    public Car makeCar(String basePlate, String frame, String door) {  
        carBuilder.buildBasePlate(basePlate);  
        carBuilder.buildFrame(frame);  
        carBuilder.buildDoor(door);  
        return carBuilder.makeCar();  
    }  
}
package creational.builder;  
  
public class Test {  
    public static void main(String[] args) {  
        Engineer engineer = new Engineer();  
        CarBuilder carBuilder = new CarBuilder();  
        engineer.setCarBuilder(carBuilder);  
        Car car = engineer.makeCar("底盘", "车架", "车门");  
        System.out.println(car);  
    }  
}

image.png

原型模式

  • 用于创建重复的对象,能够保证创建对象的性能
  • 原型设计模式是创建对象的最佳方式
package creational.prototype;  
  
public class Pig implements Cloneable {  
    private String name;  
    private String doSomething;  
  
    public Pig() {  
        System.out.println("小猪被初始化了...");  
    }  
  
    public String getName() {  
        return name;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
  
    public String getDoSomething() {  
        return doSomething;  
    }  
  
    public void setDoSomething(String doSomething) {  
        this.doSomething = doSomething;  
    }  
  
    @Override  
    public String toString() {  
        return "Pig{" +  
                "name='" + name + '\'' +  
                ", doSomething='" + doSomething + '\'' +  
                '}' + super.toString();  
    }  
  
    @Override  
    protected Object clone() throws CloneNotSupportedException {  
        return super.clone();  
    }  
}
package creational.prototype;  
  
public class Test {  
    public static void main(String[] args) throws CloneNotSupportedException {  
        Pig peki = new Pig();  
        peki.setName("佩奇");  
        peki.setDoSomething("喜欢吃蛋糕");  
        System.out.println(peki);  
  
        Pig george = (Pig) peki.clone();  
        george.setName("乔治");  
        george.setDoSomething("喜欢睡觉");  
        System.out.println(george);  
  
        Pig pigDad = (Pig) peki.clone();  
        pigDad.setName("猪爸爸");  
        pigDad.setDoSomething("喜欢开车");  
        System.out.println(pigDad);  
  
        Pig pigMom = (Pig) peki.clone();  
        pigMom.setName("猪妈妈");  
        pigMom.setDoSomething("喜欢做饭");  
        System.out.println(pigMom);  
    }  
}

image.png

单例模式

  • 在程序中想要保持一个实例对象,就使用单例模式
  • 减少内存开销
  • 懒汉式
  • 双重检查
  • 饿汉式
  • 静态内部类
  • 枚举

懒汉式

  • 在需要使用对象的时候,才会创建
package creational.singleton.lazy;  
  
public class LazySingleton {  
    private static LazySingleton lazySingleton = null;  
  
    private LazySingleton() {}  
  
    public static synchronized LazySingleton getInstance() {  
        if (lazySingleton == null)  
            lazySingleton = new LazySingleton();  
        return lazySingleton;  
    }  
}
package creational.singleton.lazy;  
  
public class Run implements Runnable {  
    @Override  
    public void run() {  
        LazySingleton lazySingleton = LazySingleton.getInstance();  
        System.out.println(Thread.currentThread().getName() + " " + lazySingleton);  
    }  
}
package creational.singleton.lazy;  
  
public class Test {  
    public static void main(String[] args) {  
        new Thread(new Run(), "t1").start();  
        new Thread(new Run(), "t2").start();  
    }  
}

image.png

双重检查

  • 通过两个 if 判断同步锁进行实现
package creational.singleton.doubleChecked;  
  
public class DoubleCheckSingleton {  
    private static DoubleCheckSingleton doubleCheckSingleton = null;  
  
    private DoubleCheckSingleton() {}  
  
    public static DoubleCheckSingleton getInstance() {  
        if (doubleCheckSingleton == null) {  
            synchronized (DoubleCheckSingleton.class) {  
                if (doubleCheckSingleton == null)  
                    doubleCheckSingleton = new DoubleCheckSingleton();  
            }  
        }  
        return doubleCheckSingleton;  
    }  
}
package creational.singleton.doubleChecked;  
  
public class Run implements Runnable {  
    @Override  
    public void run() {  
        DoubleCheckSingleton doubleCheckSingleton = DoubleCheckSingleton.getInstance();  
        System.out.println(Thread.currentThread().getName() + " " + doubleCheckSingleton);  
    }  
}
package creational.singleton.doubleChecked;  
  
public class Test {  
    public static void main(String[] args) {  
        new Thread(new Run(), "t1").start();  
        new Thread(new Run(), "t2").start();  
    }  
}

image.png

静态内部类

  • 在单例类中,通过私有的静态内部类,创建单例对象
package creational.singleton.staticInnerClass;  
  
public class StaticInnerClassSingleton {  
    private static class InnerClass {  
        private static StaticInnerClassSingleton staticInnerClassSingleton = new StaticInnerClassSingleton();  
    }  
  
    private StaticInnerClassSingleton() {}  
  
    public static StaticInnerClassSingleton getInstance() {  
        return InnerClass.staticInnerClassSingleton;  
    }  
}
package creational.singleton.staticInnerClass;  
  
public class Run implements Runnable {  
    @Override  
    public void run() {  
        StaticInnerClassSingleton staticInnerClassSingleton = StaticInnerClassSingleton.getInstance();  
        System.out.println(Thread.currentThread().getName() + " " + staticInnerClassSingleton);  
    }  
}
package creational.singleton.staticInnerClass;  
  
public class Test {  
    public static void main(String[] args) {  
        new Thread(new Run(), "t1").start();  
        new Thread(new Run(), "t2").start();  
        new Thread(new Run(), "t3").start();  
    }  
}

image.png

饿汉式

  • 在调用时,就会创建单例对象,通过静态代码块或静态变量直接初始化
package creational.singleton.hungry;  
  
public class HungrySingleton {  
    private static final HungrySingleton hungrySingleton = new HungrySingleton();  
  
    private HungrySingleton() {}  
  
    public static HungrySingleton getInstance() {  
        return hungrySingleton;  
    }  
}

package creational.singleton.hungry;  
  
public class HungrySingleton {   
    private static HungrySingleton hungrySingleton = null;  
  
    static {  
        hungrySingleton = new HungrySingleton();  
    }  
  
    private HungrySingleton() {}  
  
    public static HungrySingleton getInstance() {  
        return hungrySingleton;  
    }  
}
package creational.singleton.hungry;  
  
public class Run implements Runnable {  
    @Override  
    public void run() {  
        HungrySingleton hungrySingleton = HungrySingleton.getInstance();  
        System.out.println(Thread.currentThread().getName() + " " + hungrySingleton);  
    }  
}
package creational.singleton.hungry;  
  
public class Test {  
    public static void main(String[] args) {  
        new Thread(new Run(), "t1").start();  
        new Thread(new Run(), "t2").start();  
        new Thread(new Run(), "t3").start();  
    }  
}

image.png

枚举

  • 枚举的方式实现单例模式,是最佳的实现方式
  • 它可以有效防止对单例模式的破坏
    • 序列化和反序列化的方式破坏单例模式
    • 通过反射的方式破坏单例模式
package creational.singleton.enumSingleton;  
  
public enum EnumSingleton {  
    INSTANCE;  
  
    public static EnumSingleton getInstance() {  
        return INSTANCE;  
    }  
}
package creational.singleton.enumSingleton;  
  
public class Test {  
    public static void main(String[] args) {  
        EnumSingleton instance1 = EnumSingleton.getInstance();  
        EnumSingleton instance2 = EnumSingleton.getInstance();  
        System.out.println(instance1);  
        System.out.println(instance2);  
        System.out.println(instance1 == instance2);  
    }  
}

image.png

序列化和反序列化破坏单例模式-解决方法

  • 通过将单例对象序列化到文件中,再反序列化读取出来
  • 最终通过反序列化的方式创建出一个对象
  • 发现两个对象的内存地址完全不一致,从而破坏了单例模式的结构
package creational.singleton.broker;  
  
import creational.singleton.lazy.LazySingleton;  
  
import java.io.*;  
  
public class TestSerializer {  
    public static void main(String[] args) throws IOException, ClassNotFoundException {  
        // 懒汉式  
        LazySingleton lazySingleton = LazySingleton.getInstance();  
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("singleton"));  
        oos.writeObject(lazySingleton);  
  
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("singleton"));  
        LazySingleton objInstance = (LazySingleton) ois.readObject();  
  
        System.out.println(lazySingleton);  
        System.out.println(objInstance);  
        System.out.println(objInstance == lazySingleton);
    }  
}

image.png

只有使用枚举的方式可以防止单例结构被破坏:

package creational.singleton.broker;  
  
import creational.singleton.enumSingleton.EnumSingleton;  
  
import java.io.*;  
  
public class TestSerializer {  
    public static void main(String[] args) throws IOException, ClassNotFoundException {  
        // 枚举  
        EnumSingleton enumSingleton = EnumSingleton.getInstance();  
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("singleton"));  
        oos.writeObject(enumSingleton);  
  
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("singleton"));  
        EnumSingleton objInstance = (EnumSingleton) ois.readObject();  
  
        System.out.println(enumSingleton);  
        System.out.println(objInstance);  
        System.out.println(objInstance == enumSingleton);  
    }  
}

image.png

要想其他方式也可以防止被序列化和反序列化而破坏,需要重写 readResolve() 方法:

package creational.singleton.lazy;  
  
import java.io.Serializable;  
  
public class LazySingleton implements Serializable {  
    private static LazySingleton lazySingleton = null;  
  
    private LazySingleton() {}  
  
    public static synchronized LazySingleton getInstance() {  
        if (lazySingleton == null)  
            lazySingleton = new LazySingleton();  
        return lazySingleton;  
    }  
  
    public Object readResolve() {  
        return lazySingleton;  
    }  
}
package creational.singleton.broker;  
  
import creational.singleton.lazy.LazySingleton;  
  
import java.io.*;  
  
public class TestSerializer {  
    public static void main(String[] args) throws IOException, ClassNotFoundException {  
        // 懒汉式  
        LazySingleton lazySingleton = LazySingleton.getInstance();  
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("singleton"));  
        oos.writeObject(lazySingleton);  
  
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("singleton"));  
        LazySingleton objInstance = (LazySingleton) ois.readObject();  
  
        System.out.println(lazySingleton);  
        System.out.println(objInstance);  
        System.out.println(objInstance == lazySingleton);  
    }  
}

image.png

因为在反序列化创建对象时,是通过反射创建的,反射底层会调用 readResolve() 方法,如果重写了,就可以返回自己的单例对象;如果没有重写,则会通过反射的方式创建一个新对象,从而破坏了单例设计模式。

反射破坏单例模式-解决方法

  • 通过字节码对象创建构造器对象
  • 通过构造器对象去初始化单例对象
package creational.singleton.broker;  
  
import creational.singleton.lazy.LazySingleton;  
  
import java.lang.reflect.Constructor;  
import java.lang.reflect.InvocationTargetException;  
  
public class TestReflect {  
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {  
        Class<LazySingleton> lazySingletonClass = LazySingleton.class;  
        Constructor<LazySingleton> constructor = lazySingletonClass.getDeclaredConstructor();  
        // 赋予权限  
        constructor.setAccessible(true);  
        LazySingleton lazySingleton = constructor.newInstance();  
        System.out.println(lazySingleton);  
        LazySingleton lazySingleton1 = LazySingleton.getInstance();  
        System.out.println(lazySingleton1);  
        System.out.println(lazySingleton1 == lazySingleton);  
    }  
}

image.png

通过使用枚举来实现单例模式可以避免这个问题:

package creational.singleton.broker;  
  
import creational.singleton.enumSingleton.EnumSingleton;  
  
import java.lang.reflect.Constructor;  
import java.lang.reflect.InvocationTargetException;  
  
public class TestReflect {  
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {  
        Class<EnumSingleton> enumSingletonClass = EnumSingleton.class;  
        Constructor<EnumSingleton> constructor = enumSingletonClass.getDeclaredConstructor(String.class, int.class);  
        // 赋予权限  
        constructor.setAccessible(true);  
        EnumSingleton enumSingleton = constructor.newInstance("abc", 666);  
        System.out.println(enumSingleton);  
        EnumSingleton enumSingleton1 = EnumSingleton.getInstance();  
        System.out.println(enumSingleton1);  
        System.out.println(enumSingleton1 == enumSingleton);  
    }  
}

image.png

在使用枚举时,通过反射创建枚举对象,是不被允许的,会抛出异常

在其他的单例模式中,也可以通过模拟这种实现方式,不允许通过反射创建:

package creational.singleton.lazy;  
  
import java.io.Serializable;  
  
public class LazySingleton implements Serializable {  
    private static LazySingleton lazySingleton = null;  
  
    private LazySingleton() {  
        if (lazySingleton == null)  
            throw new RuntimeException("不允许通过反射创建单例对象");  
    }  
  
    public static synchronized LazySingleton getInstance() {  
        if (lazySingleton == null)  
            lazySingleton = new LazySingleton();  
        return lazySingleton;  
    }  
  
    public Object readResolve() {  
        return lazySingleton;  
    }  
}
package creational.singleton.broker;  
  
import creational.singleton.enumSingleton.EnumSingleton;  
import creational.singleton.lazy.LazySingleton;  
  
import java.lang.reflect.Constructor;  
import java.lang.reflect.InvocationTargetException;  
  
public class TestReflect {  
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {  
        Class<LazySingleton> lazySingletonClass = LazySingleton.class;  
        Constructor<LazySingleton> constructor = lazySingletonClass.getDeclaredConstructor();  
        // 赋予权限  
        constructor.setAccessible(true);  
        LazySingleton lazySingleton = constructor.newInstance();  
        System.out.println(lazySingleton);  
        LazySingleton lazySingleton1 = LazySingleton.getInstance();  
        System.out.println(lazySingleton1);  
        System.out.println(lazySingleton1 == lazySingleton);  
    }  
}

image.png

外观模式

  • 又被称为门面模式
  • 提供了一个统一的接口,用来访问子系统中的一群接口
  • 定义了一个高层接口,让子系统使用更加容易
package structural.faced;  
  
public class OrderService {  
    public void makeOrder() {  
        System.out.println("生成订单");  
    }  
}
package structural.faced;  
  
public class PayService {  
    public void pay() {  
        System.out.println("正在支付");  
    }  
  
    public boolean checkBalance() {  
        System.out.println("检查用户的余额");  
        return true;    }  
}
package structural.faced;  
  
public class TakeService {  
    public void taking() {  
        System.out.println("外卖正在制作中,请稍后...");  
    }  
}
package structural.faced;  
  
public class Food {  
    private String name;  
  
    public String getName() {  
        return name;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
}
package structural.faced;  
  
public class SelectFoodService {  
    public void select(String name) {  
        System.out.println("点餐成功:" + name);  
    }  
}
package structural.faced;  
  
public class TakingSystem {  
    private SelectFoodService selectFoodService;  
    private PayService payService;  
    private OrderService orderService;  
    private TakeService takeService;  
  
    public TakingSystem() {  
        selectFoodService = new SelectFoodService();  
        payService = new PayService();  
        orderService = new OrderService();  
        takeService = new TakeService();  
    }  
  
    public void orderTaking(Food food) {  
        // 点餐  
        selectFoodService.select(food.getName());  
        // 校验余额  
        boolean b = payService.checkBalance();  
        if (b) {  
            // 支付  
            payService.pay();  
            // 生成订单  
            orderService.makeOrder();  
            // 制作外卖  
            takeService.taking();  
        }  
    }  
}
package structural.faced;  
  
public class Test {  
    public static void main(String[] args) {  
        Food food = new Food();  
        food.setName("鱼香肉丝");  
        TakingSystem takingSystem = new TakingSystem();  
        takingSystem.orderTaking(food);  
    }  
}

image.png

适配器模式

  • 适配器模式是作为两个不兼容的接口之间的桥梁,将一个接口转换成用户希望的另一个接口
  • 适配器模式使得原本由于接口不兼容而不能一起工作的类可以一起工作
  • 它结合了两个独立接口的功能
package structural.adapter;  
  
/**  
 * 媒体播放器接口  
 */  
public interface MediaPlayer {  
    void play(String audioType, String filename);  
}
package structural.adapter;  
  
/**  
 * 高级媒体播放器接口  
 */  
public interface AdvancedMediaPlayer {  
    void playVlc(String filename);  
    void playMp4(String filename);  
}
package structural.adapter;  
  
public class VlcPlayer implements AdvancedMediaPlayer{  
    @Override  
    public void playVlc(String filename) {  
        System.out.println("播放vlc文件:" + filename);  
    }  
  
    @Override  
    public void playMp4(String filename) {  
        // 当前格式为vlc,MP4格式不做具体实现  
    }  
}
package structural.adapter;  
  
public class Mp4Player implements AdvancedMediaPlayer{  
    @Override  
    public void playVlc(String filename) {  
        // 当前格式为mp4,vlc格式不做实现  
    }  
  
    @Override  
    public void playMp4(String filename) {  
        System.out.println("播放mp4文件:" + filename);  
    }  
}

编写适配器:

package structural.adapter;  
  
/**  
 * 媒体播放器适配器  
 */  
public class MediaPlayerAdapter implements MediaPlayer {  
    private AdvancedMediaPlayer advancedMediaPlayer;  
  
    public MediaPlayerAdapter(String audioType) {  
        if ("vlc".equalsIgnoreCase(audioType)) {  
            advancedMediaPlayer = new VlcPlayer();  
        } else if ("mp4".equalsIgnoreCase(audioType)) {  
            advancedMediaPlayer = new Mp4Player();  
        }  
    }  
  
    @Override  
    public void play(String audioType, String filename) {  
        if ("vlc".equalsIgnoreCase(audioType)) {  
            advancedMediaPlayer.playVlc(filename);  
        } else if ("mp4".equalsIgnoreCase(audioType)) {  
            advancedMediaPlayer.playMp4(filename);  
        }  
    }  
}

编写 AudioPlayer 类:

package structural.adapter;  
  
public class AudioPlayer implements MediaPlayer {  
    private MediaPlayerAdapter mediaPlayerAdapter;  
  
    @Override  
    public void play(String audioType, String filename) {  
        if ("mp3".equalsIgnoreCase(audioType)) {  
            // 音频文件  
            System.out.println("播放mp3文件:" + filename);  
        } else if ("vlc".equalsIgnoreCase(audioType) || "mp4".equalsIgnoreCase(audioType)) {  
            // 视频文件  
            mediaPlayerAdapter = new MediaPlayerAdapter(audioType);  
            mediaPlayerAdapter.play(audioType, filename);  
        }  
    }  
}

测试:

package structural.adapter;  
  
public class Test {  
    public static void main(String[] args) {  
        AudioPlayer audioPlayer = new AudioPlayer();  
        audioPlayer.play("mp3", "老中医.mp3");  
        audioPlayer.play("vlc", "老中医.vlc");  
        audioPlayer.play("mp4", "老中医.mp4");  
    }  
}

image.png

桥接模式

  • 把抽象化与实现化解耦,使得二者可以独立变化
  • 通过提供抽象化和实现化之间的桥接结构,来实现二者解耦
  • 需要提供一个作为桥接的接口,使得实体类的功能独立于接口实现类,这两种类型的类结构改变而互不影响
package structural.bridge;  
  
/**  
 * 图形接口  
 */  
public interface Shape {  
    void draw(String tool);  
}
package structural.bridge;  
  
public class Circle implements Shape {  
    @Override  
    public void draw(String tool) {  
        System.out.println("使用" + tool + "画了一个圆形");  
    }  
}
package structural.bridge;  
  
public class Square implements Shape{  
    @Override  
    public void draw(String tool) {  
        System.out.println("使用" + tool + "画了一个方形");  
    }  
}
package structural.bridge;  
  
public abstract class Tools {  
    public Tools(Shape shape) {}  
  
    public abstract void use();  
}
package structural.bridge;  
  
public class Pencil extends Tools {  
    private Shape shape;  
  
    public Pencil(Shape shape) {  
        super(shape);  
        this.shape = shape;  
    }  
  
    @Override  
    public void use() {  
        shape.draw("铅笔");  
    }  
}
package structural.bridge;  
  
public class Pen extends Tools {  
    private Shape shape;  
  
    public Pen(Shape shape) {  
        super(shape);  
        this.shape = shape;  
    }  
  
    @Override  
    public void use() {  
        shape.draw("钢笔");  
    }  
}
package structural.bridge;  
  
public class Test {  
    public static void main(String[] args) {  
        // 使用工具绘制图形  
        Tools tools1 = new Pencil(new Circle());  
        tools1.use();  
  
        Tools tools2 = new Pen(new Square());  
        tools2.use();  
    }  
}

image.png

组合模式

  • 又叫部分整体模式,用于把一组相似的对象当作一个单一的对象
  • 组合模式依据树形结构来组合对象,用来表示部分以及整体层次
  • 创建了对象组的树形结构
  • 这种模式创建了一个包含自己对象组的类,该类提供了修改相同对象组的方式
package structural.composite;  
  
import java.util.ArrayList;  
import java.util.List;  
  
public class Employee {  
    private String name;  
    private String deptNo;  
    private Long salary;  
    private List<Employee> employeeList;  
  
    public Employee(String name, String deptNo, Long salary) {  
        this.name = name;  
        this.deptNo = deptNo;  
        this.salary = salary;  
        this.employeeList = new ArrayList<>();  
    }  
  
    public void add(Employee employee) {  
        this.employeeList.add(employee);  
    }  
  
    public void remove(Employee employee) {  
        this.employeeList.remove(employee);  
    }  
  
    public String getName() {  
        return name;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
  
    public String getDeptNo() {  
        return deptNo;  
    }  
  
    public void setDeptNo(String deptNo) {  
        this.deptNo = deptNo;  
    }  
  
    public Long getSalary() {  
        return salary;  
    }  
  
    public void setSalary(Long salary) {  
        this.salary = salary;  
    }  
  
    public List<Employee> getEmployeeList() {  
        return employeeList;  
    }  
  
    public void setEmployeeList(List<Employee> employeeList) {  
        this.employeeList = employeeList;  
    }  
  
    @Override  
    public String toString() {  
        return "姓名:'" + name + '\'' +  
                ", 部门编号:'" + deptNo + '\'' +  
                ", 薪资:" + salary;  
    }  
}
package structural.composite;  
  
public class Test {  
    public static void main(String[] args) {  
        // 创建CEO  
        Employee ceo = new Employee("张三", "1", 20000L);  
        // 创建部门经理  
        Employee manager = new Employee("李四", "2", 10000L);  
        // 创建销售员  
        Employee saler1 = new Employee("王五", "3", 5000L);  
        Employee saler2 = new Employee("田七", "3", 5000L);  
        // 创建仓库管理员  
        Employee stock = new Employee("赵六", "4", 3000L);  
        // 添加层级关系  
        ceo.add(manager);  
        manager.add(saler1);  
        manager.add(saler2);  
        manager.add(stock);  
        System.out.println(ceo);  
        for (Employee employee : ceo.getEmployeeList()) {  
            System.out.println("姓名:" + employee.getName() +  
                    " 部门编号:" + employee.getDeptNo() +  
                    " 薪资:" + employee.getSalary()  
            );  
            for (Employee e : employee.getEmployeeList()) {  
                System.out.println("姓名:" + e.getName() +  
                        " 部门编号:" + e.getDeptNo() +  
                        " 薪资:" + e.getSalary()  
                );  
            }  
        }  
    }  
}

image.png

代理模式

  • 为对象提供一种代理,以控制这个对象的访问操作
  • 代理对象目标对象之间起到中介的作用
  • 保护目标对象和增强目标对象
  • 代理模式能将代理对象与真实被调用的目标对象分离
  • 一定程度上降低了系统的耦合度,扩展性好

静态代理

package structural.proxy.staticProxy;  
  
public class Order {  
    private String info;  
    private String userId;  
  
    public String getInfo() {  
        return info;  
    }  
  
    public void setInfo(String info) {  
        this.info = info;  
    }  
  
    public String getUserId() {  
        return userId;  
    }  
  
    public void setUserId(String userId) {  
        this.userId = userId;  
    }  
  
    @Override  
    public String toString() {  
        return "Order{" +  
                "info='" + info + '\'' +  
                ", userId='" + userId + '\'' +  
                '}';  
    }  
}
package structural.proxy.staticProxy;  
  
public interface OrderDao {  
    int insert(Order order);  
}
package structural.proxy.staticProxy;  
  
public class OrderDaoImpl implements OrderDao{  
    @Override  
    public int insert(Order order) {  
        System.out.println("持久层,保存订单信息");  
        return 1;  
    }  
}
package structural.proxy.staticProxy;  
  
public interface OrderService {  
    int saveOrder(Order order);  
}
package structural.proxy.staticProxy;  
  
public class OrderServiceImpl implements OrderService {  
    private OrderDao orderDao;  
  
    @Override  
    public int saveOrder(Order order) {  
        System.out.println("业务层,调用持久层");  
        orderDao = new OrderDaoImpl();  
        return orderDao.insert(order);  
    }  
}

创建代理对象:

package structural.proxy.staticProxy;  
  
public class OrderServiceImplStaticProxy {  
    private OrderService orderService;  
  
    public int saveOrder(Order order) {  
        orderService = new OrderServiceImpl();  
        before();  
        System.out.println("代理对象调用业务层");  
        int i = orderService.saveOrder(order);  
        after();  
        return i;  
    }  
  
    private void before() {  
        System.out.println("代理对象,开启事务");  
    }  
  
    private void after() {  
        System.out.println("代理对象,提交事务");  
    }  
}

测试:

package structural.proxy.staticProxy;  
  
public class Test {  
    public static void main(String[] args) {  
        Order order = new Order();  
        order.setInfo("订单信息");  
        order.setUserId("1");  
        OrderServiceImplStaticProxy proxy = new OrderServiceImplStaticProxy();  
        proxy.saveOrder(order);  
    }  
}

image.png

动态代理

package structural.proxy.dynamicProxy;  
  
import structural.proxy.staticProxy.Order;  
import structural.proxy.staticProxy.OrderService;  
import structural.proxy.staticProxy.OrderServiceImpl;  
  
import java.lang.reflect.InvocationHandler;  
import java.lang.reflect.Method;  
import java.lang.reflect.Proxy;  
  
public class OrderServiceImplDynamicProxy implements InvocationHandler {  
    private Object orderService;  
  
    public OrderServiceImplDynamicProxy(Object orderService) {  
        this.orderService = orderService;  
    }  
  
    public Object bind() {  
        return Proxy.newProxyInstance(orderService.getClass().getClassLoader(), orderService.getClass().getInterfaces(), this);  
    }  
  
    private void before() {  
        System.out.println("代理对象,开启事务");  
    }  
  
    private void after() {  
        System.out.println("代理对象,提交事务");  
    }  
  
    @Override  
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
        before();  
        Object result = method.invoke(orderService, args);  
        after();  
        return result;  
    }  
}
package structural.proxy.dynamicProxy;  
  
public class Test {  
    public static void main(String[] args) {  
        Order order = new Order();  
        order.setInfo("订单信息");  
        order.setUserId("1");  
        OrderService proxy = (OrderService) new OrderServiceImplDynamicProxy(new OrderServiceImpl()).bind();  
        proxy.saveOrder(order);  
    }  
}

image.png

装饰者模式

  • 在原有对象不做改变的基础上,将给对象附加新的功能
  • 提供了比继承更有弹性的替代方案(扩展原有对象功能)
  • 扩展一个类的功能或给一个类附加职责
  • 动态地给一个对象添加功能,这些功能可以再动态地撤销
  • 继承的有力补充,比继承灵活,不改变原有对象的情况下,给一个对象扩展功能
  • 通过使用不同装饰类以及这些装饰类排列组合,可以实现不同的效果
package structural.decorator;  
  
public abstract class ABatterCake {  
    protected abstract String getInfo();  
    protected abstract int getCost();  
}
package structural.decorator;  
  
public class BatterCake extends ABatterCake {  
    @Override  
    protected String getInfo() {  
        return "煎饼";  
    }  
  
    @Override  
    protected int getCost() {  
        return 6;  
    }  
}
package structural.decorator;  
  
public abstract class ADecorator extends ABatterCake {  
    private ABatterCake aBatterCake;  
  
    public ADecorator(ABatterCake aBatterCake) {  
        this.aBatterCake = aBatterCake;  
    }  
  
    @Override  
    protected String getInfo() {  
        return this.aBatterCake.getInfo();  
    }  
  
    @Override  
    protected int getCost() {  
        return this.aBatterCake.getCost();  
    }  
  
    protected abstract void something();  
}
package structural.decorator;  
  
public class EggDecorator extends ADecorator {  
  
    @Override  
    protected String getInfo() {  
        return super.getInfo() + ",加一个鸡蛋";  
    }  
  
    @Override  
    protected int getCost() {  
        return super.getCost() + 2;  
    }  
  
    public EggDecorator(ABatterCake aBatterCake) {  
        super(aBatterCake);  
    }  
  
    @Override  
    protected void something() {  
  
    }
}
package structural.decorator;  
  
public class SausageDecorator extends ADecorator{  
    @Override  
    protected String getInfo() {  
        return super.getInfo() + ",加一根香肠";  
    }  
  
    @Override  
    protected int getCost() {  
        return super.getCost() + 3;  
    }  
  
    public SausageDecorator(ABatterCake aBatterCake) {  
        super(aBatterCake);  
    }  
  
    @Override  
    protected void something() {  
  
    }
}
package structural.decorator;  
  
public class Test {  
    public static void main(String[] args) {  
        ABatterCake batterCake = new BatterCake();  
        batterCake = new EggDecorator(batterCake);  
        batterCake = new SausageDecorator(batterCake);  
        batterCake = new SausageDecorator(batterCake);  
        System.out.println("套餐信息:" + batterCake.getInfo() + " " + "价格:" + batterCake.getCost());  
    }  
}

image.png

享元模式

  • 提供了减少对象数量从而改善应用所需的对象结构的方式
  • 运用共享技术有效地支持大量细粒度的对象
  • 总结:减少创建对象的数量,从而减少内存的占用,提升性能
package structural.flyweight;  
  
public interface Employee {  
    void report();  
}
package structural.flyweight;  
  
public class Manager implements Employee{  
    private String department;  
    private String content;  
  
    public Manager() {  
    }  
    public Manager(String department, String content) {  
        this.department = department;  
        this.content = content;  
    }  
  
    public String getDepartment() {  
        return department;  
    }  
  
    public void setDepartment(String department) {  
        this.department = department;  
    }  
  
    public String getContent() {  
        return content;  
    }  
  
    public void setContent(String content) {  
        this.content = content;  
    }  
  
    @Override  
    public void report() {  
        System.out.println(this.content);  
    }  
}
 package structural.flyweight;  
  
import java.util.HashMap;  
import java.util.Map;  
  
public class ManagementFactory {  
    private static final Map<String, Employee> EMPLOYEE_MAP = new HashMap<>();  
  
    public static Employee getManager(String department) {  
        Manager manager = (Manager) EMPLOYEE_MAP.get(department);  
        if (manager == null) {  
            System.out.println("====================================");  
            System.out.println("创建部门经理:" + department);  
            manager = new Manager(department, department + "部门来此汇报工作");  
            EMPLOYEE_MAP.put(department, manager);  
        }  
        return manager;  
    }  
}
package structural.flyweight;  
  
public class Test {  
    private static final String[] DEPARTMENTS = new String[]{"市场部", "营销部", "广告部", "业务服务部"};  
  
    public static void main(String[] args) {  
        for (String department : DEPARTMENTS) {  
            Employee manager = ManagementFactory.getManager(department);  
            manager.report();  
            System.out.println(department + "部门会报完成");  
            System.out.println("====================================");  
        }  
    }  
}

image.png

模板方法模式

  • 定义了一个算法的架构,并允许子类为一个或多个步骤提供实现
  • 在子类不改变算法结构的情况下,重新定义算法的某些步骤
  • 实现一个算法的不变部分,并将可变部分留给子类来完成
  • 将子类中公共的行为抽出来并封装到一个公共父类中,避免代码重复
package behavior.templateMethod;  
  
public abstract class AClass {  
    protected final void makeClass() {  
        this.makePPT();  
        this.makeVideo();  
        if (flag()) {  
            this.makeNote();  
        }  
        this.doSomething();  
    }  
  
    public final void makePPT() {  
        System.out.println("制作课程的PPT");  
    }  
  
    public final void makeVideo() {  
        System.out.println("制作课程的视频");  
    }  
  
    public final void makeNote() {  
        System.out.println("制作课程的讲义");  
    }  
  
    protected boolean flag() {  
        return false;  
    }  
  
    public abstract void doSomething();  
}
package behavior.templateMethod;  
  
public class DesignPatternClass extends AClass{  
    private boolean flag;  
  
    public DesignPatternClass(boolean flag) {  
        this.flag = flag;  
    }  
  
    @Override  
    protected boolean flag() {  
        return this.flag;  
    }  
  
    @Override  
    public void doSomething() {  
        System.out.println("提供设计模式课程的源代码");  
    }  
}
package behavior.templateMethod;  
  
public class H5Class extends AClass{  
    @Override  
    protected boolean flag() {  
        return super.flag();  
    }  
  
    @Override  
    public void doSomething() {  
        System.out.println("提供前端课程的素材及代码");  
    }  
}
package behavior.templateMethod;  
  
public class Test {  
    public static void main(String[] args) {  
        AClass c = new DesignPatternClass(true);  
        c.makeClass();  
        System.out.println("==============================");  
        c = new H5Class();  
        c.makeClass();  
    }  
}

image.png

迭代器模式

  • 提供方法,顺序访问集合对象中的各个元素,而又不暴露对象的内部表示
  • 为遍历不同的集合提供统一的接口,分离了集合对象的遍历行为
package behavior.iterator;  
  
public interface Iterator {  
    boolean hasNext();  
    Object next();  
}
package behavior.iterator;  
  
public interface Container {  
    Iterator getIterator();  
}
package behavior.iterator;  
  
public class NameContainer implements Container {  
    public String[] names = {"张三", "李四", "王五", "赵六", "田七"};  
  
    @Override  
    public Iterator getIterator() {  
        return new NameIterator();  
    }  
  
    private class NameIterator implements Iterator {  
        int index;  
  
        @Override  
        public boolean hasNext() {  
            return index < names.length;  
        }  
  
        @Override  
        public Object next() {  
            if (this.hasNext()) {  
                return names[index++];  
            }  
            throw new IndexOutOfBoundsException();  
        }  
    }  
}
package behavior.iterator;  
  
public class Test {  
    public static void main(String[] args) {  
        Container container = new NameContainer();  
        for (Iterator iterator = container.getIterator(); iterator.hasNext(); ) {  
            String name = (String) iterator.next();  
            System.out.println(name);  
        }  
    }  
}

image.png

策略模式

  • 定义了算法,分别封装起来,它们直接可以相互替换,让算法的变化不会影响到使用算法的用户
  • 如果有大量的 if else,可以使用策略模式进行替换
  • 避免使用多条条件判断
  • 提高算法的保密性和安全性
package behavior.strategy;  
  
public interface Strategy {  
    int operation(int num1, int num2);  
}
package behavior.strategy;  
  
public class AddStrategy implements Strategy {  
    @Override  
    public int operation(int num1, int num2) {  
        return num1 + num2;  
    }  
}
package behavior.strategy;  
  
public class SubtractStrategy implements Strategy {  
    @Override  
    public int operation(int num1, int num2) {  
        return num1 - num2;  
    }  
}
package behavior.strategy;  
  
public class MultiplyStrategy implements Strategy{  
    @Override  
    public int operation(int num1, int num2) {  
        return num1 * num2;  
    }  
}
package behavior.strategy;  
  
public class Operation {  
    private Strategy strategy;  
  
    public Operation(Strategy strategy) {  
        this.strategy = strategy;  
    }  
  
    public int execute(int num1, int num2) {  
        return strategy.operation(num1, num2);  
    }  
}
package behavior.strategy;  
  
public class Test {  
    public static void main(String[] args) {  
        Operation operation = new Operation(new AddStrategy());  
        System.out.println(operation.execute(1, 3));  
        System.out.println("========================");  
        operation = new Operation(new SubtractStrategy());  
        System.out.println(operation.execute(1, 3));  
        System.out.println("========================");  
        operation = new Operation(new MultiplyStrategy());  
        System.out.println(operation.execute(1, 3));  
    }  
}

image.png

解释器模式

  • 通过给定的语言,定义它的语法和行为,并定义解释器,这个解释器用来解释语言中的句子
  • 为了解释一种语言而为语言创建的解释器
    • 某个类型问题触发频次足够高,比如处理日志和不同日志格式
package behavior.interpreter;  
  
public interface Expression {  
    boolean interpret(String context);  
}
package behavior.interpreter;  
  
public class TerminalExpression implements Expression{  
    private String data;  
  
    public TerminalExpression(String data) {  
        this.data = data;  
    }  
  
    @Override  
    public boolean interpret(String context) {  
        return context.contains(data);  
    }  
}
package behavior.interpreter;  
  
public class OrExpression implements Expression{  
    private Expression expression1;  
    private Expression expression2;  
  
    public OrExpression(Expression expression1, Expression expression2) {  
        this.expression1 = expression1;  
        this.expression2 = expression2;  
    }  
  
    @Override  
    public boolean interpret(String context) {  
        return expression1.interpret(context) || expression2.interpret(context);  
    }  
}
package behavior.interpreter;  
  
public class AddExpression implements Expression{  
    private Expression expression1;  
    private Expression expression2;  
  
    public AddExpression(Expression expression1, Expression expression2) {  
        this.expression1 = expression1;  
        this.expression2 = expression2;  
    }  
  
    @Override  
    public boolean interpret(String context) {  
        return expression1.interpret(context) && expression2.interpret(context);  
    }  
}
package behavior.interpreter;  
  
public class Test {  
    public static void main(String[] args) {  
        Expression zhagnsan = new TerminalExpression("zhangsan");  
        Expression lisi = new TerminalExpression("lisi");  
        OrExpression orExpression = new OrExpression(zhagnsan, lisi);  
        System.out.println("张三是一个男人吗?" + orExpression.interpret("zhangsan"));  
        Expression wangwu = new TerminalExpression("wangwu");  
        Expression zhaoliu = new TerminalExpression("married");  
        AddExpression addExpression = new AddExpression(wangwu, zhaoliu);  
        System.out.println("王五是否已婚?" + addExpression.interpret("wangwu married"));  
    }  
}

image.png

观察者模式

  • 当对象间存在一对多关系时,则使用观察者模式
  • 比如,当一个对象被修改,会自动通知依赖它的对象
  • 让多个观察者对象同时监听某一个主题对象,当主题对象发生变化时,它的所有依赖者(观察者)都会收到通知并更新
package behavior.observer;  
  
import java.util.ArrayList;  
import java.util.List;  
  
public class Subject {  
    private List<Observer> observerList = new ArrayList<>();  
    private int state;  
  
    public void bind(Observer observer) {  
        observerList.add(observer);  
    }  
  
    public void notifyObservers() {  
        for (Observer observer : observerList) {  
            observer.update();  
        }  
    }  
  
    public int getState() {  
        return state;  
    }  
  
    public void setState(int state) {  
        this.state = state;  
        notifyObservers();  
    }  
}
package behavior.observer;  
  
public abstract class Observer {  
    protected Subject subject;  
    public abstract void update();  
}
package behavior.observer;  
  
public class HexObserver extends Observer {  
    public HexObserver(Subject subject) {  
        // 将当前观察者与主题绑定  
        this.subject = subject;  
        // 将当前观察者添加到主题的观察者列表中  
        this.subject.bind(this);  
    }  
  
    @Override  
    public void update() {  
        System.out.println("Hex String:" + Integer.toHexString(subject.getState()));  
    }  
}
package behavior.observer;  
  
public class BinaryObserver extends Observer {  
    public BinaryObserver(Subject subject) {  
        // 将当前观察者与主题绑定  
        this.subject = subject;  
        // 将当前观察者添加到主题的观察者列表中  
        this.subject.bind(this);  
    }  
  
    @Override  
    public void update() {  
        System.out.println("Binary String:" + Integer.toBinaryString(subject.getState()));  
    }  
}
package behavior.observer;  
  
public class Test {  
    public static void main(String[] args) {  
        Subject subject = new Subject();  
        new BinaryObserver(subject);  
        new HexObserver(subject);  
  
        System.out.println("==========状态值为:15==========");  
        subject.setState(15);  
        System.out.println("===============================");  
        System.out.println("==========状态值为:8==========");  
        subject.setState(8);  
        System.out.println("===============================");  
    }  
}

image.png

备忘录模式

  • 在不破坏封装新的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态
  • 可以在以后将对象恢复到原先保存的状态
  • 很多时候我们总是需要去记录一个对象的内部状态,这样做的目的就是为了允许用户取消不确定或者错误的操作,能够恢复到原先的状态
package behavior.memorandum;  
  
public class Order {  
    private String state;  
  
    public Order(String state) {  
        this.state = state;  
    }  
  
    public String getState() {  
        return state;  
    }  
}
package behavior.memorandum;  
  
public class Memorandum {  
    private String state;  
  
    public String getState() {  
        return state;  
    }  
  
    public void setState(String state) {  
        this.state = state;  
    }  
  
    public Order saveStateToOrder() {  
        return new Order(state);  
    }  
  
    public void getStateFromOrder(Order order) {  
        this.state = order.getState();  
    }  
}
package behavior.memorandum;  
  
import java.util.ArrayList;  
import java.util.List;  
  
public class Container {  
    private List<Order> orderList = new ArrayList<>();  
  
    public void add(Order order) {  
        this.orderList.add(order);  
    }  
  
    public Order getOrder(int index) {  
        return this.orderList.get(index);  
    }  
}
package behavior.memorandum;  
  
public class Test {  
    public static void main(String[] args) {  
        Memorandum memorandum = new Memorandum();  
        Container container = new Container();  
        memorandum.setState("1# 打开冰箱");  
        container.add(memorandum.saveStateToOrder());  
        memorandum.setState("2# 将大象放进去");  
        container.add(memorandum.saveStateToOrder());  
        memorandum.setState("3# 关上冰箱门");  
        container.add(memorandum.saveStateToOrder());  
  
        System.out.println("==========当前步骤==========");  
        System.out.println(memorandum.getState());  
  
        System.out.println("==========备忘录==========");  
        Order order = container.getOrder(0);  
        memorandum.getStateFromOrder(order);  
        System.out.println(memorandum.getState());  
        order = container.getOrder(1);  
        memorandum.getStateFromOrder(order);  
        System.out.println(memorandum.getState());  
        order = container.getOrder(2);  
        memorandum.getStateFromOrder(order);  
        System.out.println(memorandum.getState());  
    }  
}

image.png

命令模式

  • 请求调用者和行为实现者解耦合,使得调用者和行为实现者不直接交互
package behavior.command;  
  
public interface Order {  
    void execute();  
}
package behavior.command;  
  
/**  
 * 股票类  
 */  
public class Stock {  
    private String name = "aaa";  
    private int count = 10;  
  
    public void buy() {  
        System.out.println("购买 [股票:" + name + "],数量: " + count + "支");  
    }  
  
    public void sale() {  
        System.out.println("卖出 [股票:" + name + "],数量: " + count + "支");  
    }  
}
package behavior.command;  
  
/**  
 * 购买股票  
 */  
public class BuyStock implements Order{  
    private Stock aaaStock;  
  
    public BuyStock(Stock aaaStock) {  
        this.aaaStock = aaaStock;  
    }  
  
    @Override  
    public void execute() {  
        aaaStock.buy();  
    }  
}
package behavior.command;  
  
/**  
 * 出售股票  
 */  
public class SaleStock implements Order{  
    private Stock aaaStock;  
  
    public SaleStock(Stock aaaStock) {  
        this.aaaStock = aaaStock;  
    }  
  
    @Override  
    public void execute() {  
        aaaStock.sale();  
    }  
}
package behavior.command;  
  
import java.util.ArrayList;  
import java.util.List;  
  
/**  
 * 股票经纪人,记录用户操作的命令  
 */  
public class Broker {  
    private List<Order> orderList = new ArrayList<>();  
  
    public void takeOrder(Order order) {  
        orderList.add(order);  
    }  
  
    public void placeOrders() {  
        for (Order order : orderList) {  
            order.execute();  
        }  
        orderList.clear();  
    }  
}
package behavior.command;  
  
public class Test {  
    public static void main(String[] args) {  
        Stock aaaStock = new Stock();  
        BuyStock buyStock = new BuyStock(aaaStock);  
        SaleStock saleStock = new SaleStock(aaaStock);  
        Broker broker = new Broker();  
        broker.takeOrder(buyStock);  
        broker.takeOrder(saleStock);  
        broker.placeOrders();  
    }  
}

image.png

中介者模式

  • 降低多个对象和类之间通信复杂度
  • 用一个中介对量来封装一系列的对象交互,中介者使用各对象不需要显式地相互引用,从而实现松耦合,而且可以独立的改变它们之间的交互
  • 对象与对象之间存在大量的关联关系,这样势必会导致系统的结构变得很复杂,同时若一个对象发生改变,我们需要跟踪与之相关的对象,同时做出相应的处理
package behavior.mediator;  
  
public class User {  
    private String name;  
  
    public User(String name) {  
        this.name = name;  
    }  
  
    public String getName() {  
        return name;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
  
    public void sendMessage(String message) {  
        Role.work(this, message);  
    }  
}
package behavior.mediator;  
  
public class Role {  
    public static void work(User user, String message) {  
        System.out.println("姓名:" + user.getName() + ",任务:" + message);  
    }  
}
package behavior.mediator;  
  
public class Test {  
    public static void main(String[] args) {  
        User zhangsan = new User("张三");  
        User lisi = new User("李四");  
        zhangsan.sendMessage("李四帮我定一下外卖");  
        lisi.sendMessage("好的");  
    }  
}

image.png

责任链模式

  • 为请求创建了一个接收者对象的链,对请求的发送者和接收者进行解耦
  • 通常每个接收者都包含对另一个接收者的引用,如果当前接收者不能处理该请求,那么他会把请求传递给下一个接收者
  • 避免请求发送者和接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止
  • 职责链上的处理者负责处理请求,用户只需要将请求发送到职责链上即可,无需关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者进行了解耦
package behavior.chain;  
  
public abstract class AbstractLogger {  
    public static final int INFO = 1;  
    public static final int DEBUG = 2;  
    public static final int ERROR = 3;  
  
    protected AbstractLogger nextLogger;  
    protected int level;  
  
    public void setNextLogger(AbstractLogger nextLogger) {  
        this.nextLogger = nextLogger;  
    }  
  
    public void logMessage(int level, String message) {  
        if (this.level <= level)  
            write(message);  
        if (this.nextLogger != null)  
            this.nextLogger.logMessage(level, message);  
    }  
  
    protected abstract void write(String message);  
}
package behavior.chain;  
  
public class InfoLogger extends AbstractLogger {  
  
    public InfoLogger(int level) {  
        this.level = level;  
    }  
  
    @Override  
    protected void write(String message) {  
        System.out.println("INFO >>> " + message);  
    }  
}
package behavior.chain;  
  
public class DebugLogger extends AbstractLogger {  
  
    public DebugLogger(int level) {  
        this.level = level;  
    }  
  
    @Override  
    protected void write(String message) {  
        System.out.println("DEBUG >>> " + message);  
    }  
}
package behavior.chain;  
  
public class ErrorLogger extends AbstractLogger {  
  
    public ErrorLogger(int level) {  
        this.level = level;  
    }  
  
    @Override  
    protected void write(String message) {  
        System.out.println("ERROR >>> " + message);  
    }  
}
package behavior.chain;  
  
public class Test {  
    public static AbstractLogger getChainOfLogger() {  
        AbstractLogger infoLogger = new InfoLogger(AbstractLogger.INFO);  
        AbstractLogger debugLogger = new DebugLogger(AbstractLogger.DEBUG);  
        AbstractLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);  
        infoLogger.setNextLogger(debugLogger);  
        debugLogger.setNextLogger(errorLogger);  
        return infoLogger;  
    }  
  
    public static void main(String[] args) {  
        AbstractLogger logger = getChainOfLogger();  
        logger.logMessage(AbstractLogger.INFO, "info message");  
        logger.logMessage(AbstractLogger.DEBUG, "debug message");  
        logger.logMessage(AbstractLogger.ERROR, "error message");  
    }  
}

image.png

访问者模式

  • 使用一个访问者类,它改变了元素类的执行算法
  • 通过这种方式,元素的执行算法可以随着访问者的改变而改变
  • 元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作
  • 将数据结构与数据操作分离
package behavior.visitor;  
  
public interface ComputerPartVisitor {  
    void visit(Keyboard keyboard);  
  
    void visit(Mouse mouse);  
  
    void visit(Monitor monitor);  
  
    void visit(Computer computer);  
}
package behavior.visitor;  
  
/**  
 * 电脑组件接口  
 */  
public interface ComputerPart {  
    void accept(ComputerPartVisitor computerPartVisitor);  
}
package behavior.visitor;  
  
/**  
 * 鼠标  
 */  
public class Mouse implements ComputerPart{  
    @Override  
    public void accept(ComputerPartVisitor computerPartVisitor) {  
        computerPartVisitor.visit(this);  
    }  
}
package behavior.visitor;  
  
/**  
 * 键盘  
 */  
public class Keyboard implements ComputerPart{  
    @Override  
    public void accept(ComputerPartVisitor computerPartVisitor) {  
        computerPartVisitor.visit(this);  
    }  
}
package behavior.visitor;  
  
/**  
 * 显示器  
 */  
public class Monitor implements ComputerPart{  
    @Override  
    public void accept(ComputerPartVisitor computerPartVisitor) {  
        computerPartVisitor.visit(this);  
    }  
}
package behavior.visitor;  
  
/**  
 * 主机  
 */  
public class Computer implements ComputerPart {  
    private ComputerPart[] parts = new ComputerPart[]{new Mouse(), new Keyboard(), new Monitor()};  
  
    @Override  
    public void accept(ComputerPartVisitor computerPartVisitor) {  
        for (ComputerPart part : parts) {  
            part.accept(computerPartVisitor);  
        }  
        computerPartVisitor.visit(this);  
    }  
}
package behavior.visitor;  
  
public class ComputerDisplayVisitor implements ComputerPartVisitor{  
    @Override  
    public void visit(Keyboard keyboard) {  
        System.out.println("组装键盘:" + keyboard);  
    }  
  
    @Override  
    public void visit(Mouse mouse) {  
        System.out.println("组装鼠标:" + mouse);  
    }  
  
    @Override  
    public void visit(Monitor monitor) {  
        System.out.println("组装显示器:" + monitor);  
    }  
  
    @Override  
    public void visit(Computer computer) {  
        System.out.println("电脑组装完成:" + computer);  
    }  
}
package behavior.visitor;  
  
public class Test {  
    public static void main(String[] args) {  
        ComputerPart computer = new Computer();  
        computer.accept(new ComputerDisplayVisitor());  
    }  
}

image.png

状态模式

  • 在状态模式中,类的行为是基于它的状态改变的
  • 允许对象在内部状态发生改变时改变它的行为,看起来好像修改了它的类
  • 对象的行为依赖于它的状态(属性),并且可以根据它状态的改变而改变相关的行为
package behavior.state;  
  
public interface State {  
    public void operator(Context context);  
}
package behavior.state;  
  
public class Context {  
    private State state;  
  
    public Context() {  
        this.state = null;  
    }  
  
    public State getState() {  
        return state;  
    }  
  
    public void setState(State state) {  
        this.state = state;  
    }  
}
package behavior.state;  
  
public class StartState implements State{  
    @Override  
    public void operator(Context context) {  
        System.out.println("当前操作已开始...");  
        context.setState(this);  
    }  
  
    public String toString() {  
        return "当前操作正在进行中...";  
    }  
}
package behavior.state;  
  
public class EndState implements State{  
    @Override  
    public void operator(Context context) {  
        System.out.println("当前操作已结束...");  
        context.setState(this);  
    }  
  
    public String toString() {  
        return "当前操作正在结束中...";  
    }  
}
package behavior.state;  
  
public class Test {  
    public static void main(String[] args) {  
        Context context = new Context();  
        State start = new StartState();  
        start.operator(context);  
        System.out.println(context.getState().toString());  
        State end = new EndState();  
        end.operator(context);  
        System.out.println(context.getState().toString());  
    }  
}

image.png

  • 31
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java设计模式是一套对代码设计经验的总结,被人们反复利用,并且很多人都熟知的代码设计方式。其中,单例模式是一种常用的设计模式。在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在。这种模式有几个好处,比如可以节约系统资源,提高程序效率,以及提供一个全局访问点等。在实现单例模式时,可以采用饿汉式单例模式,即在类加载时创建一个对象,并通过私有构造器和静态方法来保证对象的唯一性。另外,工厂方法模式也是Java中常用的设计模式之一。在工厂方法模式中,可以定义一个工厂类,该类负责创建对象的实例,并将其封装在一个工厂方法中。通过这种方式,可以实现对象的创建与使用的分离,提高代码的灵活性和可维护性。总的来说,Java设计模式是一种用于解决特定问题的通用解决方案,可以提高代码的重用性、可读性和可扩展性。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [Java常用设计模式](https://blog.csdn.net/qq_33327680/article/details/123815614)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [JAVA中23种设计模式](https://blog.csdn.net/qw_0214/article/details/78878531)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值