关于设计模式:手把手教你23种设计模式

62次阅读

共计 44194 个字符,预计需要花费 111 分钟才能阅读完成。

相干常识

简略工厂模式(不属于 GoF 23 种设计模式)

工厂办法模式

形象工厂模式

单例模式

原型模式

建造者模式

代理模式

门面模式(外观模式)

装璜器模式

享元模式

组合模式(整体 - 局部模式)【通明式】【平安式】

适配器模式【类适配器】【对象适配器】

桥接模式

模板办法模式

策略模式

责任链模式(职责链模式)

迭代器模式

命令模式

状态模式

备忘录模式(快照模式)

中介者模式(调解模式)

解释器模式

访问者模式

观察者模式

委派模式(不属于 GoF 23 种设计模式)


学习设计模式前,强烈建议先学习软件设计七大准则(https://blog.csdn.net/samllwi…)

相干常识

《设计模式:可复用面向对象软件的根底》(Design Patterns: Elements of Reusable Object-Oriented Software)一书有 4 位作者,这 4 位作者在软件开发畛域里也以他们的“四人组”(Gang of Four,GoF)匿名著称。

23 种设计模式依照目标分类:创立型模式、结构型模式和行为型模式

23 种设计模式依照作用范畴分类:类模式和对象型模式

设计模式分类如下表:

范畴 \ 目标 创立型模式 结构型模式 行为型模式
类模式 工厂办法(Factory Method)模式 (类)适配器(Adapter)模式 模板办法(TemplateMethod)模式
解释器(Interpreter)模式
对象模式 单例(Singleton)模式
原型(Prototype)模式
形象工厂(AbstractFactory)模式
建造者(Builder)模式
代理(Proxy)模式
(对象)适配器(Adapter)模式
桥接(Bridge)模式
装璜(Decorator)模式
外观(Facade)模式
享元(Flyweight)模式
组合(Composite)模式
策略(Strategy)模式
命令(Command)模式
职责链(Chain of Responsibility)模式
状态(State)模式
观察者(Observer)模式
中介者(Mediator)模式
迭代器(Iterator)模式
访问者(Visitor)模式
备忘录(Memento)模式

把设计模式英文也写上的起因是到时候看源码后缀,能够看出应用了什么设计模式

简略工厂模式(不属于 GoF 23 种设计模式)

含意:简单对象不禁用户间接创立,用工厂类进行创立

示例:

小米能够生产手机和电脑,都由工厂产生

public interface IProduct {void show();
}

public class MiComputer implements IProduct {public void show() {System.out.println("小米电脑");
    }
}

public class MiPhone implements IProduct {public void show() {System.out.println("小米手机");
    }
}

public class MiFactory {public static IProduct create(String type){if ("phone".equals(type)){return new MiPhone();
        }else if ("computer".equals(type)){return new MiComputer();
        }else {return null;}
    }
}

public class TestMain {public static void main(String[] args) {IProduct miPhone = MiFactory.create("phone");
        miPhone.show();
        IProduct miComputer= MiFactory.create("computer");
        miComputer.show();}
}

类图:

工厂办法模式

含意:”工厂办法模式“是对简略工厂模式的进一步抽象化,其益处是能够使零碎在不批改原来代码的状况下引进新的产品,即满足开闭准则。

示例:

小米手机工厂生产手机,小米电脑工厂生产电脑

public interface IProduct {void show();
}

public class MiComputer implements IProduct {public void show() {System.out.println("小米电脑");
    }
}

public class MiPhone implements IProduct {public void show() {System.out.println("小米手机");
    }
}

public interface IFactory {IProduct create();
}

public class MiComputerFactory implements IFactory {public IProduct create() {return new MiComputer();
    }
}

public class MiPhoneFactory implements IFactory  {public IProduct create(){return new MiPhone();
    }
}

public class TestMain {public static void main(String[] args) {IProduct miPhone = new MiPhoneFactory().create();
        miPhone.show();
        IProduct miComputer = new MiComputerFactory().create();
        miComputer.show();}
}

类图:

形象工厂模式

含意:是一种为拜访类提供一个创立一组相干或相互依赖对象的接口,且拜访类毋庸指定所要产品的具体类就能失去同族的不同等级的产品的模式构造。一个工厂能够同时生产多种商品

示例:

小米工厂能够生产手机和电脑;华为工厂也能够生产手机和电脑

public interface IProduct {void show();
}

public class HuaWeiComputer implements IProduct {public void show() {System.out.println("华为电脑");
    }
}

public class HuaWeiPhone implements IProduct {public void show() {System.out.println("华为手机");
    }
}

public class MiComputer implements IProduct {public void show() {System.out.println("小米电脑");
    }
}

public class MiPhone implements IProduct {public void show() {System.out.println("小米手机");
    }
}

public interface IFactory {IProduct createPhone();
    IProduct createComputer();}

public class HuaWeiFactory implements IFactory {public IProduct createPhone() {return new HuaWeiPhone();
    }
    public IProduct createComputer() {return new HuaWeiComputer();
    }
}

public class MiFactory implements IFactory {public IProduct createPhone() {return new MiPhone();
    }
    public IProduct createComputer() {return new MiComputer();
    }
}

public class TestMain {public static void main(String[] args) {MiFactory miFactory = new MiFactory();
        IProduct miPhone = miFactory.createPhone();
        IProduct miComputer = miFactory.createComputer();
        miPhone.show();
        miComputer.show();
        HuaWeiFactory huaWeiFactory = new HuaWeiFactory();
        IProduct huaweiPhone = huaWeiFactory.createPhone();
        IProduct huaweiComputer = huaWeiFactory.createComputer();
        huaweiPhone.show();
        huaweiComputer.show();}
}

类图:

单例模式

含意:指一个类只有一个实例,且该类能自行创立这个实例的一种模式

单例模式技能要求:idea 下要会多线程调试,管制每个线程的执行程序

饿汉式

含意:类加载时进行实例化,没有线程平安问题。未应用的类也会占用内存空间

示例:【举荐】

public class HungrySingleton {private final static HungrySingleton INSTANCE = new HungrySingleton();

    private HungrySingleton() {}

    public static HungrySingleton getInstance() {return INSTANCE;}
}

懒汉式

含意:类加载时不会进行实例化,未应用的类不会占用内存空间

示例:

写法 1:该写法会有线程平安问题,多个申请会同时进入”if (instance == null)“,并发时会产生多个示例,这也是要理解 idea 多线程调试。

public class LazySingleton1 {
    private  static LazySingleton1 instance;

    private LazySingleton1() {}

    public static LazySingleton1 getInstance() {if (instance == null) {instance = new LazySingleton1();
        }
        return instance;
    }
}

写法 2:加锁,不会有线程平安问题,但会影响效率,每个申请都得进行排队

public class LazySingleton2 {
    private  static LazySingleton2 instance;

    private LazySingleton2() {}

    public static synchronized LazySingleton2 getInstance() {if (instance == null) {instance = new LazySingleton2();
        }
        return instance;
    }
}

写法 3:将锁移到外部,能够提高效率,然而还有线程平安问题

public class LazySingleton3 {
    private  static LazySingleton3 instance;

    private LazySingleton3() {}

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

写法 4:双重查看锁,不仅提高效率,也防止了线程平安问题【举荐】

public class LazySingleton4 {
    private static volatile LazySingleton4 instance;

    private LazySingleton4() {}

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

动态外部类形式

含意:动态外部类在加载时不会进行实例化,调用 getInstance()时才会进行实例化。不会占用内存,也不会有线程平安问题【举荐】

示例:

public class StaticInnerSingleton {private StaticInnerSingleton() { }

    public static StaticInnerSingleton getInstance() {return InnerSingletonHolder.INSTANCE;}

    private static class InnerSingletonHolder {private static final StaticInnerSingleton INSTANCE = new StaticInnerSingleton();
    }
}

枚举形式

含意:不论何种单例模式,会有反射创立新实例的状况,但枚举对象有校验不能通过构造方法创立实例【举荐】

示例:

动态外部类通过反射会创立新实例

public class TestMain {public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {StaticInnerSingleton instance = StaticInnerSingleton.getInstance();
        System.out.println(instance);
        Class<StaticInnerSingleton> clazz = StaticInnerSingleton.class;
        Constructor<StaticInnerSingleton> constructor = clazz.getDeclaredConstructor();
        constructor.setAccessible(true);
        StaticInnerSingleton staticInnerSingleton = constructor.newInstance();
        System.out.println(staticInnerSingleton);
    }
}

后果:

枚举单例

public enum EnumSingleton {
    INSTANCE;

    public static EnumSingleton getInstance() {return INSTANCE;}
}

public class TestMain {public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {EnumSingleton instance = EnumSingleton.getInstance();
        System.out.println(instance);
        Constructor<EnumSingleton> declaredConstructor = EnumSingleton.class.getDeclaredConstructor(String.class, int.class);
        declaredConstructor.setAccessible(true);
        EnumSingleton enumSingleton = declaredConstructor.newInstance();
        System.out.println(enumSingleton);
    }
}

后果:

容器形式

含意:应用时才去创立实例,不会节约内存,无线程平安问题

示例:

public class ContainerSingleton {private ContainerSingleton() { }

    private static Map<String, Object> container = new HashMap<>();

    public static Object getInstance(String className) {if (container.get(className) == null) {synchronized (ContainerSingleton.class) {if (container.get(className) == null) {
                    Object instance = null;
                    try {instance = Class.forName(className).newInstance();} catch (InstantiationException e) {e.printStackTrace();
                    } catch (IllegalAccessException e) {e.printStackTrace();
                    } catch (ClassNotFoundException e) {e.printStackTrace();
                    }
                    container.put(className, instance);
                }
            }
        }
        return container.get(className);
    }
}

序列化形式

含意:将实例存储为文件后,从新从文件读取会从新创立一个对象,蕴含”readResolve“办法读取时就不会从新创建对象

示例:

未增加”readResolve“办法时

public class SerializeSingleton implements Serializable {private final static SerializeSingleton INSTANCE = new SerializeSingleton();

    private SerializeSingleton() {}

    public static SerializeSingleton getInstance() {return INSTANCE;}
}

public class TestMain {public static void main(String[] args) throws IOException, ClassNotFoundException {SerializeSingleton instance = SerializeSingleton.getInstance();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("SerializeSingleton.obj"));
        objectOutputStream.writeObject(instance);
        objectOutputStream.flush();
        objectOutputStream.close();
        ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("SerializeSingleton.obj"));
        Object o = objectInputStream.readObject();
        objectInputStream.close();
        System.out.println(instance == o);
    }
}

后果:

增加”readResolve“办法时

public class SerializeSingleton implements Serializable {private final static SerializeSingleton INSTANCE = new SerializeSingleton();

    private SerializeSingleton() {}

    public static SerializeSingleton getInstance() {return INSTANCE;}

    private Object readResolve(){return INSTANCE;}
}

后果:

原型模式

含意:用一个曾经创立的实例作为原型,通过复制该原型对象来创立一个和原型雷同或类似的新对象。

原型模式的克隆分为浅克隆和深克隆。

浅克隆:创立一个新对象,新对象的属性和原来对象完全相同,对于非根本类型属性,仍指向原有属性所指向的对象的内存地址。

深克隆:创立一个新对象,属性中援用的其余对象也会被克隆,不再指向原有对象地址。

示例:

每个人都有手机,克隆人的时候手机是独立的,不会去援用同一个手机

public class Phone implements Serializable {
}

@Data
public class PerSonPrototype implements Serializable {
    private String name;
    private Integer age;
    private Phone phone;

    /**
     * 深克隆
     * @return
     */
    public PerSonPrototype deepClone(){
        try {ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream outputStream = new ObjectOutputStream(bos);
            outputStream.writeObject(this);
            ObjectInputStream inputStream = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
            Object o = inputStream.readObject();
            return (PerSonPrototype) o;
        } catch (Exception e) {e.printStackTrace();
        }
        return null;
    }

    /**
     * 浅克隆
     * @return
     */
    public PerSonPrototype shallowClone(){PerSonPrototype perSonPrototype = new PerSonPrototype();
        perSonPrototype.setName(this.getName());
        perSonPrototype.setAge(this.getAge());
        perSonPrototype.setPhone(this.getPhone());
        return perSonPrototype;
    }
}

public class TestMain {public static void main(String[] args) {PerSonPrototype perSonPrototype = new PerSonPrototype();
        perSonPrototype.setName("zhang");
        perSonPrototype.setAge(10);
        perSonPrototype.setPhone(new Phone());
        PerSonPrototype deepCloneObj = perSonPrototype.deepClone();
        PerSonPrototype shallowCloneObj = perSonPrototype.shallowClone();
        System.out.println(perSonPrototype.getPhone() == deepCloneObj.getPhone());
        System.out.println(perSonPrototype.getPhone() == shallowCloneObj.getPhone());
    }
}

后果:

类图:

建造者模式

含意:将一个简单对象的结构与它的示意拆散,使同样的构建过程能够创立不同的示意

mybatis-plus 中能够通过 lambada 表达式构建查问语句,就是应用了建造者模式

示例:

汽车工厂通过工程师来组装汽车

/**
 * 汽车
 *
 * @author lipangpang
 * @date 2021/12/13
 * @description
 */
@Data
public class Car {
    /**
     * 轮胎
     */
    private String tyre;
    /**
     * 发动机
     */
    private String engine;
    /**
     * 色彩
     */
    private String color;

}

/**
 * 工程师
 *
 * @author lipangpang
 * @date 2021/12/13
 * @description
 */
public abstract class IBuilder {protected Car car = new Car();

    public abstract void buildTyre();

    public abstract void buildEngine();

    public abstract void buildColor();

    public Car getCar() {return car;}
}

/**
 * @author lipangpang
 * @date 2021/12/13
 * @description
 */
public class Builder extends IBuilder {

    @Override
    public void buildTyre() {car.setTyre("玛吉斯轮胎");
    }

    @Override
    public void buildEngine() {car.setEngine("蓝鲸发动机");
    }

    @Override
    public void buildColor() {car.setColor("红色");
    }
}

/**
 * 汽车工厂
 *
 * @author lipangpang
 * @date 2021/12/13
 * @description
 */
public class CarFactory {
    private IBuilder builder;

    public CarFactory(IBuilder builder) {this.builder = builder;}

    public Car build(){builder.buildTyre();
        builder.buildEngine();
        builder.buildColor();
        return builder.getCar();}
}

public class TestMain {public static void main(String[] args) {CarFactory carFactory = new CarFactory(new Builder());
        Car car = carFactory.build();
        System.out.println(car);
    }
}

类图:

代理模式

含意:因为某些起因须要给某对象提供一个代理以管制对该对象的拜访。这时,拜访对象不适宜或者不能间接援用指标对象,代理对象作

为拜访对象和指标对象之间的中介。

依据代理的创立期间,代理模式分为动态代理和动静代理。

动态:由程序员创立代理类或特定工具主动生成源代码再对其编译,在程序运行前代理类的 .class 文件就曾经存在了。

动静:在程序运行时,使用反射机制动态创建而成

示例:

动态代理

人通过中介购买房子,中介先列出房子相干信息,人购买房子,中介收取中介费

public interface IPerson {void buy();
}

public class Person implements IPerson {
    @Override
    public void buy() {System.out.println("顾客买房子");
    }
}

public class Proxy implements IPerson{

    private IPerson person;

    public Proxy(IPerson person) {this.person = person;}

    @Override
    public void buy() {before();
        person.buy();
        after();}

    public void before(){System.out.println("列出房子相干信息");
    }

    public void after(){System.out.println("交易胜利,收取中介费");
    }
}

public class TestMain {public static void main(String[] args) {IPerson person = new Person();
        Proxy proxy = new Proxy(person);
        proxy.buy();}
}

类图:

实例:

动静代理实现

public interface IPerson {void buy();
}

public class Person implements IPerson {
    @Override
    public void buy() {System.out.println("顾客买房子");
    }
}

public class ProxyInvocationHandler implements InvocationHandler {
    private Object target;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("列出房子相干信息");
        Object result = method.invoke(target, args);
        System.out.println("交易胜利,收取中介费");
        return result;
    }
}

