一、提出需求

咖啡馆订单系统项目(咖啡馆):

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

二、方案设计

1、方案一:较差的方案


方案一小结和分析

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

2、方案二:比较好点的方案

 前面分析到方案一,因为咖啡单品+调料组合会造成类的倍增,因此可以做改进,将调料内置到Drink类,这样
就不会造成类数量过多。从而提高项目的维护性。

方案设计如下图:

说明: milk,soy,choclate 可以设计为Boolean,表示是否要添加相应的调料。


方案二的问题分析

1. 方案2可以控制类的数量,不至于造成过多的类;
2. 在增删调料种类时,代码维护量仍然很大;
3. 考虑到添加多份调料时,可以将Boolean改成Int。

三、装饰者模式原理

1、方案设计图

2、针对上面的图说明

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

四、装饰者模式定义

1. 装饰者模式:动态的将新功能附加到对象上。在对象功能扩展方面,它比继承更有弹性,装饰者模式也体现了
开闭原则(ocp);
2. 这里提到的动态的将新功能附加到对象和ocp原则,接下来会在应用实例上会以代码的形式体现。

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

1、方案设计图

2、方案说明

1. Drink这个超类和前面基本一样;
2. ShortBlack等单品咖啡的设计也和前面一样;
3. Decorator是一个装饰类,含一个被装饰的对象(Drink obj);
4. Decorator的cost 进行费用的叠加,递归计算出价格。

3、订单

装饰者模式下的订单:2份巧克力+一份牛奶的LongBlack

订单说明:

1. Milk包含了LongBlack;
2. 一份Chocolate包含了(Milk+LongBlack);
3. 一份Chocolate包含了(Chocolate+Milk+LongBlack);
4. 这样不管是什么形式的单品咖啡+调料组合,通过递归方式可以方便的组合和维护。

订单分析

1. 有一份 Milk + LongBlack【milk装饰LongBlack】;
2. 使用一份Chocolate装饰【一份 Milk + LongBlack 】;
3. 使用一份chocolate装饰【chocolate+milk+longBlack】;
4. 当计算cost要递归的计算。

五、装饰者模式咖啡订单项目应用实例代码

1、代码结构图

2、示例代码

================================abstract class Drink 超类================================
package com.lj.akka.decoratormode.coffeebar
/*** @author Administrator* @create 2020-03-28*/
abstract class Drink {// coffee描述private var _description: String = _// _description的setter与getter方法def description: String = _descriptiondef description_=(value: String): Unit = {_description = value}// coffee价格private var _price: Float = _// _price的setter与getter方法def price: Float = _pricedef price_=(value: Float): Unit = {_price = value}def cost(): Float
}
==================================class Coffee extends Drink=================================
package com.lj.akka.decoratormode.coffeebar.differentcoffee
import com.lj.akka.decoratormode.coffeebar.Drink
/*** @author Administrator* @create 2020-03-28*/
class Coffee extends Drink {override def cost(): Float = {super.price}
}
==================================class DeCaf extends Coffee=================================
// 说明:其它种类的咖啡,它这个一样的写法都是集成Coffee类,并使用主构造器完成价格和名称描述
package com.lj.akka.decoratormode.coffeebar.differentcoffee
/*** @author Administrator* @create 2020-03-28*/
class DeCaf extends Coffee {// 使用主构造器super.description_=("DeCaf Coffee")super.price_=(10.0f)
}
===============================class Decorator extends Drink==============================package com.lj.akka.decoratormode.coffeebar.coffeedecorator
import com.lj.akka.decoratormode.coffeebar.Drink
/*** @author Administrator* @create 2020-03-28*/
class Decorator extends Drink{private var drink: Drink = nulldef this(drink: Drink) {thisthis.drink = drink}override def cost(): Float = {super.price + drink.cost()}// 获取信息是也需要递归获取override def description: String = {super.description + " && " + drink.description}
}
===============class Chocolate(drink: Drink) extends Decorator(drink)===============
// 其它的添加的配料写法都一样
package com.lj.akka.decoratormode.coffeebar.coffeedecorator
import com.lj.akka.decoratormode.coffeebar.Drink
/*** @author Administrator* @create 2020-03-28*/
class Chocolate(drink: Drink) extends Decorator(drink) {super.description_=("Chocolate")super.price_=(5f)
}
============================咖啡点单:object CoffeeBar============================
package com.lj.akka.decoratormode
import com.lj.akka.decoratormode.coffeebar.Drink
import com.lj.akka.decoratormode.coffeebar.coffeedecorator.{Chocolate, Milk}
import com.lj.akka.decoratormode.coffeebar.differentcoffee.{DeCaf, LongBlack}
/*** @author Administrator* @create 2020-03-28*/
object CoffeeBar {def main(args: Array[String]): Unit = {val order01: Drink = new DeCafval order01_name = order01.descriptionval order01_price = order01.cost()// 001顾客点的是DeCaf Coffee,价格10.0RMB.println(s"001顾客点的是${order01_name},合计${order01_price}RMB.")var order02: Drink = new LongBlackorder02 = new Milk(order02)order02 = new Chocolate(order02)order02 = new Milk(order02)val order02_name = order02.descriptionval order02_price = order02.cost()// 002顾客点的是Chocolate && Chocolate && Chocolate && LongBlack Coffee,合计26.0RMB.println(s"002顾客点的是${order02_name},合计${order02_price}RMB.")}
}

小结:从上面代码可以看出装饰者模式在代码维护上更加的复合OCP原则,使代码更优雅。

3、Java中装饰者模式的经典使用

Java的IO结构,FilterInputStream就是一个装饰者

对以前的知识回顾,加深基础知识!
学习来自:北京尚硅谷韩顺平老师—尚硅谷大数据技术之Scala
每天进步一点点,也许某一天你也会变得那么渺小!!!

第 17 章 设计模式(3 装饰者模式)相关推荐

