设计模式之禅PK之结构类
结构类设计模式
- 结构类模式:
- 适配器模式
- 桥梁模式
- 组合模式
- 装饰模式
- 门面模式
- 享元模式
- 代理模式
- 相同点:他们都是通过组合类或对象产生更大的结构以适应更高的层次的逻辑需求
【代理模式】VS【装饰模式】
- 首先:
- 装饰模式是代理模式的一个特殊应用,两者的共同特点是都具有相同的接口,不同点则是代理模式着重对代理过程的控制,而装饰模式则是对类的功能进行加强或减弱,它着重类的功能变化
- 以例子驱动:找短跑运动员去跑步
- 代理模式:找代理去说服
- 装饰模式:加强运动员的跑步素质
- 类图对比
代理模式 | 装饰模式 |
---|---|
- 咦,怎么类图一样?别忘了装饰模式可是代理模式的一个特殊应用,这样一说就没什么神秘的了吧!
代码详细逻辑
-
代理模式
-
IRunner
package com.peng.pk_dl; /** * @author kungfu~peng * @data 2017年12月11日 * @description */ public interface IRunner { // 运动员的主要工作就是跑步 public void run(); }
-
Runner
package com.peng.pk_dl; /** * @author kungfu~peng * @data 2017年12月11日 * @description */ public class Runner implements IRunner { @Override public void run() { System.out.println("运动员跑步,动作很潇洒!"); } }
-
RunnerAgent
package com.peng.pk_dl; import java.util.Random; /** * @author kungfu~peng * @data 2017年12月11日 * @description */ public class RunnerAgent implements IRunner { // 真正的运动员 private IRunner ir; // 构造函数传入真正的运动员 public RunnerAgent(IRunner ir) { super(); this.ir = ir; } @Override public void run() { if (new Random().nextBoolean()) { System.out.println("代理人允许!"); this.ir.run(); } else { System.out.println("代理人不允许!"); } } }
-
Client
package com.peng.pk_dl; /** * @author kungfu~peng * @data 2017年12月11日 * @description */ public class Client { public static void main(String[] args) throws InterruptedException { // 定义一个运动员 IRunner ir = new Runner(); // 定义这个运动员的代理人 RunnerAgent ra = new RunnerAgent(ir); // 询问代理人是否运动员是否可以跑步 for (int i = 0; i < 10; i++) { Thread.sleep(1000); System.out.println("======您好:代理,运动员可以跑吗--第" + (i + 1) + "次询问====="); ra.run(); } } }
-
执行结果(某一次的执行结果)
======您好:代理,运动员可以跑吗--第1次询问===== 代理人不允许! ======您好:代理,运动员可以跑吗--第2次询问===== 代理人不允许! ======您好:代理,运动员可以跑吗--第3次询问===== 代理人不允许! ======您好:代理,运动员可以跑吗--第4次询问===== 代理人允许! 运动员跑步,动作很潇洒! ======您好:代理,运动员可以跑吗--第5次询问===== 代理人允许! 运动员跑步,动作很潇洒! ======您好:代理,运动员可以跑吗--第6次询问===== 代理人不允许! ======您好:代理,运动员可以跑吗--第7次询问===== 代理人允许! 运动员跑步,动作很潇洒! ======您好:代理,运动员可以跑吗--第8次询问===== 代理人允许! 运动员跑步,动作很潇洒! ======您好:代理,运动员可以跑吗--第9次询问===== 代理人不允许! ======您好:代理,运动员可以跑吗--第10次询问===== 代理人允许! 运动员跑步,动作很潇洒!
-
-
装饰模式
-
IRunner
package com.peng.pk_dl; /** * @author kungfu~peng * @data 2017年12月11日 * @description */ public interface IRunner { // 运动员的主要工作就是跑步 public void run(); }
-
Runner
package com.peng.pk_dl; /** * @author kungfu~peng * @data 2017年12月11日 * @description */ public class Client { public static void main(String[] args) { // 定义一个运动员 IRunner ir = new Runner(); // 定义这个运动员的装饰者 RunnerWithJet ra = new RunnerWithJet(ir); ra.run(); } }
-
RunnerWithJet
package com.peng.pk_dl; /** * @author kungfu~peng * @data 2017年12月11日 * @description */ public class RunnerWithJet implements IRunner { // 真正的运动员 private IRunner ir; // 构造函数传入真正的运动员 public RunnerWithJet(IRunner ir) { super(); this.ir = ir; } @Override public void run() { System.out.println("增加动力装置------喷火~~~~"); this.ir.run(); } }
-
Client
package com.peng.pk_dl; /** * @author kungfu~peng * @data 2017年12月11日 * @description */ public class Client { public static void main(String[] args) { // 定义一个运动员 IRunner ir = new Runner(); // 定义这个运动员的装饰者 RunnerWithJet ra = new RunnerWithJet(ir); ra.run(); } }
-
执行结果
增加动力装置------喷火~~~~ 运动员跑步,动作很潇洒!
-
最佳实践
代理模式 | 装饰模式 | |
---|---|---|
细微的差别 | 把当前的行为和功能委托给其他对象执行,代理类负责接口限定,是否可以调用真实角色,以及是否对发送到真实角色的消息进行变形处理,他不对对象的功能做任何的处理,保证原汁原味的调用 | 保证接口不变的情况下加强类的功能(也可以削弱功能),但不做准入条件判断和准入参数过滤,这不是装饰模式关心的 |
应用范围 | 俯拾皆是 | 比较拘谨(java.io.*中有大量的使用) eg:new DataOutputStream(new FileOutputStream("text.txt")) |
声明
- 摘自秦小波《设计模式之禅》第2版;
- 仅供学习,严禁商业用途;
- 代码手写,没有经编译器编译,有个别错误,自行根据上下文改正;