一总结装饰模式的用法
1. 需要动态的给一个对象添加功能(给自己或者别的对象赋予新的职责),这些功能可以再动态的撤销。
2. 需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实。(采用继承的方式就可能出现类爆炸)
二场景:
披着羊皮的狼吃羊,原来是赤裸裸的吃,现在装饰一下,然后这只狡猾的狼开始披着羊皮吃羊,披着人皮吃羊,披着兔皮吃羊:
分析(根据下图设计):
1狼:被装饰者
2羊皮,人皮,兔皮是用来装饰的(装饰者),若这时候需要给狼再增加一种皮,那么只需要增加 继承DecoratedWithSkins 的类就可以了。
3 无论怎么伪装都还是只狼,所以大灰狼,和无论如何华丽的装饰都继承狼这个类
//Wolf.java(狼)
package wby.firstzsms;
public abstract class Wolf {
public abstract String eat();
}
//Timberwolf.java(大灰狼)
package wby.firstzsms;
//大灰狼
public class Timberwolf extends Wolf{
@Override
public String eat() {
return "吃羊";
}
}
//DecoratedWithSkins.java(皮肤)
/*
皮肤也继承狼这个类,并且各种皮肤(装饰者)都has-a狼,使用组合的原因是:可以把狼和皮更好地匹配起来,若是只采用继承,就无法体现动态时多态的特点。
*/
package wby.firstzsms;
public abstract class DecoratedWithSkins extends Wolf{
Wolf wolf;
}
//WolfInHumanSkin.java(人皮)
package wby.firstzsms;
public class WolfInHumanSkin extends DecoratedWithSkins{
private final String WolfInHumanSkin_eatString="狼披着人皮";
public WolfInHumanSkin(Wolf wolf){
this.wolf=wolf;//被装饰着记录到实例中
}
public String eat() {
return WolfInHumanSkin_eatString+wolf.eat();
}
}
//WolfInSheepClothing.java(羊皮)
package wby.firstzsms;
public class WolfInSheepClothing extends DecoratedWithSkins{
private final String WolfInSheepClothing_eatSting="狼披着羊皮";
public WolfInSheepClothing(Wolf wolf){
this.wolf=wolf;
}
public String eat() {
return WolfInSheepClothing_eatSting+wolf.eat();
}
}
//ArabbitWolf.java(兔皮)
package wby.firstzsms;
public class ArabbitWolf extends DecoratedWithSkins{
private final String ArabbitWolf_eatString="狼披着兔皮";
public ArabbitWolf(Wolf wolf){
this.wolf=wolf;
}
public String eat() {
return ArabbitWolf_eatString+wolf.eat();
}
}
//3)、编写测试代码
//Test.java
package wby.firstzsms;
public class Test {
public static void main(String[] args) {
Wolf wolf1=new Timberwolf();
wolf1=new ArabbitWolf(wolf1);//兔皮装饰狼(运行时动态增加职责)
System.out.println(wolf1.eat());
Wolf wolf2=new Timberwolf();
wolf2=new WolfInHumanSkin(wolf2);//人皮装饰狼(运行时动态增加职责)
System.out.println(wolf2.eat());
}
}
运行结果:
狼披着兔皮吃羊
狼披着人皮吃羊