设计模式之装饰者模式(Decorator)-03

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

 

方案 1-较差的方案

这种方案把所有可能性都罗列出来继承了Drink

1) Drink 是一个抽象类,表示饮料
2) description 就是描述,比如咖啡的名字等
3) cost 就是计算费用,是一个抽象方法
4) Decaf 等等就是具体的单品咖啡,继承 Drink,并实现 cost 方法
5) Espresso&&Milk 等等就是单品咖啡+各种调料的组合,这个会很多..
6)  这种设计方式时,会有很多的类,并且当增加一个新的单品咖啡或者调料时,类的数量就会倍增( 类爆炸)

 

方案 2-好点的方案

前面分析到方案 1 因为咖啡单品+调料组合会造成类的倍增,因此可以做改进,将调料内置到 Drink
类,这样就不会造成类数量过多。从而提高项目的维护性(如图)=>同时违反 ocp,如果添加新的调料就会修改源代码,扩展性不好.

 

装饰者模式原理
1) 装饰者模式就像打包一个快递
    主体:比如:陶瓷、衣服 (Component)
    包装:比如:报纸填充、塑料泡沫、纸板、木板(Decorator)
2) Component 主体:比如类似前面的 Drink
3) ConcreteComponent 和 Decorator
    ConcreteComponent:具体的主体,比如前面的各个单品咖啡
4) Decorator: 装饰者,比如各调料.
    在如图的 Component 与 ConcreteComponent 之间,如果 ConcreteComponent 类很多,还可      以设计一个缓冲层,将共有的部分提取出来,抽象层一个类。


装饰者模式定义
1) 装饰者模式: 动态的将新功能附加到对象上。在对象功能扩展方面,它比 继承更有弹性( 递归),
装饰者模式也体现了开闭原则(ocp)
2) 这里提到的动态的将新功能附加到对象和 ocp 原则


用装饰者模式设计重新设计的方案

 

抽象父类Drink

//说明
//1. Drink 是表示饮品,是一个抽象类
abstract class Drink {
  var description = ""
  private var price = 0.0f

  def setDescription(description: String): Unit = {
    this.description = description
  }

  def getDescription(): String = {
    description + " 价格: " + this.getPrice()
  }

  def getPrice(): Float = {
    price
  }

  def setPrice(price: Float): Unit = {
    this.price = price
  }
  //将计算成本的方法做成一个抽象方法cost
  def cost(): Float
}

装饰者类,装饰Drink 

//这个就是Decorator装饰者
class Decorator extends Drink {

  //obj就是被装饰的对象Drink
  //obj可以是单品咖啡,也可以是单品咖啡+调料的组合
  private var obj: Drink = null

  def this(obj: Drink) {
    this
    this.obj = obj
  }
  //这里我们实现了cost,这里使用了递归方式
  override def cost(): Float = {

    super.getPrice() + obj.cost()
  }
  //获取信息时,也需要递归获取
  override def getDescription(): String = {

    super.getDescription() + "&&" + obj.getDescription()
  }
}

咖啡调料种类

class Chocolate(obj: Drink) extends Decorator(obj) {
  super.setDescription("Chocolate")
  //一份巧克力3.0f
  super.setPrice(3.0f)
}
class Milk(obj: Drink) extends Decorator(obj) {

  setDescription("Milk")
  setPrice(2.0f)
}

咖啡种类,如果以后扩展别的饮品就容易扩展了. 

//在Drink 和  单品咖啡,我做了一个缓冲层
//这里是为了扩展,针对当前项目可以不要
class Coffee extends Drink{
  override def cost(): Float = {
    super.getPrice()
  }
}
class DeCaf extends Coffee {

  //使用主构造器
  super.setDescription("DeCaf")
  super.setPrice(3.0f)
}
class LongBlack extends Coffee {
  //使用主构造器
  super.setDescription("LongBlack")
  super.setPrice(5.0f)
}

测试主程序 


object CoffeeBar {
  def main(args: Array[String]): Unit = {
    println("咖啡bar..")

    val order: Drink = new DeCaf //点DeCaf单品咖啡
    println("order1 price:" + order.cost()) //3.0
    println("order1 desc:" + order.getDescription())

    println("------------------------------------------")
//  点一份LongBlack,并加入1份Milk 和 2份Chocolate
    var order2: Drink = new LongBlack //5.0
    order2 = new Milk(order2) //2.0
    order2 = new Chocolate(order2)//3.0
    order2 = new Chocolate(order2)//3.0
    order2 = new NewMilk(order2)
//
    println("order2 price:"+order2.cost()); //
    println("order2 desc:"+order2.getDescription())
//
    //java.io.FilterInputStream
  }
}

装饰设计模式解决:对一组类进行功能的增强。

包装:写一个类(包装类)对被包装对象进行包装;

 * 1、包装类和被包装对象要实现同样的接口;

 * 2、包装类要持有一个被包装对象;

 * 3、包装类在实现接口时,大部分方法是靠调用被包装对象来实现的,对于需要修改的方法我们自己实现;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值