public class TestMain {public static void main(String[] args) {IPerson person = new Person();
        ProxyInvocationHandler handler = new ProxyInvocationHandler(person);
        IPerson proxyInstance = (IPerson) Proxy.newProxyInstance(person.getClass().getClassLoader(),                  person.getClass().getInterfaces(), handler);
        proxyInstance.buy();}
}

类图:

门面模式(外观模式)

含意:门面模式也叫外观模式,通过为多个简单的子系统提供一个统一的接口,而使这些子系统更加容易被拜访的模式。

门店模式是一种动态的代理模式。

示例:

用户再商城购买商品,会在订单零碎先创立订单,而后库存零碎扣减库存,再从物流零碎发货

public class OrderSystem {public void createOrder(){System.out.println("订单零碎先创立订单");
    }
}

public class StockSystem {public void decreaseStock(){System.out.println("库存零碎扣减库存");
    }
}

public class LogisticsSystem {public void addSalesVolume(){System.out.println("物流零碎发货");
    }
}

public class MallFacade {private OrderSystem orderSystem = new OrderSystem();
    private StockSystem stockSystem = new StockSystem();
    private LogisticsSystem logisticsSystem = new LogisticsSystem();

    public void buyGoods(){orderSystem.createOrder();;
        stockSystem.decreaseStock();
        logisticsSystem.addSalesVolume();}
}

