From a1e00213a6e5856c7a6a1dee736b2fbbc00ef47d Mon Sep 17 00:00:00 2001 From: songzhibin Date: Sat, 10 Jul 2021 15:19:16 +0800 Subject: [PATCH] Update README.md --- README.md | 1523 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 1517 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 33f4543..ac053ab 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,1521 @@ -# JavaDesignPattern -设计模式在java中的应用示例代码 +# DesignPattern +设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。 -建议阅读源码时配合文章介绍 +设计模式分为三种类型,共23种: -http://blog.anxpp.com/index.php/archives/489/ + - **创建型模式**:[单例模式](https://github.com/songzhibin/JavaDesignPattern#3-单例设计模式)、[抽象工厂模式](https://github.com/songzhibin/JavaDesignPattern#2-工厂模式)、[建造者模式](https://github.com/songzhibin/JavaDesignPattern#11-建造者模式)、[工厂模式](https://github.com/songzhibin/JavaDesignPattern#2-工厂模式)、[原型模式](https://github.com/songzhibin/JavaDesignPattern#12-原型模式)。 + - **结构型模式**:[适配器模式](https://github.com/songzhibin/JavaDesignPattern#5-适配器模式)、[桥接模式](https://github.com/songzhibin/JavaDesignPattern#15-桥接模式)、[装饰模式](https://github.com/songzhibin/JavaDesignPattern#7-装饰者模式)、[组合模式](https://github.com/songzhibin/JavaDesignPattern#16-组合模式)、[外观模式](https://github.com/songzhibin/JavaDesignPattern#8-外观模式)、[享元模式](https://github.com/songzhibin/JavaDesignPattern#13-享元模式)、[代理模式](https://github.com/songzhibin/JavaDesignPattern#14-代理模式)。 + - **行为型模式**:[模版方法模式](https://github.com/songzhibin/JavaDesignPattern#9-模板方法模式)、[命令模式](https://github.com/songzhibin/JavaDesignPattern#6-命令模式)、[迭代器模式](https://github.com/songzhibin/JavaDesignPattern#17-迭代器模式)、[观察者模式](https://github.com/songzhibin/JavaDesignPattern#1-观察者模式)、[中介者模式](https://github.com/songzhibin/JavaDesignPattern#18-中介者模式)、[备忘录模式](https://github.com/songzhibin/JavaDesignPattern#19-备忘录模式)、[解释器模式](https://github.com/songzhibin/JavaDesignPattern#20-解释器模式)、[状态模式](https://github.com/songzhibin/JavaDesignPattern#10-状态模式)、[策略模式](https://github.com/songzhibin/JavaDesignPattern#4-策略模式)、[责任链模式](https://github.com/songzhibin/JavaDesignPattern#21-责任链模式)、[访问者模式](https://github.com/songzhibin/JavaDesignPattern#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/songzhibin/JavaDesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/observer) +> - [Factory](https://github.com/songzhibin/JavaDesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/factory) +> - [Singleton](https://github.com/songzhibin/JavaDesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/singleton) +> - [Strategy](https://github.com/songzhibin/JavaDesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/strategy) +> - [Adapter](https://github.com/songzhibin/JavaDesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/adapter) +> - [Command](https://github.com/songzhibin/JavaDesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/command) +> - [Decorator](https://github.com/songzhibin/JavaDesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/decorator) +> - [Facade](https://github.com/songzhibin/JavaDesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/facade) +> - [Template Method](https://github.com/songzhibin/JavaDesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/templatemethod) +> - [State](https://github.com/songzhibin/JavaDesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/state) +> - [Builder](https://github.com/songzhibin/JavaDesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/builder) +> - [Prototype](https://github.com/songzhibin/JavaDesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/prototype) +> - [Flyweight](https://github.com/songzhibin/JavaDesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/flyweight) +> - [Proxy](https://github.com/songzhibin/JavaDesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/proxy) +> - [Bridge](https://github.com/songzhibin/JavaDesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/bridge) +> - [Composite](https://github.com/songzhibin/JavaDesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/composite) +> - [Iterator](https://github.com/songzhibin/JavaDesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/iterator) +> - [Mediator](https://github.com/songzhibin/JavaDesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/mediator) +> - [Memento](https://github.com/songzhibin/JavaDesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/memento) +> - [Chain of Responsibility](https://github.com/songzhibin/JavaDesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/chainofresponsibility) +> - [Visitor](https://github.com/songzhibin/JavaDesignPattern/tree/master/app/src/main/java/com/example/jingbin/designpattern/visitor) + +## Project Picture + +![](https://raw.githubusercontent.com/songzhibin/JavaDesignPattern/master/image/ds1.png) +![](https://raw.githubusercontent.com/songzhibin/JavaDesignPattern/master/image/ds2.png) + +## Pattern Analysis +### 1. 观察者模式 + > 定义了对象之间的一对多的依赖,这样一来,当一个对象改变时,它的所有的依赖者都会收到通知并自动更新。 + + - 对于JDK或者Andorid中都有很多地方实现了观察者模式,比如XXXView.addXXXListenter , 当然了 XXXView.setOnXXXListener不一定是观察者模式,因为观察者模式是一种一对多的关系,对于setXXXListener是1对1的关系,应该叫回调。 + + - 专题接口:[Subject.java](https://github.com/songzhibin/JavaDesignPattern/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/songzhibin/JavaDesignPattern/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/songzhibin/JavaDesignPattern/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/songzhibin/JavaDesignPattern/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/songzhibin/JavaDesignPattern/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/songzhibin/JavaDesignPattern/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/songzhibin/JavaDesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/factory/gcff/XianRoujiaMoStore.java) + - 分店依旧使用简单工厂模式:[XianSimpleRoujiaMoFactory.java](https://github.com/songzhibin/JavaDesignPattern/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/songzhibin/JavaDesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/factory/cxgc/RoujiaMoYLFactory.java) + - 各自分店实现接口,完成原料提供:[XianRoujiaMoYLFoctory.java](https://github.com/songzhibin/JavaDesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/factory/cxgc/XianRoujiaMoYLFoctory.java) + - 准备时,使用官方的原料:[RoujiaMo.java](https://github.com/songzhibin/JavaDesignPattern/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/songzhibin/JavaDesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/singleton/ehan/SingletonEHan.java) +- 含懒汉式[双重校验锁 推荐用]:[SingletonLanHan.java](https://github.com/songzhibin/JavaDesignPattern/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/songzhibin/JavaDesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/singleton/inclass/SingletonIn.java) +- 枚举[推荐用]:[SingletonEnum.java](https://github.com/songzhibin/JavaDesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/singleton/enums/SingletonEnum.java) + + +### 4. 策略模式 +> 策略模式:定义了算法族,分别封装起来,让它们之间可相互替换,此模式让算法的变化独立于使用算法的客户。 + + - 以创建游戏角色为例子: + - 最初的游戏角色的父类:[Role.java](https://github.com/songzhibin/JavaDesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/strategy/old/Role.java) + - 发现有重复代码后,重构后的父类:[Role.java](https://github.com/songzhibin/JavaDesignPattern/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/songzhibin/JavaDesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/adapter/Mobile.java) + - 手机依赖一个提供5V电压的接口: [V5Power.java](https://github.com/songzhibin/JavaDesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/adapter/V5Power.java) + - 我们拥有的是220V家用交流电: [V220Power.java](https://github.com/songzhibin/JavaDesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/adapter/V220Power.java) + - **适配器,完成220V转5V的作用**:[V5PowerAdapter.java](https://github.com/songzhibin/JavaDesignPattern/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/songzhibin/JavaDesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/command/Door.java) + - 2、把命令封装成类: + - 统一的命令接口:[Command.java](https://github.com/songzhibin/JavaDesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/command/Command.java) + - 家电实现该接口:[DoorOpenCommand.java](https://github.com/songzhibin/JavaDesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/command/DoorOpenCommand.java) + - 3、遥控器:[ControlPanel.java](https://github.com/songzhibin/JavaDesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/command/ControlPanel.java) + - 4、定义一个命令,可以干一系列的事情:[QuickCommand.java](https://github.com/songzhibin/JavaDesignPattern/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/songzhibin/JavaDesignPattern/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/songzhibin/JavaDesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/decorator/IEquip.java) + - 2、各个装备的实现类: + - eg:**武器**的实现类: [ArmEquip.java](https://github.com/songzhibin/JavaDesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/decorator/equip/ArmEquip.java) + +- 3、装饰品的超类(装饰品也属于装备):[IEquipDecorator.java](https://github.com/songzhibin/JavaDesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/decorator/gem/IEuipDecorator.java) +- 4、装饰品的实现类: + - eg:**蓝宝石**的实现类(可累加): [BlueGemDecorator.java](https://github.com/songzhibin/JavaDesignPattern/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/songzhibin/JavaDesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/facade/device/PopcornPopper.java) + - 电影院类:[HomeTheaterFacade.java](https://github.com/songzhibin/JavaDesignPattern/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/songzhibin/JavaDesignPattern/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/songzhibin/JavaDesignPattern/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/songzhibin/JavaDesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/state/old/VendingMachine.java) + - 改进后的售货机(更具有延展性):[VendingMachineBetter.java](https://github.com/songzhibin/JavaDesignPattern/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/songzhibin/JavaDesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/state/better/State.java) + - 对应状态的接口实现类: + - eg: 中奖状态:[WinnerState.java](https://github.com/songzhibin/JavaDesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/state/better/WinnerState.java) + - eg: 售卖状态:[SoldState.java](https://github.com/songzhibin/JavaDesignPattern/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/songzhibin/JavaDesignPattern/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/songzhibin/JavaDesignPattern/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/songzhibin/JavaDesignPattern/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/songzhibin/JavaDesignPattern/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/songzhibin/JavaDesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/prototype/shapeimpl/Circle.java)、[Rectangle](https://github.com/songzhibin/JavaDesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/prototype/shapeimpl/Rectangle.java)、[Square](https://github.com/songzhibin/JavaDesignPattern/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/songzhibin/JavaDesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/prototype/ShapeCache.java) + + ```java + public class ShapeCache { + + private static Hashtable shapeMap = new Hashtable(); + + 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 circleMap = new HashMap(); + + 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/songzhibin/JavaDesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/bridge/RedCircle.java)、[GreenCircle](https://github.com/songzhibin/JavaDesignPattern/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/songzhibin/JavaDesignPattern/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 subordinates; + + public Employee(String name, String dept, int salary) { + this.name = name; + this.dept = dept; + this.salary = salary; + this.subordinates = new ArrayList(); + } + + public void add(Employee e) { + subordinates.add(e); + } + + public void remove(Employee e) { + subordinates.remove(e); + } + + public List 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 mementoList = new ArrayList(); + + 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/songzhibin/JavaDesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/visitor/impl/Keyboard.java)、[Monitor](https://github.com/songzhibin/JavaDesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/visitor/impl/Monitor.java)、[Mouse](https://github.com/songzhibin/JavaDesignPattern/blob/master/app/src/main/java/com/example/jingbin/designpattern/visitor/impl/Mouse.java)、[Computer](https://github.com/songzhibin/JavaDesignPattern/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) -或者 -http://blog.csdn.net/anxpp/article/details/51224293