一、设计模式简介

1.1、设计模式七大原则

1.开闭原则 
对扩展开放,对修改关闭。

2.依赖倒置原则(面向接口编程)
依赖关系通过接口、抽象类。

3.单一职责原则 
一个类、接口、方法只负责一项职责或职能。

4.接口隔离原则 
客户端不需要多余的接口,一个类对另一个类的依赖建立在最小的接口上。

5.迪米特法则(最少知道原则)
一个对象对其他对象尽可能少的了解,每个类尽量减少对其他类的依赖(降低耦合)。

6.里氏替换原则
1.子类必须实现父类的抽象方法,但不得重写(覆盖)父类的非抽象(已实现)方法。
2.子类中可以增加自己特有的方法。
3.子类实现父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。
4.子类实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。

7.合成/复用原则(组合/复用原则)
尽量使用合成/聚合,少用继承。

1.2、设计模式种类 

1.2.1、创建型模式5种 

提供实例化的方法,为适合的状况提供相应的对象创建方法。
    工厂方法模式【Factory Method】
    抽象工厂模式【Abstract Factory】
    创建者模式【Builder】
    原型模式【Prototype】
    单例模式【Singleton】

1.2.2、结构型模式7种 

用来处理实体之间的关系,使得这些实体能够更好地协同工作。
    外观模式【Facade】
    适配器模式【Adapter】
    代理模式【Proxy】
    装饰模式【Decorator】
    桥接模式【Bridge】
    组合模式【Composite】
    享元模式【Flyweight】

1.2.3、行为型模式11种  

不同的实体间进行通信,为实体之间的通信提供更容易,更灵活的通信方法。
    模板方法模式【Template Method】
    观察者模式【Observer】
    状态模式【State】
    策略模式【Strategy】
    职责链模式【Chain of Responsibility】
    命令模式【Command】
    访问者模式【Visitor】
    调停者模式【Mediator】
    备忘录模式【Memento】
    迭代器模式【Iterator】
    解释器模式【Interpreter】

二、常用的设计模式 

2.1、工厂模式 

将抽象类的子类建造控制在工厂中,只关注产品的生产,便于管理。

组成 
IProduct:抽象产品接口,描述所有实例所共有的公共接⼝。
Product:具体产品类,实现抽象产品类的接⼝,⼯⼚ 类创建对象,有多个需要定义多个。
IFactory:抽象⼯⼚接口,描述具体⼯⼚的公共接⼝。
Factory:具体⼯⼚类,实现创建产品类对象,实现抽象⼯⼚类的接⼝,有多个需要定义多个。

public interface Meat {
    String getName();
}

public class BeefMeat implements Meat{
    public String getName(){
        return "牛肉";
    }
}

public class PigMeat implements Meat{
    public String getName(){
        return "猪肉";
    }
}

public class MeatFactory {
    public static Meat creatMeat(String meatName){
        if("Pig".equals(meatName)){
            return new PigMeat();
        }if ("Beef".equals(meatName)){
            return new BeefMeat();
        }else {
            return null;
        }
    }
}

public static void main(String[] args) {
	Meat meat = MeatFactory.creatMeat("Beef");
	System.out.println(meat.getName());
}

2.2、单例模式 


//静态内部类单例
public class Singleton {
	private static class LazyHolder {
	  private static final Singleton single = new Singleton();
	} 
	  private Singleton (){}
	  public static final Singleton getSingle() {
		return LazyHolder.single;
	  }
}
 
//枚举
enum Singleton {
	INSTANCE; //属性
	public void sayOK() {
		System.out.println("ok~");
	}
}

2.3、建造者模式 

常用于一些基本部件不变而组合方式常变的场景,关注产品的组合方式和装配顺序。

组成 

Product(产品):具体的产品对象。
Builder(抽象建造者):创建 Product 对象的各个部件指定的接口或抽象类。
ConcreteBuilder(具体建造者):实现Builder 接口,构建和装配各个部件。
Director(指挥者):隔离客户与对象的产生过程,负责控制产品对象的生产过程。

// 产品
public class Computer {

    private String cpu;

    private String memory;

    private String disk;

    public String getCpu() {
        return cpu;
    }

    public void setCpu(String cpu) {
        this.cpu = cpu;
    }

    public String getMemory() {
        return memory;
    }

