zoukankan      html  css  js  c++  java
  • 07 装饰者模式

    1 星巴克咖啡订单项目

    星巴克咖啡订单项目(咖啡馆):

    • 咖啡种类/单品咖啡:Espresso(意大利浓咖啡)、ShortBlack、LongBlack(美式咖啡)、Decaf(无因咖啡)
    • 调料:Milk、Soy(豆浆)、Chocolate
    • 要求在扩展新的咖啡种类时,具有良好的扩展性、改动方便、维护方便
    • 使用OO来计算不同种类咖啡的费用:客户可以点单品咖啡,也可以单品咖啡+调料组合。
    2 传统解决方案

    方案一:

    classDiagram class Espresso{ cost() void } class ShortBlack{ cost() void } class LongBlack{ cost() void } class Decaf{ cost() void } class EspressoANDMilk{ cost() void } class EspressoANDSoy{ cost() void } class EspressoANDChocolate{ cost() void } class Drink{ <<interface>> discription getDescription() cost() } Espresso --|> Drink : 继承 ShortBlack --|> Drink : 继承 LongBlack --|> Drink : 继承 Decaf --|> Drink : 继承 EspressoANDMilk --|> Drink : 继承 EspressoANDSoy --|> Drink : 继承 EspressoANDChocolate --|> Drink : 继承
    • Drink 是一个抽象类,表示饮料
    • description就是对咖啡的描述,比如咖啡的名字
    • cost()方法就是计算费用,Drink 类中做成一个抽象方法
    • Decaf 就是单品咖啡,继承Drink。并实现cost
    • EspressANDMilk就是单品咖啡+词料,这个组合很多
      这样设计,会有很多类,当我们增加一个单品咖啡,或者一个新的调料,类的数量就会倍增,就会出现类爆炸

    方案二:

    classDiagram class Espresso{ cost() void } class ShortBlack{ cost() void } class LongBlack{ cost() void } class Decaf{ cost() void } class Drink{ <<interface>> discription milk soy chocolate getDescription() cost() hasMilk() setMilk() } Espresso --|> Drink : 继承 ShortBlack --|> Drink : 继承 LongBlack --|> Drink : 继承 Decaf --|> Drink : 继承
    • 方案2可以控制类的数量,不至于造成很多的类在增加或者删除调料种类时,代码的维护量很大
    • 考虑到用户可以添加多份调料时,可以将hasMilk 返回一个对应int
    • 考虑使用装饰者模式
    3 装饰者模式

    ​ 装饰者模式:动态的将新功能附加到对象上。在对象功能扩展方面,它比继承更有弹性,装饰者模式也体现了开闭原则。

    4 装饰者模式原理
    1. 装饰者模式就像打包一个快递

      主体(被装饰者)比如:陶瓷、衣服(Component)

      包装:比如:报纸填充、塑料泡沫、纸板、木板(Decorator)

    2. Component
      主体:比如类似前面的Drink

    3. ConcreteComponentConcreteComponent:具体的主体,比如前面的各个单品咖啡

    4. Decorator:装饰者,比如各调料
      在如图的ComponentConcreteComponent之间,如果ConcreteComponent类很多,还可以设计一个缓冲层,将共有的部分提取出来,抽象成一个类。

      classDiagram class Component{ <<abstract>> methodA() methodB() } class Decorator{ component Component methodA() methodB() } class ConcreteDecorator{ methodA() methodB() } class ConcreteComponent{ methodA() methodB() } Decorator --|> Component : 继承 ConcreteComponent --|> Component : 继承 ConcreteDecorator --|> Decorator : 继承 Decorator o-- Component : 聚合
    5 装饰者模式解决星巴克咖啡问题
    classDiagram class Espresso{ cost() void } class ShortBlack{ cost() void } class LongBlack{ cost() void } class Decaf{ cost() void } class Drink{ <<interface>> discription getDescription() cost() } Espresso --|> Coffee : 继承 ShortBlack --|> Coffee : 继承 LongBlack --|> Coffee : 继承 Decaf --|> Coffee : 继承 Coffee --|> Drink : 继承 class Decorator{ Drink drink getDescription() cost() } class Milk{ getDescription() cost() } class Soy{ getDescription() cost() } class Chocolate{ getDescription() cost() } Decorator --|> Drink : 继承 Decorator *-- Drink : 组合 Milk --|> Decorator : 继承 Soy --|> Decorator : 继承 Chocolate --|> Decorator : 继承
    • Drink类就是前面说的抽象类,component

    • shortBlack就单品咖菲

    • Decorator是一个装饰类,含有一个被装饰的对象(Drink drink)

    • Decorator 的cost方法进行一个费用的累加计算,递归的计算价格

    • Milk包含了LongBlack

    • 一份Chocolate包含了(Milk+LongBlack)

    • 一份Chocolate包含了(Chocolate+Milk+LongBlack)

    • 这样不管是什么形式的单品咖啡+调料组合,通过递归方式可以方便的组合和维护。

    6 装饰者模式在JDK的应用
    classDiagram class InputStream{ <<interface>> } FileInputStream ..|> InputStream : 实现 StringInputStream ..|> InputStream : 实现 ByteInputStream ..|> InputStream : 实现 FilterInputStream --|> InputStream : 继承 BufferInputStream --|> FilterInputStream : 继承 DataInputStream --|> FilterInputStream : 继承 LineNumberInputStream --|> FilterInputStream : 继承
    DataInputStrcam dis = new DataInputStream(new FileInputStream("d:llabc.txt"));
    System.out.println(dis.read));
    dis.close();
    
    • InputStream是抽象类,类似我们前面讲的 Drink
    • FileInputStreamInputStream子类,类似我们前面的 DeCaf, LongBlack
    • FilterInputStreamInputStream子类:类似我们前面的Decorator修饰者
    • DataInputStreamFilterInputStream子类,具体的修饰者,类似前面的Milk, Soy
    • FilterInputStream类有protected volatile InputStream in;即含被装饰者
      分析得出在jdk的io体系中,就是使用装饰者模式
  • 相关阅读:
    一个简单的瀑布流效果
    C#遇到的一些奇怪问题
    能够按页号提取word文档文本内容的小程序,由C#实现
    设计模式学习之简单工场模式
    设计模式学习之策略模式
    检查机器是否安装了.NET Framework 或已经安装了哪些.net版本
    书籍清单
    使用Func<T>对对象进行排序
    定义一个委托的三种形式
    设计模式学习之设计原则
  • 原文地址:https://www.cnblogs.com/nojacky/p/13922690.html
Copyright © 2011-2022 走看看