装饰模式
动态的给一个对象添加一些额外的职责,比生成子类更加灵活
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| public interface ICharacter { public void show(); }
public class Person implements ICharacter{ private String name; public Person(String n){ name = n; }
@Override public void show() { System.out.println("装饰的" + name); } }
public class Finery implements ICharacter{ protected ICharacter component; public void decorate(ICharacter com){ component = com; }
@Override public void show() { if (component != null) component.show(); } }
public class Tshirts extends Finery{ public void show(){ System.out.println("大T恤"); super.show(); } }
public static void main(String[] args) { Person xc = new Person("sss"); Sneakers qx = new Sneakers(); qx.decorate(xc); BigTrouser kk = new BigTrouser(); kk.decorate(qx); Tshirts tx = new Tshirts(); tx.decorate(kk); tx.show(); }
|
- 创建抽象接口类
Component
,定义给对象冬天的添加职责的公共接口
- 创建具体的接口
Person
(ConcreteComponent
)继承Component
,定义Show()
用于展示结果
- 创建抽象的装饰类
Finery
(Decorator
),继承Component
,定义Decorate(component)
用于进行装扮的过程;重写Show()
具体装扮结果
- 创建具体的服饰类,
Concrete Decorator
,继承Decorator
,实现具体的装饰对象,并重写Show()
显示具体装扮结果
四类角色
- 实体接口: 定义对象接口,动态添加职责
- 实体类
- 装饰抽象类: 继承实体接口,动态扩展职责
- 具体装饰类: 装饰的具体实现

可以不生成很多子类的情况下扩展类,比如商场打折促销,不仅可以使用策略模式,还可以使用装饰模式,实现打折基础上再进行满减活动
通知信息也有很多渠道,比如短信,微信,qq,邮件系统,多种信息组合通知可以使用装饰模式避免组合
优点:
- 把类中的装饰功能从类中去除,简化原有的类
- 把类的核心职责和装饰功能区分,去除重复的装饰逻辑
- 装饰类和被装饰类独立发展,不会相互耦合
- 不需要创建新的子类即可实现对类功能的动态扩展
- 支持运行时添加或者删除对象的功能
- 满足单一职责原则,可以将不同行为的类拆分成多个较小的类
缺点:
- 在封装器栈中删除特定封装器较为困难
- 较难实现行为不受先后顺序影响的装饰
- 各个装饰层的代码相对冗余
工厂 + 策略 + 装饰实现商场打折
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
| public interface ISale { public double acceptCash(double price, int num); }
public class CashSuper implements ISale{ protected ISale component; public void decorate(ISale com){ component = com; }
public double acceptCash(double price, int num) { double ans = 0; if (component != null) component.acceptCash(price, num); return ans; } }
public class CashNormal implements ISale{ @Override public double acceptCash(double price, int num){ return price * num; } }
public class CashRebate extends CashSuper{ private double moneyRebate = 1; public CashRebate(double mR){ moneyRebate = mR; }
@Override public double acceptCash(double price, int num) { double ans = price * num * moneyRebate; return super.acceptCash(ans, 1); } }
public class CashReturn extends CashSuper{ private double moneyCondition = 0; private double moneyReturn = 0; public CashReturn(double mC, double mR){ moneyCondition = mC; moneyReturn = mR; }
public double acceptCash(double price, int num){ double ans = price * num; if (moneyCondition > 0 && ans >= moneyCondition){ ans -= Math.floor(ans / moneyCondition) * moneyReturn; } return super.acceptCash(ans, 1); } }
public class CashContext { private ISale cs; public CashContext(int cashType){ switch (cashType) { case 1: cs = new CashNormal(); break; case 2: cs = new CashReturn(300, 100); break; case 3: cs = new CashRebate(0.8); break; case 4: cs = new CashRebate(0.7); break; case 5: CashNormal cn = new CashNormal(); CashRebate cr = new CashRebate(0.8); CashReturn crr = new CashReturn(200, 50); cr.decorate(cn); crr.decorate(cr); cs = crr; break; default: break; } } public double getResult(double price, int num){ return cs.acceptCash(price, num); } }
|
代理模式
为其他对象提供代理以控制这个对象的访问

代理模式
- 本地执行远程服务(远程代理): 适用于服务对象位于远程服务器上的情形,可以为一个对象在不同的地址空间提供局部代表
- 延迟初始化(虚拟代理): 如果有一个偶尔使用的重量级服务对象,一直保持对象的运行会消耗系统资源,就可以使用代理模式,比如浏览器加载图片,可以先加载图片的位置以及大小,然后再慢慢渲染出图片
- 访问控制(保护代理/安全代理): 如果只希望特定客户端使用服务对象,对象可以是操作系统中的重要部分,而客户端则是各种已经启动的程序,就可以使用代理模式
- 记录日志请求(日志记录代理): 适用于需要保存对服务对象的请求历史记录
- 缓存请求结果(缓存代理): 适用于需要缓存客户请求并对缓存生命周期进行管理时,特别是返回结果体积非常大的时候
- 智能指引: 调用真实对象是,代理处理另外一些事情,可以在没有客户端使用某个重量级对象时,立刻销毁对象
比如信用卡是银行账户的代理;银行账户是现金的代理;windows快捷方式也是代理;客户端对数据库查询需要消耗大量的资源,在有需要时才创建会带来代码大量重复,因此可以创建代理,让代理伪装成数据库对象,在客户端不知情的情况下处理初始化以及缓存查询结果