装饰者模式 订阅
装饰模式指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。 展开全文
装饰模式指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
信息
外文名
Decorator Pattern
类    别
设计模式
又    名
装饰者模式
中文名
装饰模式
设计原则
多用组合,少用继承
装饰模式定义
23种设计模式之一,英文叫Decorator Pattern,又叫装饰者模式。装饰模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
收起全文
精华内容
下载资源
问答
  • 装饰者模式

    千次阅读 2017-04-17 11:11:56
    装饰者模式

    这篇博客记录一下装饰者模式。


    我们首先借用一下Head First中的例子,来看看装饰者模式涉及的应用场景。

    假设我们需要开发一个饮料计费系统,如下图所示。
    SouthEast

    Beverage作为所有饮料的父类(抽象类或接口均可),
    定义了一个cost方法,用于计算饮料的价格。

    起初定义了四种基本的饮料,HouseBlend、DarkRoast、Decaf和Espresso。
    这些饮料均继承Beverage,并实现各自的cost方法。


    在上文的场景下,假设客户在购买饮料时,
    可以选择性地向基本饮料中加入不同的调料。
    基本饮料加入调料后,就变成了一种“新”的饮料,
    需要重新实现cost方法。

    如果我们利用继承的方式,实现这些“新”的饮料,
    那么整个计费系统的类图将变成如下的结构:
    SouthEast

    如上图所示,我们仅添加了两种调料milk和tea,
    但整个设计体系中立马新增了许多子类。
    容易预见,随着基本饮料和调料种类的增加,
    这些子类的数量会进一步增多,达到一个无法维护的数量。

    试想一下,如果某个基本饮料或调料的价格发生改变,
    那么就有许多类涉及的代码需要调整,维护这样一种代码,
    无疑是程序员的噩梦。


    针对这种问题,有的朋友可能会这么解决:
    SouthEast

    在父类Beverage中增加标志位,来表示是否添加了某种调料。
    同时,增加对应的设置和判断接口。
    这么一来,子类在计算价格时,就可以通过父类的接口,
    判断是否添加了某种饮料,然后根据判断结果来计算价格。

    通过这种方式,就可以大量地减少子类的数量,
    整个设计结构清晰易懂。

    然而,这么设计也有一个致命的缺陷。
    如果新增了调料的种类,那么每个子类的cost方法还是需要重写。
    同时,随着调料种类的增加,子类的cost方法中,
    必然存在大量用于判断是否含有某种饮料的判断语句。

    从整体来看,这种设计方式还是不够优雅,
    违背了对扩展开发,对修改关闭的设计原则。


    为了解决这类问题,就需要使用本篇博客的主角装饰者模式了。

    整个装饰者的设计思路基本上可以用下图表示:
    SouthEast

    如上图所示,假设我们需要一个加了Milk和Tea的HouseBlend。
    那么我们可以建立Milk和Tea的类,继承自Beverage。

    在代码运行时,我们可以动态地用Tea来包装HouseBlend,得到的一个Beverage对象;
    然后,继续用Milk来包装这个新的Beverage对象,得到最终的Beverage。
    此时,Milk和Tea类就可以看作HouseBlend的装饰者对象。

    在计算整体的价格时,我们可以直接调用最终的Beverage的cost接口。
    我们已经知道,最外层的实际上是个装饰者对象。
    于是,装饰者对象会进一步调用其持有的Beverage对象的cost接口。
    如果下一个Beverage对象,仍然是个装饰者,
    那么它会进一步调用其持有的Beverage对象的cost接口。

    通过如图所示的递归调用,最后将调用到基本饮料的cost接口,
    得到基本饮料的价格。
    然后,在基本饮料价格的基础上,
    逐步增加调料本身的价格,就可以得到最终的价格。

    通过这种方式,不论调料如何改变,我们都容易写出清晰简单的代码。


    现在,是时候来看看装饰者模式的定义和结构图了。

    装饰者模式动态地将责任附加到对象上。
    若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

    SouthEast

    上图的Component是被装饰对象的父类,
    ConcreteComponent是实际的被装饰对象。

    Decorator是装饰对象的父类或共同接口;
    ConcreteDecoratorA和ConcreteDecoratorB是实际的装饰者对象,
    这些对象将持有Component对象的引用,同时作为Component的子类。

    对应装饰者模式的结构图,我们看看上述场景改良后的设计结构:
    SouthEast

    对比上文的装饰者模式结构图,新的设计应该是比较容易理解的。


    在本文的最后,我们看看装饰者模式的一个实际应用场景,
    Java IO中输入流设计结构:
    SouthEast

    在了解装饰者模式后,再看下面的代码,是不是容易理解的多:

    .............
    InputStream in = new BufferedInputStream (
            new FileInputStream("test.txt"));
    .............
    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 15,386
精华内容 6,154
关键字:

装饰者模式