咖啡店的项目引出装饰者模式 | 学习笔记

简介: 快速学习咖啡店的项目引出装饰者模式

开发者学堂课程【Scala 核心编程 - 进阶咖啡店的项目引出装饰者模式学习笔记,与课程紧密连接,让用户快速学习知识。

课程地址https://developer.aliyun.com/learning/course/610/detail/9138


咖啡店的项目引出装饰者模式


内容介绍:

一、装饰者模式

二、方案1-较差的方案

三、方案1-小结与分析

四、方案2-较好的方案

五、方案2的问题分析

六、体系图

七、装饰者模式原理

讲解的内容,首先是设计模式,还有示范型上下界,视图界定上下文界定还有协变逆变不变。


一、装饰者模式(Decorator)

看一个项目需求

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

1)咖啡种类/单品咖啡:Espresso(意大利浓咖啡)、ShortBlack、LongBlack(美式咖啡)、Decaf(无因咖啡)

2)调料:Milk、Soy(豆浆)、Chocolate

3)要求在扩展新的咖啡种类时,具有良好的扩展性、改动方便、维护方便

4)使用OO(面向对象)的来计算不同种类咖啡的费用:客户可以点单品咖啡,也可以单品咖啡+调料组合。

比如说要点一份意大利浓咖啡,然后要求加一份牛奶,然后去计算价格,或者是点了一份美式咖啡,还要加两份巧克力,然后去算总的价格。


二、方案1-较差的方案

image.png

先抽象出来一个类叫 drink,不管是什么样单品它都是饮料,有一个描述为description,Cost 是计算费用,较差的方案就是单品单独设计一个类,比如有一个人再点一份意大利咖啡,她说她想加一份牛奶,这就成为了一个新的组合,如果espresso 再加一份牛奶和豆浆,就又成为了一个类,这样会出现类爆炸现象,现在单品咖啡有四个,调料有三种,一个单品就会对应七个类,加上单品本身就有八种,然后再乘以四,就有32种可能,就会出现类爆炸。


三、方案1-小结与分析

1) Drink 是一个抽象类,表示饮料

2) description 就是描述,比如咖啡的名字等3) cost就是计算费用,是一个抽象方法

4) Decaf 等等就是具体的单品咖啡,继承Drink,并实现cost方法

5) Espresso&&Milk 等等就是单品咖啡+各种调料的组合,这个会很多..

6)这种设计方式时,会有很多的类,并且当增加一个新的单品咖啡或者调料时,类的数量就会倍增(爆炸)


四、方案2-较好的方案

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

说明:

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

这样设计过后,类只要有四个就可以了,将来在设计的时候,比如说想要一份豆浆,直接在cost里面判断有没有就可以了


五、方案2的问题分析

1)方案2可以控制类的数量,不至于造成过多的类。

2)在增删调料种类时,代码维护量仍然很大。如果将来drink增加了一份调料,比如说是豆腐脑,那么就需要修改drink,就会很麻烦,这就违反了ocp原则,因为再加一个单品的时候,代码的变化是很大的。

3)考虑到添加多份调料时,可以将Boolean改成Int


六、体系图

一个项目的类的体系图,里面有很多的类,包括里面有继承关系。

1.在开发中要求尽量的遵守 ocp

开闭原则

将来如果要增加一个功能,这些代码尽量都不要去进行修改,可以直接加一个类进去,把新类加进去功能就增加了,整个体系是没有发生变化的。

2. ocp (开闭原则):通过增加新的类,来扩展功能.

开闭原则:开:指的是功能扩展开放,闭:不要去修改已有的代码


七、装饰者模式原理

1)装饰者模式就像打包一个快递

主体:比如:陶瓷、衣服

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

2) Component

主体:比如类似前面的 Drink

3) ConcreteComponent 和 Decorator

ConcreteComponent:具体的主体,

比如前面的各个单品咖啡

Decorator:装饰者,比如各调料.

4)在如图的 Component 与 ConcreteComponent 之间,如果

ConcreteComponent 类很多,还可以设计一个缓冲层,将共有的部分提取出来,抽象层一个类。

相关文章
|
缓存
银河麒麟server-V10配置镜像源
银河麒麟server-V10配置镜像源
15008 1
|
关系型数据库 MySQL 数据库
django4版本提示 django.db.utils.NotSupportedError: MySQL 8 or later is required (found 5.7.26)
在学习Django时,用户遇到`django.db.utils.NotSupportedError`,提示需要MySQL 8.0.25或更高版本,但其系统上是5.7.26。为解决这个问题,用户决定不升级MySQL,而是选择注释掉Django源码中的数据库版本检查。通过Python命令行找到Django安装路径,进入`db/backends/base/base.py`,注释掉`self.check_database_version_supported()`函数
1620 0
|
11月前
|
SQL 监控 数据可视化
完全开源!国内首个完全开源JAVA企业级低代码平台
JeeLowCode 是一款专为企业打造的 Java 企业级低代码开发平台,通过五大核心引擎(SQL、功能、模板、图表、切面)和四大服务体系(开发、设计、图表、模板),简化开发流程,降低技术门槛,提高研发效率。平台支持多端适配、国际化、丰富的组件库和灵活的布局设计,适用于 OA、ERP、IoT 等多种管理信息系统,帮助企业快速实现数字化转型。
完全开源!国内首个完全开源JAVA企业级低代码平台
|
XML 缓存 SpringCloudAlibaba
Spring循环依赖解决方案
循环依赖其实就是一个闭环,像图中情况二Spring在创建单例bean A的时候发现引用了B,这时候就会去容器中查找单例bean B,发现没有然后就会创建bean B,创建bean B时又发现引用了bean A,这时候又会去容器中查找bean A,发现没有,接下来就会循环重复上面的步骤,这是不是像极了死锁?其实循环依赖就是一个死循环的过程
297 0
Spring循环依赖解决方案
|
存储 关系型数据库 MySQL
PolarDB的特点
【5月更文挑战第13天】PolarDB的特点
596 1
elasticsearch 怎么删除过期的数据
使用elasticsearch收集日志进行处理,时间久了,很老的数据就没用了或者用途不是很大,这个时候就要对过期数据进行清理.但是es5.0之后就不支持ttl,那怎么办呢? 1,请使用官方的工具elasticsearch-curator 2,使用delete-by-query方法删除特定时间范围的数据 第一种这里不再介绍了,直接看官网吧,主要说下第二种
|
存储 安全 JavaScript
npm 账户的创建、测试、登录
npm 账户的创建、测试、登录
|
机器学习/深度学习 人工智能 算法
人工智能LLM模型:奖励模型的训练、PPO 强化学习的训练、RLHF
人工智能LLM模型:奖励模型的训练、PPO 强化学习的训练、RLHF
人工智能LLM模型:奖励模型的训练、PPO 强化学习的训练、RLHF
|
SQL 存储 索引
详细了解SQL中delete,drop,truncate的区别和不同
详细了解SQL中delete,drop,truncate的区别和不同
636 1
|
SQL 关系型数据库 MySQL
mysql加索引的时候到底会不会锁表.深入解析
默认大部分情况下 mysql的在线DDL可以让我们加索引的时候不锁表,但是也有一些限制的场景,跟本次问题相关的限制情况是在线DDL 操作完成之前,它必须等待在表上持有元数据锁(Metadata Lock)的事务提交或回滚。
12515 1
mysql加索引的时候到底会不会锁表.深入解析