今天我们来谈谈装饰者模式! 说起这个模式,相信大家都有过接触,java的IO体系总用过吧,IO体系中各种流都可以见到装饰者的影子,比如BufferedReader和Reader,通过向BufferedReader的构造函数中传入一个Reader,这个Reader就具备了缓冲的能力!
再举个例子,比如你是一个光溜溜的人, 给你套一件麻布衣服,你就成了一个平民,拥有了外出打酱油的能力(不穿衣服你敢出去???) , 再在你麻布衣服上套一层布甲,你成了一个低级士兵,拥有了战斗的能力! 如果再在布甲上面套一层蝙蝠战甲,你就有了蝙蝠侠战斗的能力,有一天,你觉得蝙蝠侠还不够厉害,没关系,脱掉蝙蝠战甲,套上一层钢铁战甲,恭喜你,你成了钢铁侠!
没错,装饰者模式就是这样,一层套一层,每一个对象都可以用来装饰别的对象,也可以被更高级的对象装饰, OK,我们画个图来看看吧!
上面的图很简单明了,因此,我们现在要来思考怎么样来实现这么一个模型呢?要让一个类既能成为装饰者,又能成为被装饰者呢?装饰者和被装饰者看上去是想同的,只不过多了某种能力而已...如果是这样的话,好像如果它们拥有同一个类型的话就可以做到吧!
Ok,我们来写代码吧!
/**一个抽象人类*/ public abstract class AbstractPerson { //每个人默认都是光溜溜的 protected String desc = "光溜溜" ; //此方法没什么作用,只是为了打印测试效果 public String getDesc(){ return desc; } /**每个人都有战斗能力*/ abstract int combatCount(); } /**一个光溜溜的男人,默认只有10点战斗力*/ class Man extends AbstractPerson{ @Override int combatCount() { return 10; } }/**一个抽象装饰者类*/ abstract class abstractDecorate extends AbstractPerson{ //所有装饰者必须持有被装饰者的引用! protected AbstractPerson abstractPerson; public abstractDecorate( AbstractPerson abstractPerson) { this.abstractPerson = abstractPerson; } //覆盖描述方法,简单的打印一下! @Override public String getDesc() { return this.abstractPerson.getDesc()+",套了一层["+this.desc+"],战斗力提示至["+this.combatCount()+"]"; } } 接下来创造4个装饰者; /**一件麻布衣服*/ class Clothes extends abstractDecorate{ public Clothes(AbstractPerson abstractPerson) { super(abstractPerson); this.desc = "麻布衣服"; } @Override int combatCount() {//穿上了麻布衣服,增加30点攻击力 return this.abstractPerson.combatCount()+30; } } /**一件布甲*/ class Corselet extends abstractDecorate{ public Corselet(AbstractPerson abstractPerson) { super(abstractPerson); this.desc = "布甲"; } @Override int combatCount() {//穿上了布甲,增加100点攻击力 return this.abstractPerson.combatCount()+100; } } /**一件蝙蝠侠战甲*/ class BatCorselet extends abstractDecorate{ public BatCorselet(AbstractPerson abstractPerson) { super(abstractPerson); this.desc = "蝙蝠侠战甲"; } @Override int combatCount() {//穿上了蝙蝠侠战甲,增加1000点攻击力 return this.abstractPerson.combatCount()+10000; } } /**一件超级钢铁侠智能战甲*/ class SteelCorselet extends abstractDecorate{ public SteelCorselet(AbstractPerson abstractPerson) { super(abstractPerson); this.desc = "超级钢铁侠智能战甲"; } @Override int combatCount() {//穿上了蝙蝠侠战甲,增加10000000点攻击力 return this.abstractPerson.combatCount()+10000000; } }
我们来测试一下!
public class Test { public static void main(String[] args) { AbstractPerson person = new Man(); person.desc="一个男人"; person = new Clothes(person); person = new Corselet(person); person = new BatCorselet(person); System.out.println(person.getDesc()); } } 输出************************************************一个男人,套了一层[麻布衣服],战斗力提示至[40],套了一层[布甲],战斗力提示至[140],套了一层[蝙蝠侠战甲],战斗力提示至[10140]
***************************************************** 如果我们想拥有钢铁侠的飞行能力怎么办?很简单嘛!将person = new BatCorselet(person)换成person = new SteelCorselet(person)不就可以了嘛!
在上门代码中,Man是一个最基本的类,它是一个光溜溜的人,没有任何能力,我们通过创造多个装饰者,并挨个将被装饰者包装一遍,使其提高了战斗力,拥有了各种能力,比如套上蝙蝠侠战甲,它就有了开蝙蝠战车的能力(我代码中没写这些) ,而换成钢铁侠战甲,则拥有了飞行能力...
通过上面的代码,我们基本可以得出装饰者模式的定义:那就是能在运行时,动态给某个对象增加新的功能行为,装饰者模式底层就是用组合,装饰者组合被装饰者!