设计模式之三:装饰者模式

装饰者模式可以在不修改任何底层代码的情况下,给对象赋予新的职责(使用对象组合的方式,在运行时装饰类)。

假定星巴兹咖啡需要更新订单系统,而他们原先类的设计如图:

 现在他们考虑客户可以选择添加调料(蒸奶,豆浆,摩卡等)到这几种咖啡中。

实现一:每种调料和咖啡的组合都形成一个新类,然后覆盖cost方法。这样会造成“类爆炸”,使得维护起来特别困难(假设需要新增加一种口味,那么类成几何倍数增长。如果要改变一种调味的价格,也需要修改许多的类)

 实现二:利用实例变量和继承来追踪这些调料。

 可以通过set方法来设置添加调料的种类,然后在基类的cost计算调料的价格。子类中的cost再调用父类的cost并加上自己的价格。

实现二的设计存在以下的一些问题:

  • 一旦出现新的调料,我们就需要添加新的方法,并改变超类中的cost方法。
  • 对以后开发出的新饮料而言,某些调料可能并不适合,但子类仍将继承这些方法。
  • 顾客想要双倍摩卡咖啡。

(利用继承设计子类的行为,是在编译时静态决定的,而且所有子类都会继承到相同行为。然而,如果利用组合的做法扩展对象行为,就可以在运行时动态进行扩展)

设计原则:类应该对扩展开放,对修改关闭

对修改关闭是因为,现有代码是正确的,如果允许修改,则容易引入bug。

实现三:装饰者模式

  1. 拿一个DarkRoast对象
  2. 以摩卡对象装饰它
  3. 以奶泡对象装饰它
  4. 调用cost方法,并依赖委托将调料价格加上

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

  • 装饰者和被装饰对象有相同的超类型
  • 可以用一个或多个装饰着包装一个对象
  • 装饰者和被装饰对象有相同的超类型,所以在任何需要原始对象(被包装的)的场合,可以用装饰过的对象替代
  • 装饰者可以在被装饰者行为之前/之后,加上自己的行为
  • 对象可以在任何时候被装饰,可以运行时动态地,不限量地用装饰者装饰

(利用继承来达到“类型匹配”,而不是利用继承获得“行为”)

class Beverage
{
private:String description = "Unknown Beverage";public:virtual String getDescription(){return description;}virtual double cost() = 0;
};class Espresson : public Beverage
{
public:Espresson(){description = "Espresson";}double cost(){return 1.99;}
};
class Mocha : public Beverage
{
private:Beverage* beverage;public:Mocha(Beverage* beverage){this->beverage = beverage;}String getDescription(){return beverage->description() + ".Mocha";}double cost(){.20 + beverage->cost();}
};
// 测试代码int main()
{// 不知道这样内存都删干净了没有,或者用智能指针更好Beverage* beverage = new Espresson();Beverage* beverage1 = new Mocha(beverage);Beverage* beverage2 = new Whip(beverage1);delete beverage;delete beverage1;delete beverage2;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/14588.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网站弱口令爆破小脚本

介绍 weakpass_exploit,网站弱口令爆破小脚本 优点: 绕过图形验证码 绕过前端数据加密 不足: ddddocr识别不够精确 单线程 注: 本项目所有文件仅供学习和研究使用,请勿使用项目中的技术源码用于非法用途,任何人造成的任何负面影响,与…

Spring Boot 中的 Future 接口是什么,如何使用

Spring Boot 中的 Future 接口是什么,如何使用 在异步编程中,我们通常需要处理一些耗时的操作。一种常见的做法是使用 Future 接口来代表一个异步操作的结果。在 Spring Boot 中,Future 接口被广泛应用于异步编程中,本文将介绍 S…

LNMP实战部署(电影网站搭建)

第三阶段基础 时 间:2023年7月5日 参加人:全班人员 内 容: 目录 LNMP架构及应用部署:(单台服务器部署) 一、安装nginx:(源码安装) 二、安装mysql数据库&#xf…

OpenCV使用ellipse()函数来绘制一个椭圆

/*** void ellipse(* InputOutputArray img, // 图像* Point center, // 椭圆原心* Size axes, // 椭圆x轴长度的一半,y轴长度的一半* double angle, // 椭圆旋转角度* double startAngle, // 起始角度* double endAngle, // 终止角度* const Scalar& color, // 椭圆颜色*…

AutoHotkey配置鼠标光标在双屏幕之间瞬移

双屏幕带来的问题 使用双屏幕会带来两个问题:一个是窗口的切换移动不方便,另一个是鼠标的切换移动不方便。 如果需要将屏幕 A 的窗口快速移动到屏幕 B,可以用过 win shift 左右键来实现。 但是令人头疼的一个问题是鼠标还停留在屏幕 A&a…

Dockerfile自定义镜像 - 基于 java:8-alpine 镜像,将一个Java项目构建为镜像

目录 一、前置知识 1.镜像结构 2.Dockerfile是什么 二、自定义一个 java 项目镜像 1.创建一个空目录,在这个空目录中创建一个文件,命名为 DockerFile,最后将 java 项目打包成 jar 包,放到这个目录中 2.编写 Dockerfile 文件 …

K8S-概述

k8s是什么? go语言开发的开源的跨主机的容器编排工具;全称是kubernetes; k8s的组件: master: ①kube-apiserver 所有服务统一的访问入口,无论对内还是对外; ②kube-controller-manager 资源…

Visual studio 2015下载安装以及缺包提示的处理方法

最近要加入的比赛团队需要用到Visual studio 2015,百度后找到很多资源,自己也转到了百度网盘。中英文都有,需要的可以下载。 链接:https://pan.baidu.com/s/12gpVwXfQxfdkXub-IwhWFw?pwds325 提取码:s325 --来自百…

Docker 私有仓库 harbor 搭建

🎈 作者:Linux猿 🎈 简介:CSDN博客专家🏆,华为云享专家🏆,Linux、C/C、云计算、物联网、面试、刷题、算法尽管咨询我,关注我,有问题私聊! &…

有哪些做的问卷调查的工具?

想要洞察市场变化、了解某个特定群体的喜好等情况,使用问卷调查是常见的方法。而互联网的发展,越来越多的人转战网络问卷,而功能各异的问卷工具却让人挑花眼。今天,我们精准针对大家的需求和常见的一些问题,为大家聊一…

C#一个开源跨平台的 HTTP 客户端库——RestSharp

一、RestSharp简介 GitHub - restsharp/RestSharp: Simple REST and HTTP API Client for .NETSimple REST and HTTP API Client for .NET. Contribute to restsharp/RestSharp development by creating an account on GitHub.https://github.com/restsharp/RestSharp …

Kafka的保姆级简易安装启动、关闭注意事项、简单使用

一.安装: 1.1Windows本机tar包安装 1.下载tar包 地址:Apache Download Mirrors,点击下面的连接先将tar包下载下来 2.解压到任意地址但自己要记得位置 3.进入到config文件找到server.properties更改信息 搜索,然后找到下面的地…