装饰者模式

一.定义

装饰模式(Decorator Pattern〉是一种比较常见的模式,其定义如下:Attach additionalresponsibilities to an object dynamically keeping the
same interface. Decorators provide a flexible alternative to subclassing for extending functionality.
(动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。)

基本的类图
装饰者模式_第1张图片

  • Component抽象构件
    Component是一个接口或者是抽象类,就是定
    义我们最核心的对象,也就是最原始的对象。
  • ConcreteComponent具体构件
    ConcreteComponent是最核心、最原始、最基本的接口或抽象类的实现,你要装饰的就是它。
  • Decorator装饰角色
    一般是一个抽象类,做什么用呢?实现接口或者抽象方法,它里面可不一定有抽象的方法呀,在它的属性里必然有一个private变量指向Component抽象构件。
  • 具体装饰角色
    ConcreteDecoratorA和ConcreteDecoratorB是两个具体的装饰类,你要把你最核心的、最原始的、最基本的东西装饰成其他东西.
    抽象构建
    在这里插入图片描述
    具体构建
    装饰者模式_第2张图片
    抽象装饰者
    装饰者模式_第3张图片
    具体装饰类
    装饰者模式_第4张图片
    具体场景类
    装饰者模式_第5张图片

二.例子

大家小时候,是不是都偷偷改过自己的成绩单呢?我以成绩单为故事,开展装饰者模式的讲解.
我们不说不开心的事情,今天以什么例子为开场白呢?就说说我上小学的糗事吧。我上小学的时候学习成绩非常差,班级上有40多个同学,我基本上都是排在45名以后,按照老师给我的评价就是:“不是读书的料”。但是我父亲管得很严格,明知道我不是这块料,还是“赶鸭子上架”,每次考完试我都战战兢兢,“竹笋炒肉”是肯定少不了的,能少点就少点吧,肉可是自己的。四年级期末考试考完,学校出来个很损的招儿(这招儿现在很流行的),打印出成绩单,要家长签字,然后才能上五年级,我那个恐惧呀,不过也就是几秒钟的时间,玩起来什么都忘记了。我们做架构,做设计,任何值得我们回忆的事件都可以通过设计记录下来。当然了,这份成绩单的事情也是可以通过类图表示的,如图所示
装饰者模式_第6张图片
成绩单的抽象类,然后有一个四年级的成绩单实现类,So Easy,我们先来看抽象类,如代码如下所示:
抽象成绩单
装饰者模式_第7张图片
四年级成绩单
装饰者模式_第8张图片

成绩单出来,你别看什么62、65之类的成绩,你要知道,在小学低于90分基本上就是中下等了,悲哀呀,爱学习的人咋就那么多!怎么着,那我把这个成绩单给老爸看看?好,我们修改一下类图,成绩单给老爸看,如图所示:
装饰者模式_第9张图片

老爸查看成绩单
装饰者模式_第10张图片
就这成绩还要我签字?!老爸就开始找扫帚,我开始做准备:深呼吸,绷紧肌肉,提臀收腹。哈哈,幸运的是,这个不是当时的真实情况,我没有直接把成绩单交给老爸,而是在交给他之前做了点技术工作,我要把成绩单封装一下,封装分类两步来实现,如下所示。
汇报最高成绩
跟老爸说各个科目的最高分,语文最高是75,数学是78,自然是80,然后老爸觉的我的成绩与最高分数相差不多,考的还是不错的嘛!这个是实情,但是不知道是什么原因,反正期末考试都考得不怎么样,但是基本上都集中在70分以上,我这60多分基本上还是垫底的角色。
汇报排名情况
在老爸看完成绩单后,告诉他我在全班排第38名,这个也是实情,为啥呢﹖有将近十个同学退学了!这个情况我是不会说的。不知道是不是当时第一次发成绩单时学校没有考虑清楚,没有写上总共有多少同学,排第几名,反正是被我钻了个空子。
那修饰是说完了,我们看看类图如何修改,如图所示:
装饰者模式_第11张图片
修饰后的成绩单
装饰者模式_第12张图片
老爸查看修饰后的成绩单
装饰者模式_第13张图片
通过继承确实能够解决这个问题,老爸看成绩单很开心,然后就给签字了,但现实的情况
是很复杂的,可能老爸听我汇报最高成绩后,就直接乐开花了,直接签名了,后面的排名就没必要看了,或者老爸要先看排名情况,那怎么办?继续扩展?你能扩展多少个类?这还是一个比较简单的场景,一旦需要装饰的条件非常多,比如20个,你还通过继承来解决,你想象的子类有多少个?你是不是马上就要崩溃了!

好,你也看到通过继承情况确实出现了问题,类爆炸,类的数量激增,光写这些类不累死你才怪,而且还要想想以后维护怎么办,谁愿意接收这么一大摊本质相似的代码维护工作?并且在面向对象的设计中,如果超过两层继承,你就应该想想是不是出设计问题了,是不是应该重新找一条康庄大道了,这是经验值,不是什么绝对的,继承层次越多以后的维护成本越多,问题这么多,那怎么办?好办,我们定义一批专门负责装饰的类,然后根据实际情况来决定是否需要进行装饰,类图稍作修正,如图所示:
装饰者模式_第14张图片

修饰的抽象类
装饰者模式_第15张图片

最高成绩修饰
装饰者模式_第16张图片
排名情况修饰
装饰者模式_第17张图片
老爸查看修饰后的成绩单
装饰者模式_第18张图片
老爸一看成绩单,听我这么一说,非常开心,儿子有进步呀,从40多名进步到30多名,进步很大,躲过了一顿海扁。想想看,如果我还要增加其他的修饰条件,是不是就非常容易了,只要实现Decorator类就可以了!这就是装饰模式。

三.结论

优点

  • 装饰类和被装饰类可以独立发展,而不会相互耦合。换句话说,Component类无须知道Decorator类,Decorator类是从外部来扩展Component类的功能,而Decorator也不用知道具体的构件。
  • 装饰模式是继承关系的一个替代方案。我们看装饰类Decorator,不管装饰多少层,返回的对象还是Component,实现的还是is-a的关系。
  • 装饰模式可以动态地扩展一个实现类的功能,这不需要多说,装饰模式的定义就是如此。

缺点

对于装饰模式记住一点就足够了:多层的装饰是比较复杂的。为什么会复杂呢?你想想看,就像剥洋葱一样,你剥到了最后才发现是最里层的装饰出现了问题,想象一下工作量吧,因此,尽量减少装饰类的数量,以便降低系统的复杂度。

你可能感兴趣的:(设计模式,java,开发语言)