  1. 设计模式学习----装饰器模式

    这两天本来是自在学习java collection Framework的Fail Fast底层机制,看到核心的部分时,突然意识到设计模式的问题,上大学到现在我还没有真正理解过设计模式的概念,于是用了大 ...

  2. 设计模式之装饰者模式--钢铁侠的形成

    前言 本文主要讲述java常见设计模式之装饰者模式,文中使用通俗易懂的案例,使你更好的学习本章知识点并理解原理,做到有道无术. 一.什么是装饰者模式 装饰者模式是23种设计模式中结构型模式的一种,它的 ...

  3. 设计模式之装饰器模式详解

    设计模式之装饰器模式详解 文章目录 设计模式之装饰器模式详解 一.什么是装饰器模式 二.装饰器模式的角色组成 三.装饰器模式通用写法示例 四.装饰器模式业务中的应用举例 五.装饰器模式优缺点 一.什么 ...

  4. Java设计模式(装饰者模式-组合模式-外观模式-享元模式)

    Java设计模式Ⅳ 1.装饰者模式 1.1 装饰者模式概述 1.2 代码理解 2.组合模式 2.1 组合模式概述 2.2 代码理解 3.外观模式 3.1 外观模式概述 3.2 代码理解 4.享元模式 ...

  5. 前端也要学系列:设计模式之装饰者模式

    什么是装饰者模式 今天我们来讲另外一个非常实用的设计模式:装饰者模式.这个名字听上去有些莫名其妙,不着急,我们先来记住它的一个别名:包装器模式. 我们记着这两个名字来开始今天的文章. 首先还是上< ...

  6. 设计模式 之 装饰者模式

    2019独角兽企业重金招聘Python工程师标准>>> 设计模式 之 装饰者模式 装饰模式指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能.它是通过创建一个包装对 ...

  7. 【设计模式】装饰者模式 ( 概念 | 适用场景 | 优缺点 | 与继承对比 | 定义流程 | 运行机制 | 案例分析 )

    文章目录 I . 装饰者模式概念 II . 装饰者模式适用场景 III . 装饰者模式优缺点 IV . 装饰者模式与继承对比 V . 装饰者模式相关设计模式 VI . 装饰者模式四个相关类 VII . ...

  8. 【设计模式】装饰器模式的使用

    问题来源 我们在进行软件系统设计的时候,有一些业务(如下图,一些通用的非功能性需求)是多个模块都需要的,是跨越模块的.把它们放到什么地方呢? 最简单的办法就是把这些通用模块的接口写好,让程序员在实现业 ...

  9. C#设计模式(9)——装饰者模式(Decorator Pattern)

    一.引言 在软件开发中,我们经常想要对一类对象添加不同的功能,例如要给手机添加贴膜,手机挂件,手机外壳等,如果此时利用继承来实现的话,就需要定义无数的类,如StickerPhone(贴膜是手机类).A ...

  10. go设计模式之装饰器模式

    go设计模式之装饰器模式 再写这篇文章时,我已经看了很多其他人发表的类似文章,大概看了这么多吧. 亓斌的设计模式-装饰者模式(Go语言描述) jeanphorn的Golang设计模式之装饰模式 七八月 ...

最新文章

  1. linux什么命令只显示ip,linux ip命令
  2. 科普:教你如何看懂 JavaGC 日志
  3. 用户画像从0到100的构建思路
  4. pc显示器分辨率 前端_五款高性价比PC显示器推荐 499元起
  5. zabbix db partition
  6. BugkuCTF-MISC题宽带信息泄露
  7. python getattr函数_Python中的getattr()函数详解
  8. Mysql 数据库默认值选 ‘‘“ 、Null和Empty String的区别
  9. HDU2092 整数解【暴力+韦达定理】
  10. [python] 解决OSError: Address already in use
  11. LAMMPS分子动力学模拟技术与应用 第一性原理计算方法及应用
  12. 数据库知识整理 - 并发控制(封锁、两段锁协议、意向锁)
  13. android 触摸 事件,Android触屏事件和MotionEvent详解
  14. 使用JavaScript获取当前时间方法(AM、PM)
  15. Java程序员月薪达到三万,需要技术水平达到什么程度?(文末送书)
  16. 手机html点击按钮复制,网页文字无法复制?按下手机这个键即可复制!网友:厉害了...
  17. 清华大学计算机崔勇,崔勇 简历 - 名人简历
  18. placement new 讲解
  19. 【java】环境变量安装
  20. 今天是2012年9月20日

热门文章

  1. SQL中的DML语句
  2. 电子商务平台到底是什么?这就告诉你!
  3. PW6276具有短路保护功能内部 集成软启动电路
  4. RAID磁盘阵列的几种模式
  5. python 生日悖论概率计算。
  6. 你真的了解DBA这份工作吗?
  7. 【CAN】CAN总线要点
  8. 基于全球价值链的电子商务整合创新问题研究[ 转]
  9. 杰克 - 鬼马海盗主角加勒比海盗系列的
  10. 登录功能图片验证码的实现