public class TestMain {public static void main(String[] args) {MallFacade mallFacade = new MallFacade();
        mallFacade.buyGoods();}
}

类图:

装璜器模式

含意:在不扭转现有对象构造的状况下,动静地给该对象减少一些职责(即减少其额定性能)的模式。

java 中流的封装是一种装璜器模式的实现,如下

BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(""));

示例:

水果蛋糕,在纯蛋糕的根底上能够减少芒果、草莓和樱桃等。

/**
 * 蛋糕接口
 * @author lipangpang
 * @date 2021/12/15
 * @description
 */
public interface ICake {String getInfo();
}

/**
 * 纯蛋糕
 * @author lipangpang
 * @date 2021/12/15
 * @description
 */
public class BaseCake implements ICake {
    @Override
    public String getInfo() {return "纯蛋糕";}
}

/**
 * 水果装璜器
 * @author lipangpang
 * @date 2021/12/15
 * @description
 */
public class FruitDecorator implements ICake {
    private ICake iCake;

    public FruitDecorator(ICake iCake) {this.iCake = iCake;}

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

/**
 * 芒果装璜器
 * @author lipangpang
 * @date 2021/12/15
 * @description
 */
public class MangoDecorator extends FruitDecorator {public MangoDecorator(ICake iCake) {super(iCake);
    }

    @Override
    public String getInfo() {return super.getInfo() + "+ 芒果";
    }
}

/**
 * 草莓装璜器
 *
 * @author lipangpang
 * @date 2021/12/15
 * @description
 */
public class StrawberryDecorator extends FruitDecorator {public StrawberryDecorator(ICake iCake) {super(iCake);
    }

    @Override
    public String getInfo() {return super.getInfo() + "+ 草莓";
    }
}

/**
 * 樱桃装璜器
 * @author lipangpang
 * @date 2021/12/15
 * @description
 */
public class CherryDecorator extends FruitDecorator {public CherryDecorator(ICake iCake) {super(iCake);
    }

    @Override
    public String getInfo() {return super.getInfo() + "+ 樱桃";
    }
}

public class TestMain {public static void main(String[] args)  {ICake baseCake = new BaseCake();
        System.out.println(baseCake.getInfo());
        MangoDecorator mangoDecorator = new MangoDecorator(baseCake);
        System.out.println(mangoDecorator.getInfo());
        StrawberryDecorator strawberryDecorator = new StrawberryDecorator(mangoDecorator);
        System.out.println(strawberryDecorator.getInfo());
        CherryDecorator cherryDecorator = new CherryDecorator(strawberryDecorator);
        System.out.println(cherryDecorator.getInfo());
    }
}

后果:

类图:

享元模式

含意:使用共享技术来无效地反对大量细粒度对象的复用。它通过共享曾经存在的对象来大幅度缩小须要创立的对象数量、防止大量类似

类的开销,从而进步系统资源的利用率。

享元模式蕴含的对象有两种状态:外部状态和内部状态;

外部状态指对象共享进去的信息,存储在享元信息外部,并且不回随环境的扭转而扭转;

内部状态指对象得以依赖的一个标记,随环境的扭转而扭转,不可共享。

示例:

火车站当初都有投放按摩椅,椅子是固定的,去生产的人不是固定的

/**
 * 游客
 *
 * @author lipangpang
 * @date 2021/12/16
 * @description
 */
public class Person {
    /**
     * 游客姓名
     */
    private String name;


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

    public String buyService() {return name + "花钱购买了";}
}

/**
 * 按摩椅接口
 *
 * @author lipangpang
 * @date 2021/12/16
 * @description
 */
public interface IChair {
    /**
     * 获取按摩椅信息
     *
     * @return
     */
    String getInfo(Person person);
}

/**
 * 按摩椅
 *
 * @author lipangpang
 * @date 2021/12/16
 * @description
 */
public class Chair implements IChair {

    /**
     * 编号
     */
    private String chairNo;

    public Chair(String chairNo) {this.chairNo = chairNo;}

    @Override
    public String getInfo(Person person) {return person.buyService() + "按摩椅" + chairNo + "的服务";
    }
}

/**
 * 按摩椅工厂
 *
 * @author lipangpang
 * @date 2021/12/16
 * @description
 */
public class ChairFactory {private Map<String, IChair> chairNo2Chair = new HashMap<>();

    public ChairFactory() {for (int i = 1; i <= 5; i++) {
            String chairNo = "A00" + i;
            chairNo2Chair.put(chairNo, new Chair(chairNo));
        }
    }

    public IChair getChair(String chairNo) {return chairNo2Chair.get(chairNo);
    }
}

public class TestMain {public static void main(String[] args) {ChairFactory chairFactory = new ChairFactory();
        IChair chair1 = chairFactory.getChair("A001");
        IChair chair11 = chairFactory.getChair("A001");
        IChair chair2 = chairFactory.getChair("A002");
        System.out.println(chair1.getInfo(new Person("zhang")));
        System.out.println(chair11.getInfo(new Person("li")));
        System.out.println(chair2.getInfo(new Person("wang")));
    }
}

类图:

组合模式(整体 - 局部模式)

含意:又叫作整体 - 局部(Part-Whole)模式,它是一种将对象组合成树状的层次结构的模式,用来示意“整体 - 局部”的关系,使用户

对单个对象和组合对象具备统一的拜访性。将对象组合到树形构造中,有根节点、树枝节点和叶子节点,树形结构图如下。

组合模式分为通明式的组合模式和平安式的组合模式。

通明式:

示例:文件系统,蕴含文件和文件夹。文件和文件都继承同一个形象接口,形象接口蕴含所有办法。

/**
 * 平安模式 - 文件系统 - 目录
 *
 * @author lipangpang
 * @date 2021/12/18
 * @description
 */
public abstract class Directory {
    protected String name;

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

    public void add(Directory directory) {throw new UnsupportedOperationException("不反对减少操作");
    }

    public void remove(Directory directory) {throw new UnsupportedOperationException("不反对移出操作");
    }

    public abstract void print();}

/**
 * 平安模式 - 文件系统 - 文件
 *
 * @author lipangpang
 * @date 2021/12/18
 * @description
 */
public class File extends Directory {public File(String name) {super(name);
    }

    @Override
    public void print() {System.out.println("文件" + this.name);
    }
}

/**
 * 平安模式 - 文件系统 - 文件夹
 *
 * @author lipangpang
 * @date 2021/12/18
 * @description
 */
public class Folder extends Directory {private List<Directory> items = new ArrayList<>();

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

    @Override
    public void print() {System.out.println("文件夹" + this.name + "==>");
        for (Directory item : items) {item.print();
        }
    }

    @Override
    public void add(Directory directory) {items.add(directory);
    }

    @Override
    public void remove(Directory directory) {items.remove(directory);
    }
}

public class TestMain {public static void main(String[] args) {Directory root = new Folder("C 盘");
        File idea = new File("idea 开发工具");
        root.add(idea);
        Directory musicTool = new Folder("音乐工具文件夹");
        File kugouMusic = new File("酷狗音乐软件");
        File qqMusic = new File("QQ 音乐软件");
        musicTool.add(kugouMusic);
        musicTool.add(qqMusic);
        root.add(musicTool);
        root.print();}
}

后果:

类图:

平安式:

示例:文件系统,蕴含文件和文件夹。文件和文件都继承同一个形象接口,形象接口只蕴含公共办法。

/**
 * 平安模式 - 文件系统 - 目录
 *
 * @author lipangpang
 * @date 2021/12/18
 * @description
 */
public abstract class Directory {
    protected String name;

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


