# DesignPattern
设计模式（Design pattern）是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。

设计模式分为三种类型，共23种：

 - **创建型模式**：[单例模式](https://github.com/youlookwhat/DesignPattern#3-单例设计模式)、[抽象工厂模式](https://github.com/youlookwhat/DesignPattern#2-工厂模式)、[建造者模式](https://github.com/youlookwhat/DesignPattern#11-建造者模式)、[工厂模式](https://github.com/youlookwhat/DesignPattern#2-工厂模式)、[原型模式](https://github.com/youlookwhat/DesignPattern#12-原型模式)。
 - **结构型模式**：[适配器模式](https://github.com/youlookwhat/DesignPattern#5-适配器模式)、[桥接模式](https://github.com/youlookwhat/DesignPattern#15-桥接模式)、[装饰模式](https://github.com/youlookwhat/DesignPattern#7-装饰者模式)、[组合模式](https://github.com/youlookwhat/DesignPattern#16-组合模式)、[外观模式](https://github.com/youlookwhat/DesignPattern#8-外观模式)、[享元模式](https://github.com/youlookwhat/DesignPattern#13-享元模式)、[代理模式](https://github.com/youlookwhat/DesignPattern#14-代理模式)。
 - **行为型模式**：[模版方法模式](https://github.com/youlookwhat/DesignPattern#9-模板方法模式)、[命令模式](https://github.com/youlookwhat/DesignPattern#6-命令模式)、[迭代器模式](https://github.com/youlookwhat/DesignPattern#17-迭代器模式)、[观察者模式](https://github.com/youlookwhat/DesignPattern#1-观察者模式)、[中介者模式](https://github.com/youlookwhat/DesignPattern#18-中介者模式)、[备忘录模式](https://github.com/youlookwhat/DesignPattern#19-备忘录模式)、[解释器模式](https://github.com/youlookwhat/DesignPattern#20-解释器模式)、[状态模式](https://github.com/youlookwhat/DesignPattern#10-状态模式)、[策略模式](https://github.com/youlookwhat/DesignPattern#4-策略模式)、[责任链模式](https://github.com/youlookwhat/DesignPattern#21-责任链模式)、[访问者模式](https://github.com/youlookwhat/DesignPattern#22-访问者模式)。

> 参照Hongyang、菜鸟教程等处文章所写。如有错误欢迎指正，如有侵权，请联系我删除。

----


## Blog Catalogue：

 - 1.[ 设计模式 观察者模式(Observer Pattern) 以微信公众服务为例](http://blog.csdn.net/lmj623565791/article/details/24179699)

 - 2.[ 设计模式 工厂模式(Factory Pattern) 从卖肉夹馍说起](http://blog.csdn.net/lmj623565791/article/details/24460585)

 - 3.[ 设计模式 单例设计模式(Singleton Pattern) 完全解析](http://blog.csdn.net/dmk877/article/details/50311791)

 - 4.[ 设计模式 策略模式(Strategy Pattern) 以角色游戏为背景](http://blog.csdn.net/lmj623565791/article/details/24116745)

 - 5.[ 设计模式 适配器模式(Adapter Pattern) 以手机充电器为例](http://blog.csdn.net/lmj623565791/article/details/25833393)

 - 6.[ 设计模式 命令模式(Command Pattern) 管理智能家电](http://blog.csdn.net/lmj623565791/article/details/24602057)

 - 7.[ 设计模式 装饰者模式(Decorator Pattern) 带你重回传奇世界](http://blog.csdn.net/lmj623565791/article/details/24269409)

 - 8.[ 设计模式 外观模式(Facade Pattern) 一键电影模式](http://blog.csdn.net/lmj623565791/article/details/25837275)

 - 9.[ 设计模式 模版方法模式(Template Method Pattern) 展现程序员的一天](http://blog.csdn.net/lmj623565791/article/details/26276093)

 - 10.[ 设计模式 状态模式(State Pattern) 以自动售货机为例](http://blog.csdn.net/lmj623565791/article/details/26350617)
 
 - 11.[ 设计模式 建造者模式(Builder Pattern) 以造汽车买汽车为例](https://wiki.jikexueyuan.com/project/java-design-pattern/builder-pattern.html)

 - 12.[ 设计模式 原型模式(Prototype Pattern) 以获取多种形状为例](https://www.runoob.com/design-pattern/prototype-pattern.html)

 - 13.[ 设计模式 享元模式(Flyweight Pattern) 以随机获取多种形状为例](https://www.runoob.com/design-pattern/flyweight-pattern.html)

 - 14.[ 设计模式 代理模式(Proxy Pattern) 以获取磁盘中的图片为例](https://www.runoob.com/design-pattern/proxy-pattern.html)

 - 15.[ 设计模式 桥接模式(Bridge Pattern) 以画不同颜色的圆为例](https://www.runoob.com/design-pattern/bridge-pattern.html)

 - 16.[ 设计模式 组合模式(Composite Pattern) 以创建和打印员工的层次结构为例](https://www.runoob.com/design-pattern/composite-pattern.html)

 - 17.[ 设计模式 迭代器模式(Iterator Pattern) 以使用迭代器打印名字为例](https://www.runoob.com/design-pattern/iterator-pattern.html)

 - 18.[ 设计模式 中介者模式(Mediator Pattern) 以公共聊天室为例](https://www.runoob.com/design-pattern/mediator-pattern.html)

 - 19.[ 设计模式 备忘录模式(Memento Pattern) 以使用备忘录为例](https://www.runoob.com/design-pattern/memento-pattern.html)

 - 20.[ 设计模式 解释器模式(Interpreter Pattern) 以解释一句话为例](https://www.runoob.com/design-pattern/interpreter-pattern.html)

 - 21.[ 设计模式 责任链模式(Chain of Responsibility Pattern) 以Android Studio中打印日志为例](https://www.runoob.com/design-pattern/chain-of-responsibility-pattern.html)

 - 22.[ 设计模式 访问者模式(Visitor Pattern) 以显示计算机的组成部分为例](https://www.runoob.com/design-pattern/visitor-pattern.html)


## Source Code
> - [Observer](https://github.com/youlookwhat/DesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/observer)
> - [Factory](https://github.com/youlookwhat/DesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/factory)
> - [Singleton](https://github.com/youlookwhat/DesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/singleton)
> - [Strategy](https://github.com/youlookwhat/DesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/strategy)
> - [Adapter](https://github.com/youlookwhat/DesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/adapter)
> - [Command](https://github.com/youlookwhat/DesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/command)
> - [Decorator](https://github.com/youlookwhat/DesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/decorator)
> - [Facade](https://github.com/youlookwhat/DesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/facade)
> - [Template Method](https://github.com/youlookwhat/DesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/templatemethod)
> - [State](https://github.com/youlookwhat/DesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/state)
> - [Builder](https://github.com/youlookwhat/DesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/builder)
> - [Prototype](https://github.com/youlookwhat/DesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/prototype)
> - [Flyweight](https://github.com/youlookwhat/DesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/flyweight)
> - [Proxy](https://github.com/youlookwhat/DesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/proxy)
> - [Bridge](https://github.com/youlookwhat/DesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/bridge)
> - [Composite](https://github.com/youlookwhat/DesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/composite)
> - [Iterator](https://github.com/youlookwhat/DesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/iterator)
> - [Mediator](https://github.com/youlookwhat/DesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/mediator)
> - [Memento](https://github.com/youlookwhat/DesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/memento)
> - [Chain of Responsibility](https://github.com/youlookwhat/DesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/chainofresponsibility)
> - [Visitor](https://github.com/youlookwhat/DesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/visitor)

## Project Picture

![](https://raw.githubusercontent.com/youlookwhat/DesignPattern/master/image/ds1.png)
![](https://raw.githubusercontent.com/youlookwhat/DesignPattern/master/image/ds2.png)

## Pattern Analysis
### 1. 观察者模式
 >  定义了对象之间的一对多的依赖，这样一来，当一个对象改变时，它的所有的依赖者都会收到通知并自动更新。

 - 对于JDK或者Andorid中都有很多地方实现了观察者模式，比如XXXView.addXXXListenter ， 当然了 XXXView.setOnXXXListener不一定是观察者模式，因为观察者模式是一种一对多的关系，对于setXXXListener是1对1的关系，应该叫回调。

 - 专题接口：[Subject.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/observer/interfaces/Subject.java) ;  

	```java
	/**
	 * 注册一个观察者
	 */
	public void registerObserver(Observer observer);
	
	/**
	 * 移除一个观察者
	 */
	public void removeObserver(Observer observer);
	
	/**
	 * 通知所有观察者
	 */
	public void notifyObservers();
	```
 
 - 3D服务号的实现类：[ObjectFor3D.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/observer/classs/ObjectFor3D.java)

	```java
	@Override
    public void registerObserver(Observer observer) {
        observers.add(observer);
    }
    @Override
    public void removeObserver(Observer observer) {
        int index = observers.indexOf(observer);
        if (index >= 0) {
            observers.remove(index);
        }
    }
    @Override
    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(msg);
        }
    }
    /**
     * 主题更新信息
     */
    public void setMsg(String msg) {
        this.msg = msg;
        notifyObservers();
    }
	```
 
 - 所有观察者需要实现此接口:[Observer.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/observer/interfaces/Observer.java)

	```java
	 public ObserverUser1(Subject subject) {
        subject.registerObserver(this);
    }
    @Override
    public void update(String msg) {
        Log.e("-----ObserverUser1 ", "得到 3D 号码:" + msg + ", 我要记下来。");
    }
	```

- 最后测试：[ObserverActivity.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/observer/ObserverActivity.java)
	
	```java
	// 创建服务号
    objectFor3D = new ObjectFor3D();
    // 创建两个订阅者
    observerUser1 = new ObserverUser1(objectFor3D);
    observerUser2 = new ObserverUser2(objectFor3D);
    // 两个观察者,发送两条信息
    objectFor3D.setMsg("201610121 的3D号为:127");
    objectFor3D.setMsg("20161022 的3D号为:000");
	```
	

### 2. 工厂模式
简单列一下这个模式的家族：

- **1、静态工厂模式**

	- 这个最常见了，项目中的辅助类，TextUtil.isEmpty等，类+静态方法。

- **2、简单工厂模式（店里买肉夹馍）**
	- 定义：通过专门定义一个类来负责创建其他类的实例，被创建的实例通常都具有共同的父类。
	- 根据类型直接创建肉夹馍：[SimpleRoujiaMoFactory.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/factory/jdgc/SimpleRoujiaMoFactory.java)
	
	```java
	public RoujiaMo creatRoujiaMo(String type) {
        RoujiaMo roujiaMo = null;
        switch (type) {
            case "Suan":
                roujiaMo = new ZSuanRoujiaMo();
                break;
            case "La":
                roujiaMo = new ZLaRoujiaMo();
                break;
            case "Tian":
                roujiaMo = new ZTianRoujiaMo();
                break;
            default:// 默认为酸肉夹馍
                roujiaMo = new ZSuanRoujiaMo();
                break;
        }
        return roujiaMo;
    }
	```

- **3、工厂方法模式（开分店）**
	-  定义：定义一个创建对象的接口，但由子类决定要实例化的类是哪一个。工厂方法模式把类实例化的过程推迟到子类。
	-  对比定义：
  	 - 1、定义了创建对象的一个接口：public abstract RouJiaMo sellRoujiaMo(String type);
 	 - 2、由子类决定实例化的类，可以看到我们的馍是子类生成的。
 - 提供创建肉夹馍店抽象方法：[RoujiaMoStore.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/factory/gcff/RoujiaMoStore.java)

	 ```java
 	public abstract RoujiaMo sellRoujiaMo(String type);
	 ```
 
 - 具体实现抽象方法：[XianRoujiaMoStore.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/factory/gcff/XianRoujiaMoStore.java)
 - 分店依旧使用简单工厂模式：[XianSimpleRoujiaMoFactory.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/factory/gcff/XianSimpleRoujiaMoFactory.java)

- **4、抽象工厂模式（使用官方提供的原料）**
	 - 定义：提供一个接口，用于创建相关的或依赖对象的家族，而不需要明确指定具体类。
	 - 对比定义：
	 	- 1、提供一个接口：public interface RouJiaMoYLFactroy
	 	- 2、用于创建相关的或依赖对象的家族 public Meat createMeat();public YuanLiao createYuanliao();我们接口用于创建一系列的原材料。
	 - 创建用于提供原料的接口工厂：[RoujiaMoYLFactory.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/factory/cxgc/RoujiaMoYLFactory.java)
	 - 各自分店实现接口，完成原料提供：[XianRoujiaMoYLFoctory.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/factory/cxgc/XianRoujiaMoYLFoctory.java)
	 - 准备时，使用官方的原料：[RoujiaMo.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/factory/cxgc/RoujiaMo.java)
	 
	 ```java
	 /**
     * 准备工作
     */
    public void prepare(RoujiaMoYLFactory roujiaMoYLFactory) {
        	Meet meet = roujiaMoYLFactory.creatMeet();
        	YuanLiao yuanLiao = roujiaMoYLFactory.creatYuanLiao();
        	Log.e("---RoujiaMo:", "使用官方的原料 ---" + name + ": 揉面-剁肉-完成准备工作 yuanLiao:"+meet+"yuanLiao:"+yuanLiao);
    }
	 ```

### 3. 单例设计模式
> 单例模式主要是为了避免因为创建了多个实例造成资源的浪费，且多个实例由于多次调用容易导致结果出现错误，而**使用单例模式能够保证整个应用中有且只有一个实例**。
 
 - 定义：只需要三步就可以保证对象的唯一性
   - (1) 不允许其他程序用new对象
   - (2) 在该类中创建对象
   - (3) 对外提供一个可以让其他程序获取该对象的方法
 - 对比定义：
   - (1) 私有化该类的构造函数
   - (2) 通过new在本类中创建一个本类对象
   - (3) 定义一个公有的方法，将在该类中所创建的对象返回

- 饿汉式[可用]：[SingletonEHan.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/singleton/ehan/SingletonEHan.java)
- 含懒汉式[双重校验锁 推荐用]：[SingletonLanHan.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/singleton/lanhan/SingletonLanHan.java)

 ```java
	 private SingletonLanHan() {}
	 private static SingletonLanHan singletonLanHanFour;
	 public static SingletonLanHan getSingletonLanHanFour() {
		    if (singletonLanHanFour == null) {
			synchronized (SingletonLanHan.class) {
			    if (singletonLanHanFour == null) {
				singletonLanHanFour = new SingletonLanHan();
			    }
			}
		    }
		    return singletonLanHanFour;
	}
    
 ```

- 内部类[推荐用]：[SingletonIn.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/singleton/inclass/SingletonIn.java)
- 枚举[推荐用]：[SingletonEnum.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/singleton/enums/SingletonEnum.java)


### 4. 策略模式
> 策略模式：定义了算法族，分别封装起来，让它们之间可相互替换，此模式让算法的变化独立于使用算法的客户。

 - 以创建游戏角色为例子：
 	 - 最初的游戏角色的父类：[Role.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/strategy/old/Role.java)
 	 - 发现有重复代码后，重构后的父类：[Role.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/strategy/better/Role.java)
 - 总结：
	 - 1、封装变化（把可能变化的代码封装起来）
	 - 2、多用组合，少用继承（我们使用组合的方式，为客户设置了算法）
	 - 3、针对接口编程，不针对实现（对于Role类的设计完全的针对角色，和技能的实现没有关系）
 - 最后测试：创建角色：
 
 ```java
 RoleA roleA = new RoleA("---A");
 roleA.setiDisplayBehavior(new DisplayYZ())
       .setiAttackBehavior(new AttackXL())
       .setiDefendBehavior(new DefendTMS())
       .setiRunBehavior(new RunJCTQ());
 roleA.display();// 样子
 roleA.attack();// 攻击
 roleA.run();// 逃跑
 roleA.defend();// 防御
 ```

### 5. 适配器模式
> 定义：将一个类的接口转换成客户期望的另一个接口，适配器让原本接口不兼容的类可以相互合作。这个定义还好，说适配器的功能就是把一个接口转成另一个接口。

 - 以充电器为实例: 手机充电器一般都是5V左右吧，咱天朝的家用交流电压220V，所以手机充电需要一个适配器（降压器）
 - 一部手机: [Mobile.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/adapter/Mobile.java)
 - 手机依赖一个提供5V电压的接口: [V5Power.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/adapter/V5Power.java)
 - 我们拥有的是220V家用交流电: [V220Power.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/adapter/V220Power.java)
 - **适配器，完成220V转5V的作用**：[V5PowerAdapter.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/adapter/V5PowerAdapter.java)
 - 最后测试：给手机冲个电：

	```java
	Mobile mobile = new Mobile();
   V5Power v5Power = new V5PowerAdapter(new V200Power());
   mobile.inputPower(v5Power);
	```

### 6. 命令模式
> 定义：将“请求”封装成对象，以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。(简化: 将请求封装成对象，将动作请求者和动作执行者解耦。)

 - 需求：最近智能家电很火热，假设现在有电视、电脑、电灯等家电，现在需要你做个遥控器控制所有家电的开关，要求做到每个按钮对应的功能供用户个性化，对于新买入家电要有非常强的扩展性。
 - 1、家电的API：[Door.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/command/Door.java)
 - 2、把命令封装成类： 
 	- 统一的命令接口：[Command.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/command/Command.java)
 	- 家电实现该接口：[DoorOpenCommand.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/command/DoorOpenCommand.java)
 - 3、遥控器：[ControlPanel.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/command/ControlPanel.java)
 - 4、定义一个命令，可以干一系列的事情：[QuickCommand.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/command/QuickCommand.java)
  
  ```java
  QuickCommand quickCloseCommand = new QuickCommand(new Command[]{new LightOffCommand(light), new ComputerOffCommand(computer), new DoorCloseCommand(door)});
  controlPanel.setCommands(6, quickOpenCommand);
  controlPanel.keyPressed(6);
  ```
  
 - 5、遥控器面板执行：[CommandActivity.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/command/CommandActivity.java)
 
 ```java
 controlPanel.setCommands(0, new DoorOpenCommand(door));// 开门
 controlPanel.keyPressed(0);
 ```

### 7. 装饰者模式
> 装饰者模式：若要扩展功能，装饰者提供了比集成更有弹性的替代方案，动态地将责任附加到对象上。

 - 先简单描述下装饰者模式发挥作用的地方，当我们设计好了一个类，我们需要给这个类添加一些辅助的功能，并且不希望改变这个类的代码，这时候就是装饰者模式大展雄威的时候了。这里还体现了一个**原则：类应该对扩展开放，对修改关闭。**
 
 - 需求：设计游戏的装备系统，基本要求，要可以计算出每种装备在镶嵌了各种宝石后的攻击力和描述：
 - 1、装备的超类：[IEquip.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/decorator/IEquip.java)
 - 2、各个装备的实现类：
   - eg：**武器**的实现类: [ArmEquip.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/decorator/equip/ArmEquip.java)

- 3、装饰品的超类（装饰品也属于装备）：[IEquipDecorator.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/decorator/gem/IEuipDecorator.java)
- 4、装饰品的实现类：
  - eg：**蓝宝石**的实现类(可累加): [BlueGemDecorator.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/decorator/gem/BlueGemDecorator.java)

- 5、最后测试：计算攻击力和查看描述：

	```java
	Log.e("---", "一个镶嵌2颗红宝石,1颗蓝宝石的靴子: ");
    IEquip iEquip = new RedGemDecorator(new RedGemDecorator(new BlueGemDecorator(new ShoeEquip())));
    Log.e("---", "攻击力:" + iEquip.caculateAttack());
    Log.e("---", "描述语:" + iEquip.description());
	```

### 8. 外观模式
> 定义：提供一个统一的接口，用来访问子系统中的一群接口，外观定义了一个高层的接口，让子系统更容易使用。**其实就是为了方便客户的使用，把一群操作，封装成一个方法。**

 - 需求：我比较喜欢看电影，于是买了投影仪、电脑、音响、设计了房间的灯光、买了爆米花机，然后我想看电影的时候，我需要一键观影和一键关闭。
 - 每个设备类的开关等操作：
  - eg: 爆米花机：[PopcornPopper.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/facade/device/PopcornPopper.java)
 - 电影院类：[HomeTheaterFacade.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/facade/theater/HomeTheaterFacade.java)
 	
	```java
	/**
     * 一键观影
     */
    public void watchMovie() {
        computer.on();
        light.down();
        popcornPopper.on();
        popcornPopper.makePopcorn();
        projector.on();
        projector.open();
        player.on();
        player.make3DListener();
    }
	```

- 最后测试：一键观影：

	```java
	new HomeTheaterFacade(computer, light, player, popcornPopper, projector).watchMovie();
	```

### 9. 模板方法模式
> 定义：定义了一个算法的骨架，而将一些步骤延迟到子类中，模版方法使得子类可以在不改变算法结构的情况下，重新定义算法的步骤。

- 需求：简单描述一下：本公司有程序猿、测试、HR、项目经理等人，下面使用模版方法模式，记录下所有人员的上班情况
- 模板方法模式中的三类角色
 - 1、具体方法(Concrete Method)
 - 2、抽象方法(Abstract Method)
 - 3、钩子方法(Hook Method)
- 工人的超类：[Worker.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/templatemethod/Worker.java)

	```java
	// 具体方法
    public final void workOneDay() {
        Log.e("workOneDay", "-----------------work start----------------");
        enterCompany();
        work();
        exitCompany();
        Log.e("workOneDay", "-----------------work end----------------");
    }
    // 工作  抽象方法
    public abstract void work();
    // 钩子方法
    public boolean isNeedPrintDate() {
        return false;
    }
    private void exitCompany() {
        if (isNeedPrintDate()) {
            Log.e("exitCompany", "---" + new Date().toLocaleString() + "--->");
        }
        Log.e("exitCompany", name + "---离开公司");
    }
	```
- 程序员实现类（可得知时间）：[ITWorker.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/templatemethod/worker/ITWorker.java)
	
	```java
	/**
     * 重写父类的此方法,使可以查看离开公司时间
     */
    @Override
    public boolean isNeedPrintDate() {
        return true;
    }
	```
- 最后测试：
	- 查看所有人员的工作情况：
	
		```java
		QAWorker qaWorker = new QAWorker("测试人员");
	    qaWorker();
	    HRWorker hrWorker = new HRWorker("莉莉姐");
	    hrWorker.workOneDay();
	    ...
		```
	- 查看程序猿离开公司的时间:
		
		```java
		ITWorker itWorker = new ITWorker("jingbin");
       itWorker.workOneDay();
		```

### 10. 状态模式
> 定义：允许对象在内部状态改变时改变它的行为，对象看起来好像修改了它的类。

 - 定义又开始模糊了，理一下，当对象的内部状态改变时，它的行为跟随状态的改变而改变了，看起来好像重新初始化了一个类似的。

 - 需求：以自动售货机为例（有已投币、未投币等状态和投币、退币等方法）
 - 最初实现待改进的售货机：[VendingMachine.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/state/old/VendingMachine.java)
 - 改进后的售货机（更具有延展性）:[VendingMachineBetter.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/state/better/VendingMachineBetter.java)

	```java
	// 放钱
    public void insertMoney() {
        currentState.insertMoney();
    }
    // 退钱
    public void backMoney() {
        currentState.backMoney();
    }
    // 转动曲柄
    public void turnCrank() {
        currentState.turnCrank();
        if (currentState == soldState || currentState == winnerState) {
            currentState.dispense();//两种情况会出货
        }
    }
    // 出商品
    public void dispense() {
        Log.e("VendingMachineBetter", "---发出一件商品");
        if (count > 0) {
            count--;
        }
    }
    // 设置对应状态
    public void setState(State state) {
        this.currentState = state;
    }
	```


 - 状态的接口：[State.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/state/better/State.java)
 - 对应状态的接口实现类：
 	- eg: 中奖状态：[WinnerState.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/state/better/WinnerState.java)
 	- eg: 售卖状态：[SoldState.java](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/state/better/SoldState.java)
 		
- 改进后的售货机测试：
	
	```java
	// 初始化售货机,且里面有3个商品
   VendingMachineBetter machineBetter = new VendingMachineBetter(3);
   machineBetter.insertMoney();
   machineBetter.turnCrank();
	```


### 11. 建造者模式
> 建造模式是对象的创建模式。建造模式可以将一个产品的内部表象（internal representation）与产品的生产过程分割开来，从而可以使一个建造过程生成具有不同的内部表象的产品对象。

 - 需求：用户去汽车店购买汽车。
 - 分析：汽车店根据每个用户的需求提取对应汽车
 - 建造者超类：[Builder](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/builder/Builder.java)

	```java
	public abstract class Builder {
	
	    public abstract void setPart(String name, String type);
	
	    public abstract Product getProduct();
	}
	```
 
- 建造者对应实现类：[ConcreteBuilder](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/builder/ConcreteBuilder.java)

	```java
	public class ConcreteBuilder extends Builder {

	    private Product product = new Product();
	
	    @Override
	    public void setPart(String name, String type) {
	        product.setName(name);
	        product.setType(type);
	    }
	
	    @Override
	    public Product getProduct() {
	        return product;
	    }
	}
	```

- 店长[Director](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/builder/Director.java)取汽车：

	```java
	// 店长
	Director director = new Director();
	// 得到宝马汽车，内部实现提取宝马汽车的详情操作
	Product product = director.getBProduct();
	// 展示汽车信息
	product.showProduct();
	```

### 12. 原型模式
> 原型模式是用于创建重复的对象，同时又能保证性能。这种类型的设计模式属于创建型模式，它提供了一种创建对象的最佳方式。

这种模式是实现了一个原型接口，该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时，则采用这种模式。例如，一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象，在下一个请求时返回它的克隆，在需要的时候更新数据库，以此来减少数据库调用。

以获取多种形状为例，共分四步：

- 1、创建一个实现了 Cloneable 接口的抽象类。[Shape](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/prototype/Shape.java)（implements Cloneable）

	```java
	public abstract class Shape implements Cloneable {
	
	    private String id;
	    protected String type;
	
	    public abstract void draw();
	
	    public String getId() {
	        return id;
	    }
	
	    public void setId(String id) {
	        this.id = id;
	    }
	
	    @Override
	    public Object clone() {
	        Object object = null;
	        try {
	            object = super.clone();
	        } catch (CloneNotSupportedException e) {
	            Log.e("--", e.getMessage());
	        }
	        return object;
	    }
	}
	```

- 2、创建扩展了上面抽象类的实体类。[Circle](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/prototype/shapeimpl/Circle.java)、[Rectangle](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/prototype/shapeimpl/Rectangle.java)、[Square](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/prototype/shapeimpl/Square.java)

	```java
	public class Circle extends Shape {
	
	    public Circle() {
	        type = "Circle";
	    }
	
	    @Override
	    public void draw() {
	        Log.e("---", "Inside Circle::draw() method.");
	    }
	    
	}
	```

- 3、创建一个类，从数据库获取实体类，并把它们存储在一个 Hashtable 中。[ShapeCache](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/prototype/ShapeCache.java)

	```java
	public class ShapeCache {
	
	    private static Hashtable<String, Shape> shapeMap = new Hashtable<String, Shape>();
	
	    public static Shape getShape(String shapeId) {
	        Shape shapeCache = shapeMap.get(shapeId);
	        return (Shape) shapeCache.clone();
	    }
	
	    // 对每种形状都运行数据库查询，并创建该形状
	    // shapeMap.put(shapeKey, shape);
	    // 例如，我们要添加三种形状
	    public static void loadCache() {
	        Circle circle = new Circle();
	        circle.setId("1");
	        shapeMap.put(circle.getId(), circle);
	
	        Rectangle rectangle = new Rectangle();
	        rectangle.setId("2");
	        shapeMap.put(rectangle.getId(), rectangle);
	
	        Square square = new Square();
	        square.setId("3");
	        shapeMap.put(square.getId(), square);
	    }
	}
	```

- 4、使用 ShapeCache 类来获取存储在 Hashtable 中的形状的克隆。

	```java
	// 使用 ShapeCache 类来获取存储在 Hashtable 中的形状的克隆。
   ShapeCache.loadCache();
   Shape shapeCache1 = ShapeCache.getShape("1");
   Shape shapeCache2 = ShapeCache.getShape("2");
   Shape shapeCache3 = ShapeCache.getShape("3");
	```

### 13. 享元模式
> 主要用于减少创建对象的数量，以减少内存占用和提高性能。这种类型的设计模式属于结构型模式，它提供了减少对象数量从而改善应用所需的对象结构的方式。

享元模式尝试重用现有的同类对象，如果未找到匹配的对象，则创建新对象。我们将通过创建 5 个对象来画出 20 个分布于不同位置的圆来演示这种模式。由于只有 5 种可用的颜色，所以 color 属性被用来检查现有的 Circle 对象。 

 - **主要解决**：在有大量对象时，有可能会造成内存溢出，我们把其中共同的部分抽象出来，如果有相同的业务请求，直接返回在内存中已有的对象，避免重新创建。

以随机获取多种形状为例，共分四步：

 - 1、创建一个接口。

	```java
	public interface Shape {
	    void draw();
	}
	```

 - 2、创建实现接口的实体类。

	```java
	public class Circle implements Shape {
	
	    private String color;
	    private int x;
	    private int y;
	    private int radius;
	
	    public Circle(String color) {
	        this.color = color;
	    }
	
	    public void setX(int x) {
	        this.x = x;
	    }
	
	    public void setY(int y) {
	        this.y = y;
	    }
	
	    public void setRadius(int radius) {
	        this.radius = radius;
	    }
	
	    @Override
	    public void draw() {
	        Log.e("---", "Circle: Draw() [Color : " + color
	                + ", x : " + x + ", y :" + y + ", radius :" + radius);
	    }
	}
	```


 - 3、创建一个工厂，生成基于给定信息的实体类的对象。

	```java
	public class ShapeFactory {
	
	    private static final HashMap<String, Shape> circleMap = new HashMap<String, Shape>();
	
	    public static Shape getShape(String color) {
	        Shape shape = circleMap.get(color);
	        if (shape == null) {
	            shape = new Circle(color);
	            circleMap.put(color, shape);
	            Log.e("getShape", "Creating circle of color : " + color);
	        }
	        return shape;
	    }
	
	}
	```


 - 4、使用该工厂，通过传递颜色信息来获取实体类的对象。

	```java
    for (int i = 0; i < 20; i++) {
        Circle circle = (Circle) ShapeFactory.getShape(getRandomColor());
        circle.setX(getRandomX());
        circle.setY(getRandomY());
        circle.setRadius(100);
        circle.draw();
    }
	```

### 14. 代理模式
> 一个类代表另一个类的功能。在代理模式中，我们创建具有现有对象的对象，以便向外界提供功能接口。可以理解为内存中没有这个对象就创建，有就直接返回这个对象。

 - **主要解决**：在直接访问对象时带来的问题，比如说：要访问的对象在远程的机器上。在面向对象系统中，有些对象由于某些原因（比如对象创建开销很大，或者某些操作需要安全控制，或者需要进程外的访问），直接访问会给使用者或者系统结构带来很多麻烦，我们可以在访问此对象时加上一个对此对象的访问层。

以获取磁盘中的图片为例，总共分三步：

 - 1、创建一个接口。

	```java
	public interface Image {
	   void display();
	}
	```

 - 2、创建实现接口的实体类 RealImage。对应代理类：ProxyImage。

	```java
	public class RealImage implements Image {
	
	    private String fileName;
	
	    public RealImage(String fileName) {
	        this.fileName = fileName;
	        loadFromDisk(fileName);
	    }
	
	    private void loadFromDisk(String fileName) {
	        Log.e("RealImage", "loading " + fileName);
	    }
	
	    @Override
	    public void display() {
	        Log.e("RealImage", "Displaying " + fileName);
	    }
	}
	```

	```java
	public class ProxyImage implements Image {
	
	    private String fileName;
	    private RealImage realImage;
	
	    public ProxyImage(String fileName) {
	        this.fileName = fileName;
	    }
	
	    @Override
	    public void display() {
	        if (realImage == null) {
	            realImage = new RealImage(fileName);
	        }
	        realImage.display();
	    }
	}
	```

 - 3、当被请求时，使用 ProxyImage 来获取 RealImage 类的对象。

	```java
	Image image = new ProxyImage("test_10mb.png");
	// 第一次是new的，图像从磁盘加载
   image.display();
   // 第二次取缓存，图像不需要从磁盘加载
   image.display();
	```

### 15. 桥接模式
> 桥接（Bridge）是用于把抽象化与实现化解耦，使得二者可以独立变化。这种类型的设计模式属于结构型模式，它通过提供抽象化和实现化之间的桥接结构，来实现二者的解耦。

 - **主要解决**：在有多种可能会变化的情况下，用继承会造成类爆炸问题，扩展起来不灵活。

以画不同颜色的圆为例，实现共分五步：

 - 1、创建桥接实现接口。

	```java
	public interface DrawAPI {
	    void drawCircle(int radius, int x, int y);
	}
	```

 - 2、创建实现了 DrawAPI 接口的实体桥接实现类。[RedCircle](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/bridge/RedCircle.java)、[GreenCircle](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/bridge/GreenCircle.java)

	```java
	public class RedCircle implements DrawAPI {
	
	    @Override
	    public void drawCircle(int radius, int x, int y) {
	        Log.e("---", "Drawing Circle[ color: red, radius: "
	                + radius + ", x: " + x + ", " + y + "]");
	    }
	}
	```

 - 3、使用 DrawAPI 接口创建抽象类 [Shape](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/bridge/Shape.java)。

	```java
	public abstract class Shape {
	
	    protected DrawAPI drawAPI;
	
	    protected Shape(DrawAPI drawAPI) {
	        this.drawAPI = drawAPI;
	    }
	
	    public abstract void draw();
	}
	```

 - 4、创建实现了 Shape 接口的实体类。

	```java
	public class Circle extends Shape {
	
	    private int x, y, radius;
	
	    protected Circle(int x, int y, int radius, DrawAPI drawAPI) {
	        super(drawAPI);
	        this.x = x;
	        this.y = y;
	        this.radius = radius;
	    }
	
	    @Override
	    public void draw() {
	        drawAPI.drawCircle(radius, x, y);
	    }
	}
	```

 - 5、使用 Shape 和 DrawAPI 类画出不同颜色的圆。

	```java
    // 画红圆
    Circle circle = new Circle(10, 10, 100, new RedCircle());s
    circle.draw();
    // 画绿圆
    Circle circle2 = new Circle(20, 20, 100, new GreenCircle());
    circle2.draw();
	```

### 16. 组合模式
> 又叫部分整体模式，是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象，用来表示部分以及整体层次。这种类型的设计模式属于结构型模式，它创建了对象组的树形结构。

 - **主要解决**：它在我们树型结构的问题中，模糊了简单元素和复杂元素的概念，客户程序可以像处理简单元素一样来处理复杂元素，从而使得客户程序与复杂元素的内部结构解耦。

以创建和打印员工的层次结构为例，最小单元示例：

 - 1、创建 Employee 类，该类带有 Employee 对象的列表。

	```java
	public class Employee {
	
	    private String name;
	    // 部门
	    private String dept;
	    // 工资
	    private int salary;
	    // 员工 list
	    private List<Employee> subordinates;
	
	    public Employee(String name, String dept, int salary) {
	        this.name = name;
	        this.dept = dept;
	        this.salary = salary;
	        this.subordinates = new ArrayList<Employee>();
	    }
	
	    public void add(Employee e) {
	        subordinates.add(e);
	    }
	
	    public void remove(Employee e) {
	        subordinates.remove(e);
	    }
	
	    public List<Employee> getSubordinates() {
	        return subordinates;
	    }
	
	    @Override
	    public String toString() {
	        return "Employee{" +
	                "name='" + name + '\'' +
	                ", dept='" + dept + '\'' +
	                ", salary=" + salary +
	                ", subordinates=" + subordinates +
	                '}';
	    }
	}
	```

 - 2.使用 Employee 类来创建和打印员工的层次结构。

	```java
    final Employee ceo = new Employee("John", "CEO", 30000);

    Employee headSales = new Employee("Robert", "Head sales", 20000);

    Employee headMarketing = new Employee("Michel", "Head Marketing", 20000);

    Employee clerk1 = new Employee("Laura", "Marketing", 10000);
    Employee clerk2 = new Employee("Bob", "Marketing", 10000);

    Employee salesExecutive1 = new Employee("Richard", "Sales", 10000);
    Employee salesExecutive2 = new Employee("Rob", "Sales", 10000);

    ceo.add(headSales);
    ceo.add(headMarketing);

    headSales.add(salesExecutive1);
    headSales.add(salesExecutive2);

    headMarketing.add(clerk1);
    headMarketing.add(clerk2);
    
    Log.e("---", ceo.toString());
    
    // 打印
    /*
     * Employee{name='John', dept='CEO', salary=30000,
     * subordinates=[Employee{name='Robert', dept='Head sales', salary=20000,
     * subordinates=[
     * Employee{name='Richard', dept='Sales', salary=10000, subordinates=[]},
     * Employee{name='Rob', dept='Sales', salary=10000, subordinates=[]}]},
     * Employee{name='Michel', dept='Head Marketing', salary=20000,
     * subordinates=[Employee{name='Laura', dept='Marketing', salary=10000, subordinates=[]},
     * Employee{name='Bob', dept='Marketing', salary=10000, subordinates=[]}]}]}
     */
	```

### 17. 迭代器模式
>  Java 和 .Net 编程环境中非常常用的设计模式。这种模式用于顺序访问集合对象的元素，不需要知道集合对象的底层表示。迭代器模式属于行为型模式。

 - **主要解决**：不同的方式来遍历整个整合对象。

以使用迭代器打印名字为例，总共分三步：
 
 - 1、创建接口:

	```java
	public interface Iterator {
	
	    public boolean hasNext();
	
	    public Object next();
	}
	```

	```java
	public interface Container {
	    public Iterator getIterator();
	}
	```

- 2、创建实现了 Container 接口的实体类。该类有实现了 Iterator 接口的内部类 NameIterator。

	```java
	public class NameRepository implements Container {
	
	    private String names[] = {"John", "jingbin", "youlookwhat", "lookthis"};
	
	    @Override
	    public Iterator getIterator() {
	        return new NameIterator();
	    }
	
	    private class NameIterator implements Iterator {
	
	        int index;
	
	        @Override
	        public boolean hasNext() {
	            if (index < names.length) {
	                return true;
	            }
	            return false;
	        }
	
	        @Override
	        public Object next() {
	            if (hasNext()) {
	                return names[index++];
	            }
	            return null;
	        }
	    }
	
	}
	```

- 3、使用 NameRepository 来获取迭代器，并打印名字。

	```java
    NameRepository nameRepository = new NameRepository();
    for (Iterator iterator = nameRepository.getIterator(); iterator.hasNext(); ) {
        String name = (String) iterator.next();
        Log.e("---", name);
        /*
         * /---: John
         * /---: jingbin
         * /---: youlookwhat
         * /---: lookthis
         */
    }
	```

### 18. 中介者模式
> 用来降低多个对象和类之间的通信复杂性。这种模式提供了一个中介类，该类通常处理不同类之间的通信，并支持松耦合，使代码易于维护。中介者模式属于行为型模式。

 - **主要解决**：对象与对象之间存在大量的关联关系，这样势必会导致系统的结构变得很复杂，同时若一个对象发生改变，我们也需要跟踪与之相关联的对象，同时做出相应的处理。

以公共聊天室为例，最小单元示例步骤：

 - 1、创建中介类。

	```java
	public class CharRoom {
	    public static void showMessage(User user, String message) {
	        Log.e("---", new Date().toString()
	                + " [" + user.getName() + "] : " + message);
	    }
	}
	```

 - 2、创建 user 类。

	```java
	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) {
	    	  // 使用中介类
	        CharRoom.showMessage(this, message);
	    }
	}
	```

 - 3、使用 User 对象来显示他们之间的通信。

	```java
        User jingbin = new User("jingbin");
        jingbin.sendMessage("Hi~ youlookwhat!");
        //---: Sun Feb 02 08:11:47 GMT+00:00 2020 [jingbin] : Hi~ youlookwhat!
        
        User jingbin = new User("youlookwhat");
        jingbin.sendMessage("Hi~ jingbin!");
        //---: Sun Feb 02 08:11:49 GMT+00:00 2020 [youlookwhat] : Hi~ jingbin!
	```

### 19. 备忘录模式
> 保存一个对象的某个状态，以便在适当的时候恢复对象。备忘录模式属于行为型模式。

- **主要解决**：所谓备忘录模式就是在不破坏封装的前提下，捕获一个对象的内部状态，并在该对象之外保存这个状态，这样可以在以后将对象恢复到原先保存的状态。

以使用备忘录为例，最小单元步骤：

 - 1、创建 备忘录 Memento 类。

	```java
	public class Memento {
	
		private String state;
		
		public Memento(String state) {
		    this.state = state;
		}
		
		public String getState() {
		    return state;
		}
		
		public void setState(String state) {
		    this.state = state;
		}
	}
	```

 - 2、创建 Originator 类。

	```java
	public class Originator {
	
	    private String state;
	
	    public String getState() {
	        return state;
	    }
	
	    public void setState(String state) {
	        this.state = state;
	    }
	
	    public Memento setSateToMemento() {
	        return new Memento(state);
	    }
	
	    public String getStateFromMemento(Memento memento) {
	        return memento.getState();
	    }
	}
	```

 - 3、创建 CareTaker 类。

	```java
	public class CareTaker {
	
	    private List<Memento> mementoList = new ArrayList<Memento>();
	
	    public void add(Memento memento) {
	        mementoList.add(memento);
	    }
	
	    public Memento get(int index) {
	        return mementoList.get(index);
	    }
	}
	```
 
 - 4、使用 CareTaker 和 Originator 对象。

	```java
   // 管理者
    CareTaker careTaker = new CareTaker();

    Originator originator = new Originator();
    originator.setState("State #1");
    originator.setState("State #2");

    // 保存状态
    careTaker.add(originator.setSateToMemento());

    originator.setState("State #3");

    // 保存状态
    careTaker.add(originator.setSateToMemento());

    originator.setState("State #4");

    Log.e("---", "Current State: " + originator.getState());
    // 得到保存的状态
    String fromMemento1 = originator.getStateFromMemento(careTaker.get(0));
    Log.e("---", "First Saved State: " + fromMemento1);
    String fromMemento2 = originator.getStateFromMemento(careTaker.get(1));
    Log.e("---", "Second Saved State: " + fromMemento2);

    /*
     * /---: Current State: State #4
     * /---: First Saved State: State #2
     * /---: Second Saved State: State #3
     */
	```

### 20. 解释器模式
> 提供了评估语言的语法或表达式的方式，它属于行为型模式。这种模式实现了一个表达式接口，该接口解释一个特定的上下文。这种模式被用在 SQL 解析、符号处理引擎等。

 - **主要解决**：对于一些固定文法构建一个解释句子的解释器。

以解释一句话为例，最小单元步骤：

 - 1、创建一个表达式接口 Expression。

	```java
	public interface Expression {
	    public boolean interpreter(String content);
	}
	```

 - 2、创建实现了上述接口的实体类。TerminalExpression、OrExpression、AndExpression。

	```java
	public class TerminalExpression implements Expression {
	
		private String data;
		
		public TerminalExpression(String data) {
		    this.data = data;
		}
		
		@Override
		public boolean interpreter(String content) {
		   // 是包含判断
		    return content.contains(data);
		}
	}
	```

	```java
	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 interpreter(String content) {
	        return expression1.interpreter(content) || expression2.interpreter(content);
	    }
	}
	```

	```java
	public class AndExpression implements Expression {
	
	    private Expression expression1;
	    private Expression expression2;
	
	    public AndExpression(Expression expression1, Expression expression2) {
	        this.expression1 = expression1;
	        this.expression2 = expression2;
	    }
	
	    @Override
	    public boolean interpreter(String content) {
	        return expression1.interpreter(content) && expression2.interpreter(content);
	    }
	}
	```

 - 3、使用 Expression 类来创建规则，并解析它们。

	```java
    /**
     * 规则：jingbin 和 youlookwhat 是男性
     */
    public static Expression getMaleExpression() {
        TerminalExpression jingbin = new TerminalExpression("jingbin");
        TerminalExpression youlookwhat = new TerminalExpression("youlookwhat");
        return new OrExpression(jingbin, youlookwhat);
    }

    /**
     * 规则：Julie 是一个已婚的女性
     */
    public static Expression getMarriedWomanExpression() {
        TerminalExpression julie = new TerminalExpression("Julie");
        TerminalExpression married = new TerminalExpression("Married");
        return new AndExpression(julie, married);
    }

	Expression maleExpression = getMaleExpression();
	// jingbin is male: true
	Log.e("---", "jingbin is male: " + maleExpression.interpreter("jingbin"));

    Expression womanExpression = getMarriedWomanExpression();
    // Julie is married woman: true
    Log.e("---", "Julie is married woman: " + womanExpression.interpreter("Married Julie"));

	```


### 21. 责任链模式
> 责任链模式（Chain of Responsibility Pattern）为请求创建了一个接收者对象的链。这种模式给予请求的类型，对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。**在这种模式中，通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求，那么它会把相同的请求传给下一个接收者，依此类推。**

 - **主要解决**：职责链上的处理者负责处理请求，客户只需要将请求发送到职责链上即可，无须关心请求的处理细节和请求的传递，所以职责链将请求的发送者和请求的处理者解耦了。

以Android Studio中打印日志为例，最小单元步骤：

 - 1、创建抽象的记录器类 AbstractLogger。

	```java
	public abstract class AbstractLogger {
	
	    public static int INFO = 1;
	    public static int DEBUG = 2;
	    public static int ERROR = 3;
	
	    protected int level;
	
	    // 责任链中的下一个元素
	    protected AbstractLogger nextLogger;
	
	    public void setNextLogger(AbstractLogger nextLogger) {
	        this.nextLogger = nextLogger;
	    }
	
	    public void logMessage(int level, String message) {
	        if (this.level <= level) {
	            write(message);
	        }
	        // 递归效果，不断调用下一级 logMessage
	        if (nextLogger != null) {
	            nextLogger.logMessage(level, message);
	        }
	    }
	
	    protected abstract void write(String message);
	}
	```

- 2、创建扩展了该记录器类的实体类。

	```java
	public class ConsoleLogger extends AbstractLogger {
	
	    public ConsoleLogger(int level) {
	        this.level = level;
	    }
	
	    @Override
	    protected void write(String message) {
	        Log.e("---", "Standard Console::Logger  " + message);
	    }
	}
	```

	```java
	public class FileLogger extends AbstractLogger {
	
	    public FileLogger(int level) {
	        this.level = level;
	    }
	
	    @Override
	    protected void write(String message) {
	        Log.e("---", "File::Logger  " + message);
	    }
	}
	```

	```java
	public class ErrorLogger extends AbstractLogger {
	
	    public ErrorLogger(int level) {
	        this.level = level;
	    }
	
	    @Override
	    protected void write(String message) {
	        Log.e("---", "Error Console::Logger  " + message);
	    }
	}
	```

- 3、创建不同类型的记录器。赋予它们不同的错误级别，并在每个记录器中设置下一个记录器。每个记录器中的下一个记录器代表的是链的一部分。

	```java
	public static AbstractLogger getChainOfLoggers() {
        ErrorLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);
        FileLogger fileLogger = new FileLogger(AbstractLogger.DEBUG);
        ConsoleLogger consoleLogger = new ConsoleLogger(AbstractLogger.INFO);
        errorLogger.setNextLogger(fileLogger);
        fileLogger.setNextLogger(consoleLogger);
        return errorLogger;
	}
	
	AbstractLogger logger = getChainOfLoggers();
	
    // ---: Standard Console::Logger  this is an information.
    logger.logMessage(AbstractLogger.INFO, "this is an information.");
    
    // ---: File::Logger  this is a debug level information.
    // ---: Standard Console::Logger  this is a debug level information.
    logger.logMessage(AbstractLogger.DEBUG, "this is a debug level information.");

    // ---: Error Console::Logger  this is a error level information.
    // ---: File::Logger  this is a error level information.
    // ---: Standard Console::Logger  this is a error level information.
    logger.logMessage(AbstractLogger.ERROR, "this is a error level information.");

	```

### 22. 访问者模式
> 在访问者模式中，我们使用了一个访问者类，它改变了元素类的执行算法。通过这种方式，元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式，元素对象已接受访问者对象，这样访问者对象就可以处理元素对象上的操作。

 - **主要解决**：稳定的数据结构和易变的操作耦合问题。

以显示计算机的组成部分为例，主要分五步实现：

 - 1、定义一个表示元素的接口。

	```java
	public interface ComputerPart {
	    public void accept(ComputerPartVisitor computerPartVisitor);
	}
	```

 - 2、创建扩展了上述类的实体类。[Keyboard](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/visitor/impl/Keyboard.java)、[Monitor](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/visitor/impl/Monitor.java)、[Mouse](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/visitor/impl/Mouse.java)、[Computer](https://github.com/youlookwhat/DesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/visitor/impl/Computer.java)

	```java
	public class Computer implements ComputerPart {
	
	    private ComputerPart[] parts;
	
	    public Computer() {
	        this.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);
	    }
	}
	```

	```java
	public class Mouse implements ComputerPart {
	    @Override
	    public void accept(ComputerPartVisitor computerPartVisitor) {
	        computerPartVisitor.visit(this);
	    }
	}
	```

 - 3、定义一个表示访问者的接口。

	```java
	public interface ComputerPartVisitor {
	
	    public void visit(Computer computer);
	
	    public void visit(Mouse mouse);
	
	    public void visit(Keyboard keyboard);
	
	    public void visit(Monitor monitor);
	}
	```

 - 4、创建实现了上述类的实体访问者。

	```java
	public class ComputerPartDisplayVisitor implements ComputerPartVisitor {
	
	    @Override
	    public void visit(Computer computer) {
	        Log.e("---", "Displaying Computer.");
	    }
	
	    @Override
	    public void visit(Mouse mouse) {
	        Log.e("---", "Displaying Mouse.");
	    }
	
	    @Override
	    public void visit(Keyboard keyboard) {
	        Log.e("---", "Displaying Keyboard.");
	    }
	
	    @Override
	    public void visit(Monitor monitor) {
	        Log.e("---", "Displaying Monitor.");
	    }
	}
	```

 - 5、使用 ComputerPartDisplayVisitor 来显示 Computer 的组成部分。

	```java
        ComputerPart computer = new Computer();
        computer.accept(new ComputerPartDisplayVisitor());
        /*
	     *打印：
	     *---: Displaying Mouse.
	     *---: Displaying Keyboard.
	     *---: Displaying Monitor.
	     *---: Displaying Computer.
	     */
	```


## Download
 - [DesignPattern.apk](https://download.csdn.net/download/jingbin_/12146492)

## Reference 
 - [CSDN：张鸿洋](http://blog.csdn.net/lmj623565791/article/category/2206597)
 - [CSDN：dmk877](http://blog.csdn.net/dmk877/article/details/50311791)
 - [菜鸟教程：设计模式](https://www.runoob.com/design-pattern/design-pattern-intro.html)


## About me
 - **QQ：** 770413277
 - **掘金：**[https://juejin.im/user/56eec46d1ea49300555a176b/posts](https://juejin.im/user/56eec46d1ea49300555a176b/posts)
 - **简书：**[https://www.jianshu.com/u/e43c6e979831](https://www.jianshu.com/u/e43c6e979831)
 - **Email：** jingbin127@163.com