    public void setMemory(String memory) {
        this.memory = memory;
    }

    public String getDisk() {
        return disk;
    }

    public void setDisk(String disk) {
        this.disk = disk;
    }

    @Override
    public String toString() {
        return "Computer{" +
                "cpu='" + cpu + '\'' +
                ", memory='" + memory + '\'' +
                ", disk='" + disk + '\'' +
                '}';
    }
}

// 抽象建造者
public interface ComputerBuilder {
    void buildCpu();
    void buildMemory();
    void buildDisk();
    Computer buildComputer();
}

// 具体建造者
public class ComputerConcreteBuilder implements ComputerBuilder{
    Computer computer;
    public ComputerConcreteBuilder() {
        computer = new Computer();
    }

    @Override
    public void buildCpu() {
        System.out.println("建造 8核 CPU");
        computer.setCpu("8核");
    }

    @Override
    public void buildMemory() {
        System.out.println("建造 32G 主存");
        computer.setMemory("32G");
    }

    @Override
    public void buildDisk() {
        System.out.println("建造 1TG 硬盘");
        computer.setDisk("1TG");
    }

    @Override
    public Computer buildComputer() {
        return computer;
    }
}

// 指挥者
public class ComputerDirector {
    public Computer constructComputer(ComputerBuilder computerBuilder){
        computerBuilder.buildCpu();
        computerBuilder.buildMemory();
        computerBuilder.buildDisk();
        return computerBuilder.buildComputer();
    }
}

public static void main(String[] args) {
	ComputerDirector computerDirector = new ComputerDirector();
	ComputerBuilder computerBuilder = new ComputerConcreteBuilder();
	Computer computer = computerDirector.constructComputer(computerBuilder);
	System.out.println(computer);
}

2.4、适配器模式 

角色 
Source:待适配的类、  Targetable:适配器、  Adapter:目标接口

类适配器、对象适配器、接口适配器

/**
 * 目标接口
 */
public interface Targetable {
    void editFile();
    void addFile();
}

/**
 * 待适配类
 */
public class Source {
    public void editFile(){
        System.out.println("待适配类---Source---editFile---");
    }
}

/**
 * 类适配器
 */
public class Adapater extends Source implements Targetable{
    @Override
    public void addFile() {
        System.out.println("类适配器---Adapater---addFile");
    }
    public static void main(String[]args){
        Targetable targetable = new Adapater();
        targetable.addFile();
        targetable.editFile();
    }
}


/**
 * 对象适配器
 */
public class ObjectAdapter implements Targetable{

    private Source source;

    public ObjectAdapter(Source sou){
        super();
        this.source = sou;
    }
    @Override
    public void editFile() {
        //System.out.println("对象适配器---ObjectAdapter---editFile");
        this.source.editFile();
    }
    @Override
    public void addFile() {
        System.out.println("对象适配器---ObjectAdapter---addFile");
    }
    public static void main(String[]args){
        Source so = new Source();
        Targetable targetable = new ObjectAdapter(so);
        targetable.addFile();
        targetable.editFile();
    }
}


/**
 * 接口类适配器
 */
public abstract class AbstractAdapter implements Targetable{
    @Override
    public void editFile() {
    }
    @Override
    public void addFile() {
    }
}

public class SourceSub1 extends AbstractAdapter{
    @Override
    public void editFile() {
        System.out.println("SourceSub1---editFile");
    }
}

public class SourceSub2 extends AbstractAdapter{
    @Override
    public void addFile() {
    System.out.println("SourceSub2---addFile");
    }
}

2.5、外观模式

角色
子系统角色:实现子系统功能。
门面角色:熟悉个子系统功能和调用关系,根据客户需要封装成统一方法对外提供服务。
客户角色:通过门面实现需求。

public class Model01 {
    public void model01Start(){
        System.out.println("Model01---model01Start");
    }
    public void model01Shutdown(){
        System.out.println("Model01---model01Shutdown");
    }
}

public class Model02 {
    public void model02Start(){
        System.out.println("Model02---model02Start");
    }
    public void model02Shutdown(){
        System.out.println("Model02---model02Shutdown");
    }
}

public class Facade {

