在不改变原有对象的基础之上,将功能附加到对象上
提供了比继承更有弹性的替代方案(扩展语言有对象功能,其实也是建立在继承之上)
具体举例
我们创建一个煎饼类
//具体描述 public String getDesc() { return "煎饼"; } //获得加个 public int cost() { return 8; }
//这时候我们想吃加鸡蛋的煎饼,就创建一个加鸡蛋的类 public class BattercakeWithEgg extends Battercake { @Override public String getDesc() { return super.getDesc() + "加一个鸡蛋"; } @Override public int cost() { return super.cost() + 1; } }
//这时候我们想吃加火腿肠的 就再创建一个加火腿肠的类。 public class BattercakeWithEggSausage extends BattercakeWithEgg { @Override public String getDesc() { return super.getDesc() + "加一根香肠"; } @Override public int cost() { return super.cost() + 2; } }
煎饼 销售价格:8 煎饼加一个鸡蛋 销售价格:9 煎饼加一个鸡蛋加一根香肠 销售价格:11
test类想像成我们的应用层代码。通过上面的打印结果我们能看出来,我们吃煎饼想要加的东西都实现了。但是如果现在我想吃一张煎饼加两个鸡蛋加两根香肠,那么就没有办法实现了。我们需要创建新的类去继承,但可以看出弊端我们需要无限的创造。可能正是由于这种场景,使得装饰者模式出现。
装饰者模式是需要有四个东西:一个抽象的实体类、一个确定的实体类、一个抽象的装饰者、一个确定的装饰者。
//抽象的实体 public abstract class ABattercake { public abstract String getDesc(); public abstract int cost(); }
//具体的实体 public class Battercake extends ABattercake { @Override public String getDesc() { return "煎饼"; } @Override public int cost() { return 8; } }
//抽象的的装饰者,当前并不是抽象类。可以变成抽象类,加个抽象方法 比如doSomething()具体需要看业务的实现。比如加鸡蛋需要敲碎壳,加香肠需要撕开包装纸 public class AbstractDecorator extends ABattercake { private ABattercake aBattercake; public AbstractDecorator(ABattercake aBattercake) { this.aBattercake = aBattercake; } @Override public String getDesc() { return aBattercake.getDesc(); } @Override public int cost() { return aBattercake.cost(); } }
//鸡蛋装饰 public class EggDecorator extends AbstractDecorator { public EggDecorator(ABattercake aBattercake) { super(aBattercake); } @Override public String getDesc() { return super.getDesc() + "加一个鸡蛋"; } @Override public int cost() { return super.cost() + 1; } }
//香肠装饰 public class SausageDecorator extends AbstractDecorator { public SausageDecorator(ABattercake aBattercake) { super(aBattercake); } @Override public String getDesc() { return super.getDesc() + "加一根香肠"; } @Override public int cost() { return super.cost() + 2; } }
通过上面的代码我们可以看到,我们把抽象的装饰器和具体的实体都继承了抽象的实体,目的是为了将他们通过共同的父类联系起来。而在抽象装饰者中我们通过构造器,以组合的方式来进行使用。
public AbstractDecorator(ABattercake aBattercake) { this.aBattercake = aBattercake; }
我们通过调用抽象的装饰者,其实是把这个行为委托给里面的抽象的实体完成的。
下面是具体的uml
其实要是但看文章基本用不了几分钟,但是吸收、运用、查资料理解我感觉还是要用一定的时间的。书上说不要为了用设计模式而用设计模式,其实我现在感觉就应该为了用设计模式而用设计模式,我认为这样在初期能够更好的去理解。
通过io的uml与之前形成uml,我们可以进行对比着看。inputstream相当于抽象实体类,ByteArrayInputStream、FileInputStream等是具体的实体类,FilterInputStream相当于抽象的装饰者,而且子类则是具体的装饰者。
其中reader,writer也是。但是我还没有验证
假如你还有兴趣去一些源码,还有一些:spring中的TransactionAwareCacheDecorator、SessionRepositoryRrequestWrapper, mybatis中的cache包下decorators的包里面。