    public abstract void print();}

/**
 * 平安模式 - 文件系统 - 文件
 *
 * @author lipangpang
 * @date 2021/12/18
 * @description
 */
public class File extends Directory {public File(String name) {super(name);
    }

    @Override
    public void print() {System.out.println("===> 文件" + this.name);
    }
}

/**
 * 平安模式 - 文件系统 - 文件夹
 *
 * @author lipangpang
 * @date 2021/12/18
 * @description
 */
public class Folder extends Directory {private List<Directory> items = new ArrayList<>();

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


    @Override
    public void print() {System.out.println("文件夹" + this.name);
        for (Directory item : items) {item.print();
        }
    }

    public void add(Directory directory) {items.add(directory);
    }

    public void remove(Directory directory) {items.remove(directory);
    }
}

public class TestMain {public static void main(String[] args) {Folder root = new Folder("C 盘");
        File idea = new File("idea 开发工具");
        root.add(idea);
        Folder musicTool = new Folder("音乐工具文件夹");
        File kugouMusic = new File("酷狗音乐软件");
        File qqMusic = new File("QQ 音乐软件");
        musicTool.add(kugouMusic);
        musicTool.add(qqMusic);
        root.add(musicTool);
        root.print();}
}

后果:

类图:

适配器模式

含意:将一个类的接口转换成客户心愿的另外一个接口,使得本来因为接口不兼容而不能一起工作的那些类能一起工作。适配器模式分为类结构型模式和对象结构型模式两种,前者类之间的耦合度比后者高,且要求程序员理解现有组件库中的相干组件的内部结构,所以利用绝对较少些。

适配器模式(Adapter)蕴含以下次要角色。

  1. 指标(Target)接口:以后零碎业务所期待的接口,它能够是抽象类或接口。
  2. 适配者(Adaptee)类:它是被拜访和适配的现存组件库中的组件接口。
  3. 适配器(Adapter)类:它是一个转换器,通过继承或援用适配者的对象,把适配者接口转换成指标接口,让客户按指标接口的格局

    拜访适配者。

类适配器:

示例:

电源适配器,能够将 220v 交流电转换成 5v 或者 10v 的直流电

/**
 * 直流电指标
 *
 * @author lipangpang
 * @date 2021/12/18
 * @description
 */
public interface IDirectTarget {
    /**
     * 获取 5v 直流电
     *
     * @return
     */
    int getDirect5v();

    /**
     * 获取 10v 直流电
     *
     * @return
     */
    int getDirect10v();}

/**
 * 交流电 220v 适配者
 *
 * @author lipangpang
 * @date 2021/12/18
 * @description
 */
public class AC220Adaptee {

    /**
     * 获取 220v 交流电
     *
     * @return
     */
    public int getAC220v() {return 220;}
}

/**
 * 电源适配器
 *
 * @author lipangpang
 * @date 2021/12/18
 * @description
 */
public class PowerAdapter extends AC220Adaptee implements IDirectTarget {
    @Override
    public int getDirect5v() {return getAC220v() / 44;
    }

    @Override
    public int getDirect10v() {return getAC220v() / 22;
    }
}

public class TestMain {public static void main(String[] args) {PowerAdapter powerAdapter = new PowerAdapter();
        System.out.println(powerAdapter.getDirect5v());
        System.out.println(powerAdapter.getDirect10v());
    }
}

类图:

对象适配器:

示例:

电源适配器,能够将 220v 交流电转换成 5v 或者 10v 的直流电

/**
 * 直流电指标
 *
 * @author lipangpang
 * @date 2021/12/18
 * @description
 */
public interface IDirectTarget {
    /**
     * 获取 5v 直流电
     *
     * @return
     */
    int getDirect5v();

    /**
     * 获取 10v 直流电
     *
     * @return
     */
    int getDirect10v();}

/**
 * 交流电 220v 适配者
 *
 * @author lipangpang
 * @date 2021/12/18
 * @description
 */
public class AC220Adaptee {

    /**
     * 获取 220v 交流电
     *
     * @return
     */
    public int getAC220v() {return 220;}
}

/**
 * 电源适配器
 *
 * @author lipangpang
 * @date 2021/12/18
 * @description
 */
public class PowerAdapter implements IDirectTarget {

    private AC220Adaptee ac220Adaptee;

    public PowerAdapter(AC220Adaptee ac220Adaptee) {this.ac220Adaptee = ac220Adaptee;}

    @Override
    public int getDirect5v() {return ac220Adaptee.getAC220v() / 44;
    }

    @Override
    public int getDirect10v() {return ac220Adaptee.getAC220v() / 22;
    }
}

public class TestMain {public static void main(String[] args) {PowerAdapter powerAdapter = new PowerAdapter(new AC220Adaptee());
        System.out.println(powerAdapter.getDirect5v());
        System.out.println(powerAdapter.getDirect10v());
    }
}

类图:

桥接模式

含意:将形象与实现拆散,使它们能够独立变动。它是用组合关系代替继承关系来实现,从而升高了形象和实现这两个可变维度的耦合

度。

桥接(Bridge)模式蕴含以下次要角色。

  1. 抽象化(Abstraction)角色:定义抽象类,并蕴含一个对实现化对象的援用。
  2. 扩大抽象化(Refined Abstraction)角色:是抽象化角色的子类,实现父类中的业务办法,并通过组合关系调用实现化角色中的业务

    办法。

  3. 实现化(Implementor)角色:定义实现化角色的接口,供扩大抽象化角色调用。
  4. 具体实现化(Concrete Implementor)角色:给出实现化角色接口的具体实现。

示例:

汽车有红色和红色,摩托车有红色和红色,当要其中一种对象时,不会创立四种对象类,而是通过组合的形式,创立两种对象类。

/**
 * 色彩接口
 *
 * @author lipangpang
 * @date 2021/12/18
 * @description
 */
public interface IColor {String getColor();
}

public class Red implements IColor {
    @Override
    public String getColor() {return "红色";}
}

public class White implements IColor {
    @Override
    public String getColor() {return "红色";}
}

/**
 * 交通工具桥接类
 *
 * @author lipangpang
 * @date 2021/12/18
 * @description
 */
public abstract class IVehicle {
    protected IColor color;

    public IVehicle(IColor color) {this.color = color;}

    public abstract void printInfo();}

/**
 * 摩托车
 *
 * @author lipangpang
 * @date 2021/12/18
 * @description
 */
public class Motorcycle extends IVehicle {public Motorcycle(IColor color) {super(color);
    }

    @Override
    public void printInfo() {System.out.println("摩托" + color.getColor());
    }
}

/**
 * 汽车
 *
 * @author lipangpang
 * @date 2021/12/18
 * @description
 */
public class Car extends IVehicle {public Car(IColor color) {super(color);
    }

    @Override
    public void printInfo() {System.out.println("汽车" + color.getColor());
    }
}

public class TestMain {public static void main(String[] args) {Car car = new Car(new White());
        car.printInfo();
        car = new Car(new Red());
        car.printInfo();}
}

类图:

模板办法模式

含意:定义一个操作中的算法骨架,而将算法的一些步骤提早到子类中,使得子类能够不扭转该算法构造的状况下重定义该算法的某些特

定步骤。

模板办法模式蕴含以下角色。

  1. 形象模板

    1. 模板办法:定义了算法的骨架,按某种顺序调用其蕴含的根本办法。
    2. 根本办法:是整个算法中的一个步骤,蕴含以下几种类型。

      1. 形象办法:在抽象类中申明,由具体子类实现。
      2. 具体方法:在抽象类中曾经实现,在具体子类中能够继承或重写它。
      3. 钩子办法:在抽象类中曾经实现,包含用于判断的逻辑办法和须要子类重写的空办法两种。
  2. 具体实现

示例:

用户在手机上购买商品流程,先筛选商品,创立订单,领取,而后依据须要时上门自提还是骑手配送。

/**
 * 购物模板类
 *
 * @author lipangpang
 * @date 2021/12/18
 * @description
 */
public abstract class ShoppingTemplate {protected abstract String searchProduct();

    final String createOrder() {return "创立订单";}

    final String payOrder() {return "领取订单";}

    /**
     * 钩子办法,用于调整业务流程
     *
     * @return
     */
    protected abstract boolean isLogistics();