    private Model01 model01;
    private Model02 model02;
    public Facade(){
        this.model01 = new Model01();
        this.model02 = new Model02();
    }
    public void start(){
        this.model01.model01Start();
        this.model02.model02Start();
    }
    public void shutdown(){
        this.model01.model01Shutdown();
        this.model02.model02Shutdown();
    }

    public static void main(String arg[] ) {
        Facade facade = new Facade();
        facade.start();
        facade.shutdown();
    }
}

2.6、桥接模式

使用桥梁(组合方式)将两个抽象类连起来,
将抽象与实现分离,解决需求多变继承类过多问题。
如: 开发跨平台的视频播放器,平台有 Android、iOS、Windows、Linux、Mac,
播放器的格式有 MP4、RMVB、FLV 格式。这种情况下,适合使用桥接模式。

public interface Driver {
    void executeSQL();
}

public class MysqlDriver implements Driver{
    @Override
    public void executeSQL() {
        System.out.println("MysqlDriver---executeSQL");
    }
}

public class OracleDriver implements Driver{
    @Override
    public void executeSQL() {
        System.out.println("OracleDriver---executeSQL");
    }
}


public abstract class DriverManagerBridge {

    private Driver driver;

    public Driver getDriver() {
        return driver;
    }

    public void setDriver(Driver driver) {
        this.driver = driver;
    }
    public void executeSql(){
        this.driver.executeSQL();
    }
}

public class MyDriverBridge extends DriverManagerBridge{

    public void execute(){
        getDriver().executeSQL();
    }
    
    public static void main(String arg[] ) {
        DriverManagerBridge driverManagerBridge = new MyDriverBridge();
        driverManagerBridge.setDriver(new MysqlDriver());
        driverManagerBridge.executeSql();
        driverManagerBridge.setDriver(new OracleDriver());
        driverManagerBridge.executeSql();
    }
}

2.7、享元模式 

通过对象的复用减少对象的创建次数和数量。

public class Memory {

    private int size; // 内存大小
    private boolean isused; // 内存是否使用
    private String id; // 内存ID

    public Memory(int size, boolean isused, String id) {
        this.size = size;
        this.isused = isused;
        this.id = id;
    }

    public int getSize() {
        return size;
    }

    public void setSize(int size) {
        this.size = size;
    }

    public boolean isIsused() {
        return isused;
    }

    public void setIsused(boolean isused) {
        this.isused = isused;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
}


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

public class MemoryFactory {

    private static List<Memory> memoryList = new ArrayList<>();

    // 获取内存
    public static Memory getMemory(int size){
        Memory memory = null;
        for (int i=0;i< memory.getSize();i++){
            memory = memoryList.get(i);
            if(memory.isIsused()==false&&memory.getSize()==size){
                memory.setIsused(true);
                memoryList.set(i,memory);
                break;
            }
        }
        if(memory==null){
            memory = new Memory(32,true, UUID.randomUUID().toString());
            memoryList.add(memory);
        }
        return memory;
    }

    // 释放内存
    public static void releaseMemory(String id){
        for (int i=0;i<memoryList.size();i++){
            Memory memory = memoryList.get(i);
            if(memory.getId().equals(id)){
                memory.setIsused(false);
                memoryList.set(i,memory);
                break;
            }
        }
    }
}

2.8、策略模式 

通过多态消除 if else

public interface Car {
    void run();
}

public class BMWCar implements Car {
    public void run() {
        System.out.println("宝马车在行驶......");
    }
}

public class BMWCar implements Car {
    public void run() {
        System.out.println("宝马车在行驶......");
    }
}

public class CarContext {

    private static CarContext carContext = new CarContext();

    private CarContext(){}

    private static Map carMap = new HashMap(16);

    static {
        carMap.put("BMWCar",new BMWCar());
        carMap.put("BenzCar",new BenzCar());
    }

    public Car create(Integer payCode){
        return (Car) carMap.get(payCode);
    }

    public static CarContext getInstance(){
        return carContext;
    }
}

2.9、模版方法模式 

将相同部分代码,放在抽象的父类中;不同的代码,放在不同的子类中。符合开闭原则。

/**
 * 抽象的父类 
 */
public abstract class Fridge {
    /**
     * 模板方法 不能被修改,用 final 修饰
     */
    protected final void store() {
        openDoor();
        closeDoor();
        // 这个钩子方法可以让子类控制模板方法的执行流程
        if (needColdStorage()) {
            codeStorage();
        }
        put();
    }

