当前位置: 首页 > 后端技术 > Java

设计模式——装饰器模式

时间:2023-04-01 23:28:48 Java

WX搜索:程序员的个人修养查看更多内容装饰器模式(Decorator)运行时扩展远比编译时继承强大。我们将讨论如何在运行时使用对象组合来装饰类。使用继承来设计子类的行为是在编译时静态确定的,所有的子类都会继承相同的行为。但是,如果可以使用组合来扩展对象的行为,则可以在运行时动态地进行,而无需修改现有代码。由于没有更改现有代码,因此出现错误的可能性并没有大大降低。设计原则Open-ClosedPrinciple类应该开发用于外部扩展,关闭用于修改。定义装饰器模式以动态地将职责附加到对象。为了扩展功能,装饰器提供了一种比继承更灵活的替代方法。类图代码实现下面以咖啡店为例,模拟装饰器模式的实现。首先,咖啡店卖的是一种咖啡。这款咖啡原价10元。如果客人需要加糖,糖的价格需要加2元。顾客还可以选择是否加牛奶,牛奶价格为¥5。添加糖或咖啡可以看作是对咖啡味道的装饰。所以,在这种情况下,咖啡是装饰器,糖和牛奶是两个装饰器。通过装饰咖啡(在这种情况下,不同的口味,甜味或牛奶,或两者兼而有之),出售不同的口味。咖啡的口味,当然价格也会不同。下面我们用代码来实现:packagecom.study.design.Decorator;/***装饰器的抽象类*/publicabstractclassCoffe{/***计算价格的方法*@return*/protectedabstractintcost();}packagecom.study.design.Decorator;/***待装饰对象*原味咖啡,售价10元*/publicclassOriginalCoffeextendsCoffe{@Overrideprotectedintcost(){return10;}}包com.study.design.Decorator;publicabstractclassDecoratorextendsCoffe{//装饰器的对象protectedCoffecoffe;protectedabstractintadditional();}packagecom.study.design.Decorator;/***decorator*添加糖¥2*/publicclassSugarextendsDecorator{publicSugar(Coffecoffee){this.coffe=coffe;}@Overrideprotectedintcost(){returncoffee.cost()+additional();}@Overrideprotectedintadditional(){return2;}}packagecom.study.design.Decorator;/***Decorator*Addmilk¥5*/publicclassMilkextendsDecorator{publicMilk(Coffecoffee){this.coffe=coffe;}@Overrideprotectedintcost(){returncoffe.cost()+additional();}@Overrideprotectedintadditional(){返回5;}}packagecom.study.design.Decorator;publicclassDecoratorTest{publicstaticvoidmain(String[]args){OriginalCoffeoriginalCoffe=newOriginalCoffe();System.out.println("咖啡原价:"+originalCoffe.cost());糖sugar=newSugar(originalCoffe);System.out.println("加糖后的价格:"+sugar.cost());牛奶milk=newMilk(originalCoffe);System.out.println("加入牛奶后的价格"+milk.cost());牛奶=新牛奶(糖);System.out.println("加入牛奶和糖后的价格:"+milk.cost());}}熟悉AOP的同学应该会想到装饰器中新增的方法或函数,这不就像AOP中的pre-advice和post-advice吗?是的!但是AOP底层是通过动态代理实现的。动态代理与装饰器模式的本质区别在于,前者侧重于控制代理对象的行为。不同的代理对象对代理对象的行为实现不同的控制,而且这些代理对象很少。有组合的可能性,后者侧重于装饰物功能的扩展。不同的装饰器为被装饰的对象添加了不同的功能,这些装饰器可以任意嵌套组合。比如可以同时加入糖和牛奶。JavaI/O中的装饰器模式对于装饰器模式,最经典的就是在JavaI/O中的应用。理解了装饰器模式之后,再回过头来系统地看一下关于JavaI/O的源码,就会顺畅很多。上面展示了输入流的部分类图关系,输出流也是如此。但是JavaI/O也带来了装饰器模式的一个“缺点”:使用装饰器模式,往往会导致一个设计中有大量的小类,太多了,这可能会给使用这个API的开发者带来困惑。但是,如果你理解了装饰器模式的原理,那么在以后使用别人重装饰的API时,你可以很容易地识别出他们的装饰器类是如何组织的,从而通过包装获得你想要的行为。要点:所有被装饰对象和装饰器都需要继承同一个父类或者实现同一个接口。装饰器必须持有装饰对象的接口类型的对象。装饰器可以在被装饰对象之前/之后添加自己的行为,甚至会完全被装饰器的行为所取代,实现特定目的的装饰器会在设计中造成很多小对象。如果过度使用,会使程序变得非常复杂。WX搜索:程序员的个人修养查看更多内容