    final String selfMention() {return "到门店自提";}

    final String Logistics() {return "骑手配送上门";}

    public void shopping() {String result = searchProduct() + ">" + createOrder() + ">" + payOrder();
        if (isLogistics()) {result += ">" + Logistics();
        } else {result += ">" + selfMention();
        }
        System.out.println(result);
    }
}

/**
 * 消费者购物类
 *
 * @author lipangpang
 * @date 2021/12/18
 * @description
 */
public class CustomerShopping extends ShoppingTemplate {
    private String productName;
    private boolean isLogistics;

    public CustomerShopping(String productName, boolean isLogistics) {
        this.productName = productName;
        this.isLogistics = isLogistics;
    }

    @Override
    protected String searchProduct() {return this.productName;}

    @Override
    protected boolean isLogistics() {return this.isLogistics;}
}

public class TestMain {public static void main(String[] args) {System.out.println("顾客 1 订单信息 ===");
        CustomerShopping customerShopping1 = new CustomerShopping("苹果",true);
        customerShopping1.shopping();
        System.out.println("顾客 2 订单信息 ===");
        CustomerShopping customerShopping2 = new CustomerShopping("香蕉",false);
        customerShopping2.shopping();}
}

后果:

类图:

策略模式

含意:定义了一系列算法,并将每个算法封装起来,使它们能够互相替换,且算法的变动不会影响应用算法的客户。

策略模式构造如下。

  1. 形象策略类
  2. 具体策略类
  3. 环境类

示例:每个人都周末都有不同的安顿,比方健身、看电影和学习等。

/**
 * 流动形象策略类
 *
 * @author lipangpang
 * @date 2021/12/22
 * @description
 */
public interface IActivity {
    /**
     * 策略办法
     */
    void execute();}

public class BodyBuildingActivity implements IActivity {
    @Override
    public void execute() {System.out.println("周末健身");
    }
}

public class MovieActivity implements IActivity {
    @Override
    public void execute() {System.out.println("周末看电影");
    }
}

public class StudyActivity implements IActivity {
    @Override
    public void execute() {System.out.println("周末学习");
    }
}

public class TestMain {public static void main(String[] args) {StrategyContext strategyContext = new StrategyContext(new MovieActivity());
        strategyContext.executeStrategy();}
}

后果:

周末看电影

类图:

责任链模式(职责链模式)

含意:为了防止申请发送者与多个申请解决者耦合在一起,于是将所有申请的解决者通过前一对象记住其下一个对象的援用而连成一条

链;当有申请产生时,可将申请沿着这条链传递,直到有对象解决它为止。

责任链模式构造如下。

  1. 形象解决者
  2. 具体解决者
  3. 客户类

示例:去店铺买货色,导购员有打 9 折权限,储备店长有打 8 折权限,店长有打 7 折权限。

/**
 * 员工抽象类
 *
 * @author lipangpang
 * @date 2021/12/22
 * @description
 */
public abstract class Handler {
    /**
     * 下一执行人
     */
    private Handler next;

    public Handler getNext() {return next;}

    public void setNext(Handler next) {this.next = next;}

    /**
     * 解决申请办法
     *
     * @param discount
     */
    abstract void handlerDiscount(Integer discount);
}

/**
 * 导购员
 *
 * @author lipangpang
 * @date 2021/12/22
 * @description
 */
public class ShoppingGuide extends Handler {
    @Override
    void handlerDiscount(Integer discount) {if (discount >= 9) {System.out.println("导购员打 9 折");
        } else {if (this.getNext() == null) {System.out.println("导购员不能进行打" + discount + "折");
            } else {this.getNext().handlerDiscount(discount);
            }
        }
    }
}

/**
 * 储备店长
 *
 * @author lipangpang
 * @date 2021/12/22
 * @description
 */
public class ReserverManager extends Handler {
    @Override
    void handlerDiscount(Integer discount) {if (discount >= 8) {System.out.println("储备店长打 8 折");
        } else {if (this.getNext() == null) {System.out.println("储备店长不能进行打" + discount + "折");
            } else {this.getNext().handlerDiscount(discount);
            }
        }
    }
}

/**
 * 店长
 *
 * @author lipangpang
 * @date 2021/12/22
 * @description
 */
public class Manager extends Handler {
    @Override
    void handlerDiscount(Integer discount) {if (discount >= 7) {System.out.println("店长打 7 折");
        } else {if (this.getNext() == null) {System.out.println("店长不能进行打" + discount + "折");
            } else {this.getNext().handlerDiscount(discount);
            }
        }
    }
}

public class TestMain {public static void main(String[] args) {ShoppingGuide shoppingGuide = new ShoppingGuide();
        ReserverManager reserverManager = new ReserverManager();
        Manager manager = new Manager();
        shoppingGuide.setNext(reserverManager);
        reserverManager.setNext(manager);
        shoppingGuide.handlerDiscount(8);
    }
}

后果:

储备店长打 8 折

类图:

迭代器模式

含意:提供一个对象来程序拜访聚合对象中的一系列数据,而不裸露聚合对象的外部示意。

迭代器模式构造如下。

  1. 形象聚合角色:义存储、增加、删除聚合对象以及创立迭代器对象的接口。
  2. 具体聚合角色:实现形象聚合类,返回一个具体迭代器的实例。
  3. 形象迭代器角色:定义拜访和遍历聚合元素的接口,通常蕴含 hasNext()、first()、next() 等办法。
  4. 具体迭代器角色:实现形象迭代器接口中所定义的办法,实现对聚合对象的遍历,记录遍历的以后地位。

示例:实现相似 List 的性能,能够减少、删除元素,获取迭代器,遍历元素。

/**
 * 形象汇合接口
 * @author lipangpang
 * @date 2021/12/25
 * @description
 */
public interface MyList {
    /**
     * 减少元素
     *
     * @param o
     */
    void add(Object o);

    /**
     * 删除元素
     *
     * @param o
     */
    void remove(Object o);

    /**
     * 获取迭代器
     *
     * @return
     */
    Iterator iterator();}

/**
 * 形象聚合实现类
 * @author lipangpang
 * @date 2021/12/25
 * @description
 */
public class MyListImpl implements MyList {private List<Object> list = new ArrayList<>();
    @Override
    public void add(Object o) {list.add(o);
    }

    @Override
    public void remove(Object o) {list.remove(o);
    }

    @Override
    public Iterator iterator() {return new IteratorImpl(list);
    }
}

/**
 * 迭代器接口
 *
 * @author lipangpang
 * @date 2021/12/25
 * @description
 */
public interface Iterator {
    /**
     * 获取第一个元素
     *
     * @return
     */
    Object first();

    /**
     * 获取下一个元素
     *
     * @return
     */
    Object next();

    /**
     * 是否有下一个元素
     *
     * @return
     */
    boolean hasNext();}

/**
 * 迭代器实现类
 *
 * @author lipangpang
 * @date 2021/12/25
 * @description
 */
public class IteratorImpl implements Iterator {
    private List<Object> list;
    private Integer index = -1;

    public IteratorImpl(List<Object> list) {this.list = list;}

    @Override
    public Object first() {
        index = 0;
        if (list.size() == 0){throw new NoSuchElementException("没有元素");
        }
        return list.get(index);
    }

    @Override
    public Object next() {if (index == list.size()){throw new NoSuchElementException("没有元素");
        }
        return list.get(index);
    }

    @Override
    public boolean hasNext() {
        index++;
        return index < list.size();}
}

public class TestMain {public static void main(String[] args) {MyList myList = new MyListImpl();
        myList.add("a");
        myList.add("b");
        myList.add("c");
        Iterator iterator = myList.iterator();
        while (iterator.hasNext()){System.out.println(iterator.next());
        }
    }
}

后果:

a
b
c

类图:

命令模式

含意:将一个申请封装为一个对象,使发出请求的责任和执行申请的责任宰割开。这样两者之间通过命令对象进行沟通,这样不便将命令

对象进行贮存、传递、调用、减少与治理。

命令模式构造如下。

  1. 形象命令类(Command)角色:申明执行命令的接口,领有执行命令的形象办法 execute()。
  2. 具体命令类(Concrete Command)角色:是形象命令类的具体实现类,它领有接收者对象,并通过调用接收者的性能来实现命令要

    执行的操作。