    /**
     * 该方法是不变的,不允许子类修改
     */
    final void openDoor() {
        System.out.println("打开冰箱门");
    }
    /**
     * 该方法是不变的,不允许子类修改
     */
    final void codeStorage() {
        System.out.println("打开冷藏功能");
    }

    /**
     * 钩子方法 , 子类可以进行覆盖 将适当的权限开放给应用层,用于控制模板方法流程。
     */
    protected boolean needColdStorage() {
        return false;
    }

    /**
     * 抽象方法 , 需要子类进行实现
     */
    abstract void put();

    final void closeDoor() {
        System.out.println("关闭冰箱门");
    }
}

/**
 * 鱼放冰箱
 */
public class FishFridge extends Fridge {
    @Override
    void put() {
        System.out.println("把鱼放进冰箱");
    }

    @Override
    protected boolean needColdStorage() {
        // 需要冷藏存储
        return true;
    }
}

/**
 * 大象放冰箱
 */
public class ElephantFridge extends Fridge {
    @Override
    void put() {
        System.out.println("把大象放进冰箱");
    }
}

    public static void main(String[] args) {
        // 把大象放到冰箱
        Fridge elephantFridge = new ElephantFridge();
        elephantFridge.store();
        System.out.println();
        // 把鱼放到冰箱
        Fridge fishFridge = new FishFridge();
        fishFridge.store();
    }

2.10、观察者模式 

将观察对象封装进  private Vector<Observer> obs; 队列中,被观察的内容改变时遍历队列,通知到观察者。

/**
 * 被观察的对象
 * JDK 提供了对观察者模式的支持 , 被观察者可以继承 Observable 类
 */
public class Game extends Observable {
    private String name;

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

    public String getName() {
        return name;
    }

    /**
     * 用户提交问题
     */
    public void produceQuestion(Game game, String question) {
        System.out.println(" 在 " + game.name + " 游戏中提交问题 : " + question);
        // 代表 被观察者 的状态发生了改变
        setChanged();
        // 通知 观察者
        notifyObservers(question);
    }
}

/**
 * 观察者 — 管理员类
 */
public class Manager implements Observer {
    /**
     * 管理员名称
     */
    private String name;

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

    @Override
    public void update(Observable o, Object arg) {
        // 获取 被观察者 对象
        Game game = (Game) o;
        // 获取 被观察者 对象 调用 notifyObservers 方法的参数
        String question = (String) arg;
        System.out.println(name + " 观察者 接收到 被观察者 " + game.getName() + " 的通知 , 用户 " + " 提出问题 " + question);
    }
}

    public static void main(String[] args) {
        // 创建被观察者
        Game game = new Game("Cat And Mouse");
        // 创建观察者
        Manager manager = new Manager("Tom");
        // 关联 观察者 与 被观察者
        game.addObserver(manager);
        // 在游戏中提交问题
        game.produceQuestion(game,"游戏崩溃");
    }

2.11、责任链模式 

责任两两关联,将被处理体传递到下个责任人。
一个请求的处理,需要多个对象协作进行处理。
OA的审批流程、账号注册时的阶段校验等。

/**
 * 用户账户信息  账号 , 密码 , 电话号码
 */
public class UserAccount {

    private String userName;
    private String password;
    private String phoneNumber;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }
}

/**
 * 校验类的父类 校验账号,校验密码,校验手机号 的请求类都需要继承该类
 */
public abstract class Verify {
    // 下个校验器
    protected Verify nextVerify;

    /**
     * 设置下一个校验器
     */
    public void setNextVerify(Verify verify) {
        this.nextVerify = verify;
    }

    /**
     * 校验过程
     */
    public abstract void deploy(UserAccount userAccount);
}

/**
 * 校验用户名称
 */
public class UserNameVerify extends Verify{
    @Override
    public void deploy(UserAccount userAccount) {
        if (userAccount.getUserName() != null){
            System.out.println("用户名校验通过");
            // 获取下一个验证器
            if (nextVerify != null) {
                nextVerify.deploy(userAccount);
            }
        } else {
            System.out.println("用户名校验未通过");
        }
    }
}

/**
 * 校验密码
 */
