【设计模式无难事】——装饰者
2018-01-11 16:04
183 查看
【设计模式无难事】——装饰者
一、意图
装饰者模式,顾名思义,通过给一个对象提供装饰作用,从而使对象得到增强。
这里可能有人会问,继承也可以达到同样目的,为什么需要装饰者?没错,继承的确也可以,但是它有明显的不足,我们现在就通过一个实际例子来说明
二、例子
需求场景
游戏中的怪物(簇)实现
包括:基础怪物、水系怪物、火系怪物,大魔王
分析&实作
(1)装饰者方式实现
1,假定所有的怪物都有2个共同的行为:攻击,逃跑。于是我们定义一个接口
Troll.java
2,接着我们做一个简单的怪物
SimpleTroll.java
3,接下来,水系怪物
WaterTroll.java
4,火系怪物
FireTroll.java
5,Boss
BossTroll.java
6,运行
7,输出
(2)继承方式实现
WaterTroll.java 和 BossTroll.java
三、思考
看完上面的例子,我们可以看到二者的区别了
1,继承是静态的,而装饰者是动态的;
用继承,BossTroll在编译阶段就固定为fireTroll的子类;
用装饰者,BossTroll在运行时才决定是要增强fireTroll对象或是waterTroll对象,这可以由服务器端动态下发,运行时来决定是火系boss还是水系boss,或是一个simpleTroll的boss。
2,装饰者没有继承体系约束,更加灵活
随着怪物种类的剧增,如果使用继承,难免会导致继承树十分庞大,而且,精准的拿捏继承体系的合理抽象也是困难的,任何层级的多余行为都会污染继承体系,不是吗?
而装饰者却可以拿出原本属于继承树任意层级中的对象来装饰,而得到新的增强对象,这点也是继承机制难以实现的。
3,还有一个非常适合装饰者的例子“星巴克咖啡”,这里就不贴代码了,如果想把
“咖啡”、“加奶咖啡”、“加糖咖啡”、“加糖加奶咖啡”、“加伴侣咖啡”、“摩卡咖啡”、“黑咖啡”、“加糖加奶摩卡咖啡”。。。。等概念组织起来的话,非用装饰者不可,继承会要了你的命。
Tips:一个类,它实现了某个接口,并持此接口的引用,是装饰者的特征
四、装饰者模式在android源码中的例子
Context、ContextImpl、ContextThemeWrapper、Activity
关于这个网上已经有大量的帖子了
附:
本文源代码在这里
有任何问题,欢迎留言或Email我 zzy_2002@126.com
转载请注明出处:http://blog.csdn.net/zzy_801011/article/details/79035321
谢谢
一、意图
装饰者模式,顾名思义,通过给一个对象提供装饰作用,从而使对象得到增强。
这里可能有人会问,继承也可以达到同样目的,为什么需要装饰者?没错,继承的确也可以,但是它有明显的不足,我们现在就通过一个实际例子来说明
二、例子
需求场景
游戏中的怪物(簇)实现
包括:基础怪物、水系怪物、火系怪物,大魔王
分析&实作
(1)装饰者方式实现
1,假定所有的怪物都有2个共同的行为:攻击,逃跑。于是我们定义一个接口
Troll.java
/** * * Interface for trolls * 精灵 */ public interface Troll { void attack(); void fleeBattle(); //临阵脱逃 }
2,接着我们做一个简单的怪物
SimpleTroll.java
/** * * SimpleTroll implements {@link Troll} interface directly. * */ public class SimpleTroll implements Troll { @Override public void attack() { LOGGER.info("怪物跑向你,试图抓住你!"); } @Override public void fleeBattle() { LOGGER.info("怪物逃跑了!"); } }
3,接下来,水系怪物
WaterTroll.java
/** * Decorator that adds a icicle for the troll */ public class WaterTroll implements Troll { private static final Logger LOGGER = LoggerFactory.getLogger(WaterTroll.class); private Troll decorated;/*被装饰的怪物*/ public WaterTroll(Troll decorated) { this.decorated = decorated; } @Override public void attack() { decorated.attack(); /*不但有被装饰怪物的攻击,还额外增加了冰霜攻击*/ LOGGER.info("怪物用冰柱攻击了你"); } @Override public void fleeBattle() { decorated.fleeBattle(); } }
4,火系怪物
FireTroll.java
/** * Decorator that adds a fireBall for the troll */ public class FireTroll implements Troll { private static final Logger LOGGER = LoggerFactory.getLogger(FireTroll.class); private Troll decorated; public FireTroll(Troll decorated) { this.decorated = decorated; } @Override public void attack() { decorated.attack(); /*不但有被装饰怪物的攻击,还额外增加了火球攻击*/ LOGGER.info("怪物用火球攻击了你!"); } @Override public void fleeBattle() { decorated.fleeBattle(); } }
5,Boss
BossTroll.java
/** * Decorator that adds a boss attack for the troll */ public class BossTroll implements Troll { private static final Logger LOGGER = LoggerFactory.getLogger(BossTroll.class); private Troll decorated; public BossTroll(Troll decorated) { this.decorated = decorated; } @Override public void attack() { decorated.attack(); /*不但有被装饰怪物的攻击,还额外增加了boss攻击*/ LOGGER.info("boss攻击"); } @Override public void fleeBattle() { decorated.fleeBattle(); } }
6,运行
public static void main(String[] args) { // simple troll LOGGER.info("来了一个基础怪物"); Troll simpleTroll = new SimpleTroll(); simpleTroll.attack(); simpleTroll.fleeBattle(); // change the behavior of the simple troll by adding a decorator LOGGER.info("来了一个水系怪物"); Troll waterTroll = new WaterTroll(simpleTroll); waterTroll.attack(); waterTroll.fleeBattle(); LOGGER.info("来了一个火系怪物"); Troll fireTroll = new FireTroll(simpleTroll); fireTroll.attack(); fireTroll.fleeBattle(); LOGGER.info("来了一 4000 个Boss"); Troll bossTroll = new BossTroll(fireTroll/*waterTroll|simpleTroll*/); bossTroll.attack(); bossTroll.fleeBattle(); } }
7,输出
15:41:23.755 [main] INFO com.iluwatar.decorator.App - 来了一个基础怪物 15:41:23.757 [main] INFO com.iluwatar.decorator.SimpleTroll - 怪物跑向你,试图抓住你! 15:41:23.758 [main] INFO com.iluwatar.decorator.SimpleTroll - 怪物逃跑了! 15:41:23.758 [main] INFO com.iluwatar.decorator.App - 来了一个水系怪物 15:41:23.758 [main] INFO com.iluwatar.decorator.SimpleTroll - 怪物跑向你,试图抓住你! 15:41:23.758 [main] INFO com.iluwatar.decorator.WaterTroll - 怪物用冰柱攻击了你 15:41:23.758 [main] INFO com.iluwatar.decorator.SimpleTroll - 怪物逃跑了! 15:41:23.758 [main] INFO com.iluwatar.decorator.App - 来了一个火系怪物 15:41:23.758 [main] INFO com.iluwatar.decorator.SimpleTroll - 怪物跑向你,试图抓住你! 15:41:23.758 [main] INFO com.iluwatar.decorator.FireTroll - 怪物用火球攻击了你! 15:41:23.758 [main] INFO com.iluwatar.decorator.SimpleTroll - 怪物逃跑了! 15:41:23.758 [main] INFO com.iluwatar.decorator.App - 来了一个Boss 15:41:23.759 [main] INFO com.iluwatar.decorator.SimpleTroll - 怪物跑向你,试图抓住你! 15:41:23.759 [main] INFO com.iluwatar.decorator.FireTroll - 怪物用火球攻击了你! 15:41:23.759 [main] INFO com.iluwatar.decorator.BossTroll - boss攻击 15:41:23.759 [main] INFO com.iluwatar.decorator.SimpleTroll - 怪物逃跑了! Process finished with exit code 0
(2)继承方式实现
WaterTroll.java 和 BossTroll.java
public class WaterTroll extends SImpleTroll { private static final Logger LOGGER = LoggerFactory.getLogger(WaterTroll.class); @Override public void attack() { super.attack(); /*不但有父类的攻击,还额外增加了冰霜攻击*/ LOGGER.info("怪物用冰柱攻击了你"); } @Override public void fleeBattle() { super.fleeBattle(); } } public class BossTroll extends fireTroll{ private static final Logger LOGGER = LoggerFactory.getLogger(BossTroll.class); @Override public void attack() { super.attack(); /*不但有父类的攻击,还额外增加了boss攻击*/ LOGGER.info("boss攻击"); } @Override public void fleeBattle() { super.fleeBattle(); } }
三、思考
看完上面的例子,我们可以看到二者的区别了
1,继承是静态的,而装饰者是动态的;
用继承,BossTroll在编译阶段就固定为fireTroll的子类;
用装饰者,BossTroll在运行时才决定是要增强fireTroll对象或是waterTroll对象,这可以由服务器端动态下发,运行时来决定是火系boss还是水系boss,或是一个simpleTroll的boss。
2,装饰者没有继承体系约束,更加灵活
随着怪物种类的剧增,如果使用继承,难免会导致继承树十分庞大,而且,精准的拿捏继承体系的合理抽象也是困难的,任何层级的多余行为都会污染继承体系,不是吗?
而装饰者却可以拿出原本属于继承树任意层级中的对象来装饰,而得到新的增强对象,这点也是继承机制难以实现的。
3,还有一个非常适合装饰者的例子“星巴克咖啡”,这里就不贴代码了,如果想把
“咖啡”、“加奶咖啡”、“加糖咖啡”、“加糖加奶咖啡”、“加伴侣咖啡”、“摩卡咖啡”、“黑咖啡”、“加糖加奶摩卡咖啡”。。。。等概念组织起来的话,非用装饰者不可,继承会要了你的命。
Tips:一个类,它实现了某个接口,并持此接口的引用,是装饰者的特征
四、装饰者模式在android源码中的例子
Context、ContextImpl、ContextThemeWrapper、Activity
关于这个网上已经有大量的帖子了
附:
本文源代码在这里
有任何问题,欢迎留言或Email我 zzy_2002@126.com
转载请注明出处:http://blog.csdn.net/zzy_801011/article/details/79035321
谢谢
相关文章推荐
- Android设计模式之中的一个个样例让你彻底明确装饰者模式(Decorator Pattern)
- 设计模式之(Decorator)装饰者模式
- Java设计模式——装饰者模式
- C#设计模式——装饰者模式(Decorator Pattern)
- Java设计模式透析--装饰者模式(二)
- 装饰者设计模式
- Java设计模式之装饰者模式
- 23种设计模式(11):装饰者模式
- 设计模式——装饰者模式
- 设计模式总结2--装饰者模式
- 设计模式之C++实现(三)---装饰者模式(Decorator)
- 设计模式之装饰者模式
- 设计相关7-装饰者模式
- C++设计模式之装饰者模式
- 装饰者设计模式
- Java 装饰者设计模式
- 设计模式-装饰者模式
- 设计模式—装饰者模式
- <Head First 设计模式>:装饰者模式--Beverage
- 设计模式之装饰者模式