  3. 实现者 / 接收者(Receiver)角色:执行命令性能的相干操作,是具体命令对象业务的真正实现者。
  4. 调用者 / 请求者(Invoker)角色:是申请的发送者,它通常领有很多的命令对象,并通过拜访命令对象来执行相干申请,它不间接访

    问接收者。

示例:每天早上家长叫孩子起床、刷牙

/**
 * 命令接口
 *
 * @author lipangpang
 * @date 2021/12/25
 * @description
 */
public interface ICommand {void execute();
}

/**
 * 起床命令
 *
 * @author lipangpang
 * @date 2021/12/25
 * @description
 */
public class GetUpCommand implements ICommand {
    private ChildrenReceiver childrenReceiver;

    public GetUpCommand(ChildrenReceiver childrenReceiver) {this.childrenReceiver = childrenReceiver;}

    @Override
    public void execute() {childrenReceiver.getUp();
    }
}

/**
 * 刷牙命令
 *
 * @author lipangpang
 * @date 2021/12/25
 * @description
 */
public class BrushTeethCommand implements ICommand {
    private ChildrenReceiver childrenReceiver;

    public BrushTeethCommand(ChildrenReceiver childrenReceiver) {this.childrenReceiver = childrenReceiver;}

    @Override
    public void execute() {childrenReceiver.brushTeeth();
    }
}

/**
 * 孩子接收者
 *
 * @author lipangpang
 * @date 2021/12/25
 * @description
 */
public class ChildrenReceiver {public void getUp() {System.out.println("起床");
    }

    public void brushTeeth() {System.out.println("刷牙");
    }
}

/**
 * 家长调用者
 *
 * @author lipangpang
 * @date 2021/12/25
 * @description
 */
public class ParentInvoker {
    private ICommand command;

    public ParentInvoker() {}

    public ICommand getCommand() {return command;}

    public void setCommand(ICommand command) {this.command = command;}

    public void call() {command.execute();
    }
}

public class TestMain {public static void main(String[] args) {ChildrenReceiver childrenReceiver = new ChildrenReceiver();
        GetUpCommand getUpCommand = new GetUpCommand(childrenReceiver);
        BrushTeethCommand brushTeethCommand = new BrushTeethCommand(childrenReceiver);
        ParentInvoker parentInvoker = new ParentInvoker();
        parentInvoker.setCommand(getUpCommand);
        parentInvoker.call();
        parentInvoker.setCommand(brushTeethCommand);
        parentInvoker.call();}
}

后果:

起床
刷牙

类图:

状态模式

含意:对有状态的对象,把简单的“判断逻辑”提取到不同的状态对象中,容许状态对象在其外部状态产生扭转时扭转其行为。

状态模式构造如下。

  1. 环境类(Context)角色:也称为上下文,它定义了客户端须要的接口,外部保护一个以后状态,并负责具体状态的切换。
  2. 形象状态(State)角色:定义一个接口,用以封装环境对象中的特定状态所对应的行为,能够有一个或多个行为。
  3. 具体状态(Concrete State)角色:实现形象状态所对应的行为,并且在须要的状况下进行状态切换。

示例:订单领取状态有待领取、已领取和已退款,待领取能力进行领取,已领取能力进行退款。

/**
 * 形象状态类
 *
 * @author lipangpang
 * @date 2021/12/26
 * @description
 */
public abstract class State {
    /**
     * 状态名称
     */
    protected String name;

    public String getName() {return name;}

    public void setName(String name) {this.name = name;}
}

/**
 * 待领取状态
 *
 * @author lipangpang
 * @date 2021/12/26
 * @description
 */
public class UnPayState extends State {public UnPayState() {
        this.name = "待领取状态";
        System.out.println("以后订单状态:" + this.name);
    }

    /**
     * 领取操作
     *
     * @param orderContext
     */
    public void pay(OrderContext orderContext) {orderContext.setState(new PayedState());
    }
}

/**
 * 已领取状态
 *
 * @author lipangpang
 * @date 2021/12/26
 * @description
 */
public class PayedState extends State {public PayedState() {
        this.name = "已领取状态";
        System.out.println("以后订单状态:" + this.name);
    }

    /**
     * 退款操作
     *
     * @param orderContext
     */
    public void refund(OrderContext orderContext) {orderContext.setState(new RefundedState());
    }
}

/**
 * 已退款状态
 *
 * @author lipangpang
 * @date 2021/12/26
 * @description
 */
public class RefundedState extends State {public RefundedState() {
        this.name = "已退款状态";
        System.out.println("以后订单状态:" + this.name);
    }
}

/**
 * 订单环境类
 *
 * @author lipangpang
 * @date 2021/12/26
 * @description
 */
public class OrderContext {
    private State state;

    public OrderContext() {this.state = new UnPayState();
    }

    public State getState() {return state;}

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

    /**
     * 领取操作
     */
    public void pay() {System.out.println("去领取");
        if ("待领取状态".equals(state.getName())){((UnPayState)state).pay(this);
        }else {System.out.println("待领取状态能力去领取");
        }
    }

    /**
     * 退款操作
     */
    public void refund() {System.out.println("去退款");
        if ("已领取状态".equals(state.getName())){((PayedState)state).refund(this);
        }else {System.out.println("已领取状态能力去退款");
        }
    }
}

public class TestMain {public static void main(String[] args) {OrderContext orderContext = new OrderContext();
        orderContext.pay();
        orderContext.refund();}
}

后果:

以后订单状态:待领取状态
去领取
以后订单状态:已领取状态
去退款
以后订单状态:已退款状态

类图:

备忘录模式(快照模式)

含意:在不毁坏封装性的前提下,捕捉一个对象的外部状态,并在该对象之外保留这个状态,以便当前当须要时能将该对象复原到原先保

存的状态。

备忘录模式构造如下。

  1. 发起人(Originator)角色:记录以后时刻的外部状态信息,提供创立备忘录和复原备忘录数据的性能,实现其余业务性能,它能够

    拜访备忘录里的所有信息。

  2. 备忘录(Memento)角色:负责存储发起人的外部状态,在须要的时候提供这些外部状态给发起人。
  3. 管理者(Caretaker)角色:对备忘录进行治理,提供保留与获取备忘录的性能,但其不能对备忘录的内容进行拜访与批改。

示例:用户在编辑文档的时候,每次保留都会存储一份以后数据的状态当做备忘录,按下撤销键能够返回上一个状态。

/**
 * 备忘录数据
 *
 * @author lipangpang
 * @date 2021/12/26
 * @description
 */
public class Memento {
    private String data;

    public String getData() {return data;}

    public void setData(String data) {this.data = data;}
}

/**
 * 备忘录管理者
 *
 * @author lipangpang
 * @date 2021/12/26
 * @description
 */
public class Caretaker {
    /**
     * 所有备忘录数据
     */
    private Stack<Memento> datas = new Stack<>();

    /**
     * 保留备忘录数据
     *
     * @return
     */
    public Memento getData() {return datas.pop();
    }

    /**
     * 获取备忘录数据
     *
     * @param memento
     * @return
     */
    public Memento saveData(Memento memento) {return datas.push(memento);
    }
}

/**
 * 编辑文档发起者
 *
 * @author lipangpang
 * @date 2021/12/26
 * @description
 */
public class EditOriginator {
    /**
     * 用户以后编辑的文本
     */
    private String text;

    public String getText() {return text;}

    public void setText(String text) {this.text = text;}

    /**
     * 创立备忘录数据
     */
    public Memento createMemento() {Memento memento = new Memento();
        memento.setData(text);
        return memento;
    }
}

public class TestMain {public static void main(String[] args) {EditOriginator editOriginator = new EditOriginator();
        Caretaker caretaker = new Caretaker();
        editOriginator.setText("第一次编辑数据");
        caretaker.saveData(editOriginator.createMemento());
        editOriginator.setText("第二次编辑数据");
        System.out.println("以后数据:" + editOriginator.getText());
        editOriginator.setText(caretaker.getData().getData());
        System.out.println("回滚后数据:" + editOriginator.getText());
    }
}

后果:

以后数据:第二次编辑数据
回滚后数据:第一次编辑数据

类图:

中介者模式(调解模式)

含意:定义一个中介对象来封装一系列对象之间的交互,使原有对象之间的耦合涣散,且能够独立地扭转它们之间的交互

中介者模式构造如下。