public class PasswordVerify extends Verify{
    @Override
    public void deploy(UserAccount userAccount) {
        if (userAccount.getPassword() != null){
            System.out.println("密码校验通过");
            // 获取下一个验证器
            if (nextVerify != null) {
                nextVerify.deploy(userAccount);
            }
        } else {
            System.out.println("密码校验未通过");
        }
    }
}

/**
 * 校验手机号
 */
public class PhoneVerify extends Verify{
    @Override
    public void deploy(UserAccount userAccount) {
        if (userAccount.getPhoneNumber() != null){
            System.out.println("手机号校验通过");
            // 获取下一个验证器
            if (nextVerify != null) {
                nextVerify.deploy(userAccount);
            }
        } else {
            System.out.println("手机号校验未通过");
        }
    }
}

    public static void main(String[] args) {
        UserNameVerify userNameVerify = new UserNameVerify();
        PasswordVerify passwordVerify = new PasswordVerify();
        PhoneVerify phoneVerify = new PhoneVerify();

        UserAccount userAccount = new UserAccount();
        userAccount.setUserName("username");
        userAccount.setPassword("123456");
        userAccount.setPhoneNumber("13888888888");

        // 创建职责链
        userNameVerify.setNextVerify(passwordVerify);
        passwordVerify.setNextVerify(phoneVerify);

        // 开始校验,执行职责链。
        userNameVerify.deploy(userAccount);
    }

2.12、状态模式

一个对象,存在多个状态,状态可以相互转换;内部状态改变,行为也要进行改变。
将各种状态的转换逻辑,分到状态的子类中,减少相互依赖。可用享元模式,在多个上下文中,共享状态实例。

/**
 * 视频状态 父类
 */
public abstract class VedioState {

    /**
     * 视频播放上下文 声明为 protected , 子类可以拿到该成员变量
     */
    protected VedioContext vedioContext;

    public void setVedioContext(VedioContext vedioContext) {
        this.vedioContext = vedioContext;
    }

    /**
     * 播放 对应播放状态
     */
    public abstract void play();

    /**
     * 停止 对应停止状态
     */
    public abstract void pause();

    /**
     * 快进 对应快进状态
     */
    public abstract void speed();

    /**
     * 停止 对应停止状态
     */
    public abstract void stop();
}

/**
 * 视频的播放状态 可以进行 快进 , 暂停 , 停止 操作
 */
public class PlayState extends VedioState{

    @Override
    public void play() {
        System.out.println("正常播放视频");
    }

    @Override
    public void pause() {
        super.vedioContext.setVedioState(VedioContext.PAUSE_STATE);
    }

    @Override
    public void speed() {
        super.vedioContext.setVedioState(VedioContext.SPEED_STATE);
    }

    @Override
    public void stop() {
        super.vedioContext.setVedioState(VedioContext.STOP_STATE);
    }
}

/**
 * 视频快进状态  可 播放、暂停、停止
 */
public class SpeedState extends VedioState{

    @Override
    public void play() {
        super.vedioContext.setVedioState(VedioContext.PLAY_STATE);
    }

    @Override
    public void pause() {
        System.out.println("快进播放视频");
    }

    @Override
    public void speed() {
        super.vedioContext.setVedioState(VedioContext.SPEED_STATE);
    }

    @Override
    public void stop() {
        super.vedioContext.setVedioState(VedioContext.STOP_STATE);
    }
}


/**
 * 暂停状态  可切换到 播放、快进、停止
 */
public class PauseState extends VedioState{

    /**
     * 播放时 , 只需要调用 PlayState 父类 VedioState 的上下文 VedioContext
     *      将上下文 VedioContext 中的状态 , 设置为 播放 的状态即可
     */
    @Override
    public void play() {
        super.vedioContext.setVedioState(VedioContext.PLAY_STATE);
    }

    /**
     * 暂停时 , 只需要调用 PlayState 父类 VedioState 的上下文 VedioContext
     *      将上下文 VedioContext 中的状态 , 设置为 暂停 的状态即可
     */
    @Override
    public void pause() {
        System.out.println("暂停播放视频");
    }

    /**
     * 快进时 , 只需要调用 PlayState 父类 VedioState 的上下文 VedioContext
     *      将上下文 VedioContext 中的状态 , 设置为 快进 的状态即可
     */
    @Override
    public void speed() {
        super.vedioContext.setVedioState(VedioContext.SPEED_STATE);
    }

