今天我们来谈谈装饰者模式! 说起这个模式,相信大家都有过接触,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是一个最基本的类,它是一个光溜溜的人,没有任何能力,我们通过创造多个装饰者,并挨个将被装饰者包装一遍,使其提高了战斗力,拥有了各种能力,比如套上蝙蝠侠战甲,它就有了开蝙蝠战车的能力(我代码中没写这些) ,而换成钢铁侠战甲,则拥有了飞行能力...
通过上面的代码,我们基本可以得出装饰者模式的定义:那就是能在运行时,动态给某个对象增加新的功能行为,装饰者模式底层就是用组合,装饰者组合被装饰者!