  1. 形象中介者(Mediator)角色:它是中介者的接口,提供了共事对象注册与转发共事对象信息的形象办法。
  2. 具体中介者(Concrete Mediator)角色:实现中介者接口,定义一个 List 来治理共事对象,协调各个共事角色之间的交互关系,因

    此它依赖于共事角色。

  3. 形象共事类(Colleague)角色:定义共事类的接口,保留中介者对象,提供共事对象交互的形象办法,实现所有相互影响的共事类

    的公共性能。

  4. 具体共事类(Concrete Colleague)角色:是形象共事类的实现者,当须要与其余共事对象交互时,由中介者对象负责后续的交互。

示例:群聊的时候,只有有一个人发消息,大众的所有人能够承受到音讯。

/**
 * 共事接口
 *
 * @author lipangpang
 * @date 2021/12/27
 * @description
 */
public abstract class IColleague {
    /**
     * 聊天室中介者
     */
    protected IGroupChatMediator groupChatMediator;
    /**
     * 共事姓名
     */
    private String name;
    /**
     * 共事发送的音讯
     */
    private String msg;

    public String getName() {return name;}

    public void setName(String name) {this.name = name;}

    public String getMsg() {return msg;}

    public void setMsg(String msg) {this.msg = msg;}

    public IColleague(IGroupChatMediator groupChatMediator, String name) {
        this.groupChatMediator = groupChatMediator;
        this.name = name;
    }

    /**
     * 发送音讯
     *
     * @param msg
     */
    abstract void sendMsg(String msg);

    /**
     * 承受音讯
     *
     * @param msg
     */
    abstract void receiveMsg(String msg);
}

/**
 * 共事
 *
 * @author lipangpang
 * @date 2021/12/27
 * @description
 */
public class Colleague extends IColleague {public Colleague(IGroupChatMediator groupChatMediator, String name) {super(groupChatMediator, name);
    }

    @Override
    void sendMsg(String msg) {this.setMsg(msg);
        groupChatMediator.distributeMsg(this);
    }

    @Override
    void receiveMsg(String msg) {System.out.println(this.getName() + "接管:" + msg);
    }
}

/**
 * 聊天室中介接口
 *
 * @author lipangpang
 * @date 2021/12/27
 * @description
 */
public interface IGroupChatMediator {
    /**
     * 退出聊天室
     *
     * @param colleague
     */
    void join(IColleague colleague);

    /**
     * 散发群音讯
     *
     * @param colleague
     */
    void distributeMsg(IColleague colleague);
}

/**
 * 聊天室中介
 *
 * @author lipangpang
 * @date 2021/12/27
 * @description
 */
public class GroupChatMediator implements IGroupChatMediator {private List<IColleague> colleagues = new ArrayList<>();

    @Override
    public void join(IColleague colleague) {colleagues.add(colleague);
    }

    @Override
    public void distributeMsg(IColleague colleague) {for (IColleague iColleague : colleagues) {if (iColleague == colleague) {continue;}
            iColleague.receiveMsg("[" + colleague.getName() + "]" + colleague.getMsg());
        }
    }
}

public class TestMain {public static void main(String[] args) {IGroupChatMediator groupChatMediator = new GroupChatMediator();
        IColleague zhangsan = new Colleague(groupChatMediator, "张三");
        IColleague lisi = new Colleague(groupChatMediator, "李四");
        IColleague wangwu = new Colleague(groupChatMediator, "王五");
        groupChatMediator.join(zhangsan);
        groupChatMediator.join(lisi);
        groupChatMediator.join(wangwu);
        zhangsan.sendMsg("你好啊");
        System.out.println("------------------");
        lisi.sendMsg("新年快乐");
        System.out.println("------------------");
        wangwu.sendMsg("happy new year");
    }
}

后果:

李四接管:[张三]你好啊
王五接管:[张三]你好啊
------------------
张三接管:[李四]新年快乐
王五接管:[李四]新年快乐
------------------
张三接管:[王五]happy new year
李四接管:[王五]happy new year

类图:

解释器模式

含意:给剖析对象定义一个语言,并定义该语言的文法示意,再设计一个解析器来解释语言中的句子。

解释器模式构造如下。

  1. 形象表达式(Abstract Expression)角色:定义解释器的接口,约定解释器的解释操作,次要蕴含解释办法 interpret()。
  2. 终结符表达式(Terminal Expression)角色:是形象表达式的子类,用来实现文法中与终结符相干的操作,文法中的每一个终结符

    都有一个具体终结表达式与之绝对应。

  3. 非终结符表达式(Nonterminal Expression)角色:也是形象表达式的子类,用来实现文法中与非终结符相干的操作,文法中的每条规定都对应于一个非终结符表达式。
  4. 环境(Context)角色:通常蕴含各个解释器须要的数据或是公共的性能,个别用来传递被所有解释器共享的数据,前面的解释器可

    以从这里获取这些值。

  5. 客户端(Client):次要工作是将须要剖析的句子或表达式转换成应用解释器对象形容的形象语法树,而后调用解释器的解释办法,

    当然也能够通过环境角色间接拜访解释器的解释办法。

示例:实现 1 +1=2,2-1= 1 的数学表达式运算。1,2 数字是终结符角色,+,- 运算符是非终结符角色。

/**
 * 表达式接口
 *
 * @author lipangpang
 * @date 2021/12/28
 * @description
 */
public interface IExpression {
    /**
     * 解释表达式
     *
     * @return
     */
    Integer interpreter();}

/**
 * 终结符表达式
 *
 * @author lipangpang
 * @date 2021/12/28
 * @description
 */
public class TerminalExpression implements IExpression {
    /**
     * 以后终结符存储的值
     */
    private Integer value;

    public TerminalExpression(Integer value) {this.value = value;}

    @Override
    public Integer interpreter() {return this.value;}
}

/**
 * 非终结符表达式
 *
 * @author lipangpang
 * @date 2021/12/28
 * @description
 */
public abstract class NonTerminalExpression implements IExpression {
    /**
     * 终结符表达式左值
     */
    protected IExpression leftValue;
    /**
     * 终结符表达式右值
     */
    protected IExpression rightValue;

    public NonTerminalExpression(IExpression leftValue, IExpression rightValue) {
        this.leftValue = leftValue;
        this.rightValue = rightValue;
    }

}

/**
 * 加运算非终结符
 *
 * @author lipangpang
 * @date 2021/12/28
 * @description
 */
public class AddExpression extends NonTerminalExpression {public AddExpression(IExpression leftValue, IExpression rightValue) {super(leftValue, rightValue);
    }

    @Override
    public Integer interpreter() {return this.leftValue.interpreter() + this.rightValue.interpreter();}
}

/**
 * 减运算非终结符
 *
 * @author lipangpang
 * @date 2021/12/28
 * @description
 */
public class SubExpression extends NonTerminalExpression {public SubExpression(IExpression leftValue, IExpression rightValue) {super(leftValue, rightValue);
    }

    @Override
    public Integer interpreter() {return this.leftValue.interpreter() - this.rightValue.interpreter();}
}

/**
 * 计算器环境类
 *
 * @author lipangpang
 * @date 2021/12/29
 * @description
 */
public class CalculatorContext {public Integer parse(String info) {String[] split = info.split(" ");
        IExpression leftValue = null;// 运算左值
        IExpression rightValue = null;// 运算右值
        IExpression operator = null;// 运算符
        for (String element : split) {if (!("+".equals(element) || "-".equals(element))) {if (leftValue == null) {leftValue = new TerminalExpression(Integer.parseInt(element));
                    continue;
                }
                if (rightValue == null) {rightValue = new TerminalExpression(Integer.parseInt(element));
                }
            }
        }
        for (String element : split) {if ("+".equals(element)) {operator = new AddExpression(leftValue, rightValue);
            } else if ("-".equals(element)) {operator = new SubExpression(leftValue, rightValue);
            }
        }
        return operator.interpreter();}
}

public class TestMain {public static void main(String[] args) {System.out.println(new CalculatorContext().parse("1 + 1"));
        System.out.println(new CalculatorContext().parse("2 - 1"));
    }
}

后果:

2
1

类图:

访问者模式

含意:将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,使其在不扭转数据结构的前提下能够增加作用于这些元素的新

的操作,为数据结构中的每个元素提供多种拜访形式。

访问者模式构造如下。

  1. 形象访问者(Visitor)角色:定义一个拜访具体元素的接口,为每个具体元素类对应一个拜访操作 visit(),该操作中的参数类型标识