    /**
     * 停止时 , 只需要调用 PlayState 父类 VedioState 的上下文 VedioContext
     *      将上下文 VedioContext 中的状态 , 设置为 停止 的状态即可
     */
    @Override
    public void stop() {
        super.vedioContext.setVedioState(VedioContext.STOP_STATE);
    }
}

/**
 * 视频的停止状态  能 播放;不能快进、暂停
 */
public class StopState extends VedioState{
    /**
     * 播放时 , 只需要调用 PlayState 父类 VedioState 的上下文 VedioContext
     *      将上下文 VedioContext 中的状态 , 设置为 播放 的状态即可
     */
    @Override
    public void play() {
        super.vedioContext.setVedioState(VedioContext.PLAY_STATE);
    }

    /**
     * 不能暂停
     */
    @Override
    public void pause() {
        System.out.println("停止状态不能暂停");
    }

    /**
     * 不能快进
     */
    @Override
    public void speed() {
        System.out.println("停止状态不能快进");
    }

    @Override
    public void stop() {
        System.out.println("停止播放视频");
    }
}

/**
 * 享元模式 共享同一个对象
 */
public class VedioContext {

    // 当前的状态
    private VedioState mVedioState;
    // 播放状态
    public final static PlayState PLAY_STATE = new PlayState();
    // 暂停状态
    public final static PauseState PAUSE_STATE = new PauseState();
    // 快进状态
    public final static SpeedState SPEED_STATE = new SpeedState();
    // 停止状态
    public final static StopState STOP_STATE = new StopState();

    public VedioState getVedioState() {
        return mVedioState;
    }

    public void setVedioState(VedioState mVedioState) {
        this.mVedioState = mVedioState;
        this.mVedioState.setVedioContext(this);
    }

    public void play() {
        this.mVedioState.play();
    }

    public void pause() {
        this.mVedioState.pause();
    }

    public void speed() {
        this.mVedioState.speed();
    }

    public void stop() {
        this.mVedioState.stop();
    }
}

public static void main(String[] args) {
    VedioContext vedioContext = new VedioContext();
    vedioContext.setVedioState(VedioContext.PLAY_STATE);
    System.out.println("当前视频状态 : " + vedioContext.getVedioState().getClass().getSimpleName());

    vedioContext.pause();
    System.out.println("当前视频状态 : " + vedioContext.getVedioState().getClass().getSimpleName());

    vedioContext.speed();
    System.out.println("当前视频状态 : " + vedioContext.getVedioState().getClass().getSimpleName());

    vedioContext.stop();
    System.out.println("当前视频状态 : " + vedioContext.getVedioState().getClass().getSimpleName());

    vedioContext.speed();
    System.out.println("当前视频状态 : " + vedioContext.getVedioState().getClass().getSimpleName());
}

2.13、备忘录模式 

存档信息:封装 存档信息。
恢复机制:为用户提供 可恢复 机制。
如: Ctrl + Z 执行 "撤销" 操作,游戏中的存档使用。

/**
 * 文档 要保存的对象
 */
public class Article {
    private String title;
    private String content;

    public Article(String tittle, String content) {
        this.title = tittle;
        this.content = content;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
    /**
     * 保存信息到备忘录
     */
    public ArticleMemento saveToMemento() {
        ArticleMemento articleMemento = new ArticleMemento(title, content);
        return articleMemento;
    }

    /**
     * 从备忘录恢复
     */
    public void undoFromMemento(ArticleMemento articleMemento) {
        this.title = articleMemento.getTitle();
        this.content = articleMemento.getContent();
    }

    @Override
    public String toString() {
        return "Article{" +
                "title='" + title + '\'' +
                ", content='" + content + '\'' +
                '}';
    }
}

/**
 * 文档的备忘录类
 */
public class ArticleMemento {
    private String title;
    private String content;

    public ArticleMemento(String title, String content) {
        this.title = title;
        this.content = content;
    }

    public String getTitle() {
        return title;
    }

    public String getContent() {
        return content;
    }