    了被拜访的具体元素。

  2. 具体访问者(ConcreteVisitor)角色:实现形象访问者角色中申明的各个拜访操作,确定访问者拜访一个元素时该做什么。
  3. 形象元素(Element)角色:申明一个蕴含承受操作 accept() 的接口,被承受的访问者对象作为 accept() 办法的参数。
  4. 具体元素(ConcreteElement)角色:实现形象元素角色提供的 accept() 操作,其办法体通常都是 visitor.visit(this),另外具体元素

    中可能还蕴含自身业务逻辑的相干操作。

  5. 对象构造(Object Structure)角色:是一个蕴含元素角色的容器,提供让访问者对象遍历容器中的所有元素的办法,通常由 List、

    Set、Map 等聚合类实现。

示例:厨师会把面粉做成面条,烘培师会把面粉做成面包;厨师会把鸡蛋做成煎蛋,烘培师会把鸡蛋做成蛋糕。

/**
 * 原料接口
 *
 * @author lipangpang
 * @date 2021/12/29
 * @description
 */
public interface IMaterial {String accept(IPersonVisitor personVisitor);
}

/**
 * 面粉
 *
 * @author lipangpang
 * @date 2021/12/29
 * @description
 */
public class Flour implements IMaterial {
    @Override
    public String accept(IPersonVisitor personVisitor) {return personVisitor.create(this);
    }
}

/**
 * 鸡蛋
 *
 * @author lipangpang
 * @date 2021/12/29
 * @description
 */
public class Egg implements IMaterial {
    @Override
    public String accept(IPersonVisitor personVisitor) {return personVisitor.create(this);
    }
}

/**
 * 人访问者接口
 *
 * @author lipangpang
 * @date 2021/12/29
 * @description
 */
public interface IPersonVisitor {String create(Flour flour);

    String create(Egg egg);
}

/**
 * 烘培师
 *
 * @author lipangpang
 * @date 2021/12/29
 * @description
 */
public class Baker implements IPersonVisitor {
    @Override
    public String create(Flour flour) {return "烘培师把面粉做成面包";}

    @Override
    public String create(Egg egg) {return "烘培师把鸡蛋做成蛋糕";}
}

/**
 * 厨师
 *
 * @author lipangpang
 * @date 2021/12/29
 * @description
 */
public class Cook implements IPersonVisitor {
    @Override
    public String create(Flour flour) {return "厨师把面粉做成面条";}

    @Override
    public String create(Egg egg) {return "厨师把鸡蛋做成煎蛋";}
}

/**
 * 资料容器
 *
 * @author lipangpang
 * @date 2021/12/29
 * @description
 */
public class MaterialContainer {List<IMaterial> materials = new ArrayList<>();

    public void addMaterial(IMaterial material) {materials.add(material);
    }

    public void accept(IPersonVisitor personVisitor) {for (IMaterial material : materials) {String result = material.accept(personVisitor);
            System.out.println(result);
        }
    }
}

public class TestMain {public static void main(String[] args) {MaterialContainer materialContainer = new MaterialContainer();
        materialContainer.addMaterial(new Flour());
        materialContainer.addMaterial(new Egg());
        materialContainer.accept(new Cook());
        System.out.println("------------");
        materialContainer.accept(new Baker());
    }
}

后果:

厨师把面粉做成面条
厨师把鸡蛋做成煎蛋
------------
烘培师把面粉做成面包
烘培师把鸡蛋做成蛋糕

类图:

观察者模式

含意:多个对象间存在一对多的依赖关系,当一个对象的状态产生扭转时,所有依赖于它的对象都失去告诉并被自动更新。

观察者模式构造如下。

  1. 形象主题(Subject)角色:也叫形象指标类,它提供了一个用于保留观察者对象的汇集类和减少、删除观察者对象的办法,以及通

    知所有观察者的形象办法。

  2. 具体主题(Concrete Subject)角色:也叫具体指标类,它实现形象指标中的告诉办法,当具体主题的外部状态产生扭转时,告诉所

    有注册过的观察者对象。

  3. 形象观察者(Observer)角色:它是一个抽象类或接口,它蕴含了一个更新本人的形象办法,当接到具体主题的更改告诉时被调用。
  4. 具体观察者(Concrete Observer)角色:实现形象观察者中定义的形象办法,以便在失去指标的更改告诉时更新本身的状态。

示例:微信公众号公布新音讯时,所有关注者都会承受到信息揭示。

/**
 * 用户观察者接口
 *
 * @author lipangpang
 * @date 2021/12/30
 * @description
 */
public interface IUserObserver {
    /**
     * 承受音讯
     *
     * @param msg
     */
    void receive(String msg);
}

/**
 * @author lipangpang
 * @date 2021/12/30
 * @description
 */
public class UserObserver implements IUserObserver {
    /**
     * 观察者姓名
     */
    private String name;

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

    @Override
    public void receive(String msg) {System.out.println(this.name + "接管音讯:" + msg);
    }
}

/**
 * 公众号主题抽象类
 *
 * @author lipangpang
 * @date 2021/12/30
 * @description
 */
public abstract class IOfficialAccountSubject {
    /**
     * 所有订阅公众号的用户观察者
     */
    List<IUserObserver> userObservers = new ArrayList<>();

    /**
     * 订阅公众号
     *
     * @param userObserver
     */
    public void addObserver(IUserObserver userObserver) {userObservers.add(userObserver);
    }

    /**
     * 推送音讯
     *
     * @param msg
     */
    public abstract void notifyObserver(String msg);
}

/**
 * 公众号
 *
 * @author lipangpang
 * @date 2021/12/30
 * @description
 */
public class OfficialAccountSubject extends IOfficialAccountSubject {
    @Override
    public void notifyObserver(String msg) {System.out.println("公众号推送音讯:" + msg);
        System.out.println("----------------");
        for (IUserObserver userObserver : userObservers) {userObserver.receive(msg);
        }
    }
}

public class TestMain {public static void main(String[] args) {IOfficialAccountSubject officialAccountSubject = new OfficialAccountSubject();
        UserObserver zhangsan = new UserObserver("zhangsan");
        UserObserver lisi = new UserObserver("lisi");
        officialAccountSubject.addObserver(zhangsan);
        officialAccountSubject.addObserver(lisi);
        officialAccountSubject.notifyObserver("新年快乐");
        System.out.println();
        officialAccountSubject.notifyObserver("给大伙派送红包");
    }
}

后果:

公众号推送音讯: 新年快乐
----------------
zhangsan 接管音讯:新年快乐
lisi 接管音讯:新年快乐

公众号推送音讯: 给大伙派送红包
----------------
zhangsan 接管音讯:给大伙派送红包
lisi 接管音讯:给大伙派送红包

类图:

委派模式(不属于 GoF 23 种设计模式)

含意:负责工作的调度和分配任务。

示例:实现 servlet 的申请,依据不同的用户申请 url 调用不同的办法。

/**
 * 商品控制器
 *
 * @author lipangpang
 * @date 2021/12/30
 * @description
 */
public class ProductController {public void getProductInfo() {System.out.println("这是商品信息");
    }
}

/**
 * 用户控制器
 *
 * @author lipangpang
 * @date 2021/12/30
 * @description
 */
public class UserController {public void getUserInfo() {System.out.println("这是用户信息");
    }
}

/**
 * servlet 接口
 *
 * @author lipangpang
 * @date 2021/12/30
 * @description
 */
public interface IServlet {Object dispatcher(String url);
}

/**
 * servlet
 *
 * @author lipangpang
 * @date 2021/12/30
 * @description
 */
public class Servlet implements IServlet {

    @Override
    public Object dispatcher(String url) {if ("/user".equals(url)) {new UserController().getUserInfo();} else if ("/product".equals(url)) {new ProductController().getProductInfo();}
        return null;
    }
}


/**
 * 客户端
 *
 * @author lipangpang
 * @date 2021/12/30
 * @description
 */
public class Client {
    private IServlet servlet;

    public Client(IServlet servlet) {this.servlet = servlet;}

    public void sendCommand(String url) {this.servlet.dispatcher(url);
    }
}

public class TestMain {public static void main(String[] args) {Servlet servlet = new Servlet();
        Client client = new Client(servlet);
        client.sendCommand("/user");
        client.sendCommand("/product");
    }
}

后果:

这是用户信息
这是商品信息

类图:

正文完
 0