    @Override
    public String toString() {
        return "ArticleMemento{" +
                "title='" + title + '\'' +
                ", content='" + content + '\'' +
                '}';
    }
}

/**
 * 备忘录管理类
 */
public class ArticleMementoManager {
    /**
     * 存储所有的备忘录信息 在 栈 数据结构中存储 , 特点后进先出
     */
    private final Stack<ArticleMemento> mArticleMementoStack = new Stack<>();

    /**
     * 获取栈顶的备忘录信息
     */
    public ArticleMemento getArticleMemento() {
        return mArticleMementoStack.pop();
    }

    /**
     * 备忘录信息入栈 放在栈顶
     */
    public void setArticleMemento(ArticleMemento articleMemento) {
        mArticleMementoStack.push(articleMemento);
    }
}

    public static void main(String[] args) {
        ArticleMementoManager articleMementoManager = new ArticleMementoManager();

        // 创建并输入文档内容
        Article article = new Article("标题", "内容");
        // 保存备忘录信息
        ArticleMemento articleMemento = article.saveToMemento();
        // 将备忘录信息设置到 备忘录管理者
        articleMementoManager.setArticleMemento(articleMemento);
        // 打印备忘录内容
        System.out.println("文档信息 : " + article.toString());

        // 修改文档内容
        article.setTitle("标题 2");
        article.setContent("内容 2");

        // 保存新的备忘录信息
        articleMemento = article.saveToMemento();
        // 将备忘录信息设置到 备忘录管理者
        articleMementoManager.setArticleMemento(articleMemento);
        // 打印备忘录内容
        System.out.println("文档信息 : " + article.toString());

        // 此时 ArticleMementoManager 中存储了 2 个存档
        // 存档 1 : Article{title='标题', content='内容', image='图片链接'}
        // 存档 2 : Article{title='标题 2', content='内容 2', image='图片链接 2'}

        // 使用备忘录回退
        // 先将栈顶的当前备忘录出栈 , 移除
        articleMementoManager.getArticleMemento();
        // 然后获取上一个备忘录 , 并设置到 Article 中
        article.undoFromMemento(articleMementoManager.getArticleMemento());
        // 打印备忘录内容
        System.out.println("文档信息 : " + article.toString());
    }

2.14、命令模式 

命令模式可使 命令的 发送者 和 接收者 完全解耦,发送者与接收者靠命令交互,把命令执行的逻辑类封装在命令类里。
命令模式 与 备忘录模式:通过 备忘录模式 保存 命令模式 的 命令历史记录,可获之前的命令。

/**
 * 命令执行 — 逻辑类
 */
public class Game {
    private String name;
    public Game(String name) {
        this.name = name;
    }
    public void open() {
        System.out.println(this.name + " 开放");
    }
    public void close() {
        System.out.println(this.name + " 关闭");
    }
}

/**
 * 命令接口
 */
public interface Command {
    /**
     * 执行命令方法
     */
    void execute();
}

/**
 * 开放命令
 */
public class OpenCommand implements Command{

    private Game game;

    public OpenCommand(Game game) {
        this.game = game;
    }

    @Override
    public void execute() {
        this.game.open();
    }
}

/**
 * 关闭命令
 */
public class CloseCommand implements Command {

    private Game game;

    public CloseCommand(Game game) {
        this.game = game;
    }
    @Override
    public void execute() {
        this.game.close();
    }
}

/**
 * 命令接收者
 */
public class Manager {
    /**
     * 存放命令
     */
    private ArrayList<Command> commands = new ArrayList<>();

    /**
     * 添加命令
     */
    public void addCommand(Command command) {
        commands.add(command);
    }

    /**
     * 执行命令
     */
    public void executeCommand() {
        for (Command command : commands) {
            // 逐个遍历执行命令
            command.execute();
        }
        // 命令执行完毕后 , 清空集合
        commands.clear();
    }
}

    public static void main(String[] args) {
        Game game01 = new Game("小游戏");
        Game game02 = new Game("大游戏");
        OpenCommand openCommand = new OpenCommand(game01);
        CloseCommand closeCommand = new CloseCommand(game02);

        // 发送命令
        Manager manager = new Manager();
        manager.addCommand(openCommand);
        manager.addCommand(closeCommand);

        // 执行命令
        manager.executeCommand();
    }

2.15、访问者模式 

2.16、调停者模式 

2.17、迭代器模式 

2.18、解释器模式 

09-14 11:02