面向对象设计模式:结构型模式之装饰器模式

news2025/7/22 4:25:10

一、引入

  • 咖啡馆订购系统

  • Initial 初始

    • 4 种咖啡
      • House blend (混合咖啡)
      • Dark Roast (深度烘培)
      • Decaf (低咖啡因咖啡)
      • Espresso (意式浓缩咖啡)
        在这里插入图片描述
        在这里插入图片描述
  • 需求变更:客户可以加料(咖啡、牛奶、糖等)

    • steamed milk
    • soy
    • mocha
    • Whip

使用继承:类爆炸 NO
在这里插入图片描述
修改父类:Beverage
在这里插入图片描述
需求倘若变更:料种类增加、料价格变化,需要修改 Beverage 类

Classes should be open for extension, but closed for modification:开放封闭原则,对修改封闭

No

在这里插入图片描述

Decorator…

二、装饰器模式

aka:Wrapper (包装器)

2.1 Intent 意图

  • Attach additional responsibilities to an object dynamically. 可动态地将其他职责附加到对象上.
  • Decorators provide a flexible alternative to subclassing for extending functionality. 装饰器为扩展功能提供了一种替代子类化的灵活替代方案.
    • Dynamically extension
    • Better than inheritance

2.2 Applicability 适用性

  • To add responsibilities to individual objects dynamically without affecting other object.
  • When extension by subclassing is impractical. 当子类化扩展是不切实际的.
    • 如,子类数量爆炸

2.3 类图

在这里插入图片描述

  • Component: defines the interface for objects that can have responsibilities added to them dynamically. 为可以动态地添加职责的对象定义接口
  • ConcreteComponent: defines an object to which additional responsibilities can be attached. 定义一个可以附加其他责任的对象.
  • Decorator: maintains a reference to a Component object and defines an interface that conforms to Component’s interface. 维护对 Component 对象的引用,并定义一个符合 Component 接口的接口
  • ConcreteDecorator: adds responsibilities to the component. 向组件添加职责

2.4 优缺点

  • 优点
    • More flexibility than static inheritance. 比静态继承更灵活
      • With Decorators, responsibilities can be added and removed at runtime simply by attaching and detaching them.
    • 避免"类爆炸"
    • 通过排列和组合,可以创建许多行为组合
    • 装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能
  • 缺点
    • Lots of little objects
    • A decorator and its component are not same
    • 多层装饰比较复杂

2.5 应用实例:Java IO 类

InputStream and OutputStream 字节流
Reader and Writer 字符流
在这里插入图片描述
FilterInputStream:protected volatile InputStream in;
在这里插入图片描述
FilterInputStream 与 InputStream 为组合和被组合关系

与装饰器设计模式类图相符!

在这里插入图片描述

public class InputStreamToReader {

	public static void main(String[] args) throws IOException {
		FileInputStream in = new FileInputStream("test.dat");
		BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(in));
		String string;
		while((string=bufferedReader.readLine())!=null)
			System.out.println(string);
		
		bufferedReader.close();
		in.close();
	}

}

2.6 应用实例:咖啡馆订购系统

  • 饮品抽象类:Beverage
public abstract class Beverage {
	protected String description = "Unknown Beverage";

	public String getDescription() {
		return description;
	}

	public abstract double cost();
}
  • 咖啡类:继承 Beverage
public class DarkRoast extends Beverage {

	public DarkRoast() {
		description = "DarkRoast";
	}

	public double cost() {
		return .99;
	}
}

public class Espresso extends Beverage {

	public Espresso() {
		description = "Espresso";
	}

	public double cost() {
		return 1.99;
	}
}
public class HouseBlend extends Beverage {

	public HouseBlend() {
		description = "House Blend Coffee";
	}

	public double cost() {
		return .89;
	}
}
  • 装饰器:CondimentDecorator
public abstract class CondimentDecorator extends Beverage {
	public abstract String getDescription();
}
  • 装饰器子类:ConcreteDecorator
public class Mocha extends CondimentDecorator {
	Beverage beverage;

	public Mocha(Beverage beverage) {
		this.beverage = beverage;
	}

	public String getDescription() {
		return beverage.getDescription() + ", Mocha";
	}

	public double cost() {
		return .20 + beverage.cost();
	}
}
public class Soy extends CondimentDecorator {
	Beverage beverage;

	public Soy(Beverage beverage) {
		this.beverage = beverage;
	}

	public String getDescription() {
		return beverage.getDescription() + ", Soy";
	}

	public double cost() {
		return .15 + beverage.cost();
	}
}

public class Whip extends CondimentDecorator {
	Beverage beverage;

	public Whip(Beverage beverage) {
		this.beverage = beverage;
	}

	public String getDescription() {
		return beverage.getDescription() + ", Whip";
	}

	public double cost() {
		return .10 + beverage.cost();
	}
}
  • 使用与测试:
public class StarbuzzCoffee {

	public static void main(String[] args) {
		Beverage beverage = new Espresso();
		System.out.println(beverage.getDescription() + " $" + beverage.cost());

		Beverage beverage2 = new DarkRoast();
		beverage2 = new Mocha(beverage2);
		beverage2 = new Mocha(beverage2);
		beverage2 = new Whip(beverage2);
		System.out.println(beverage2.getDescription() + " $" + beverage2.cost());

		Beverage beverage3 = new HouseBlend();
		beverage3 = new Soy(beverage3);
		beverage3 = new Mocha(beverage3);
		beverage3 = new Whip(beverage3);
		System.out.println(beverage3.getDescription() + " $" + beverage3.cost());
	}
}

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue2的基本内容(二)

目录 一、props配置 二、全局事件总线 1.作用 2.原理 3.使用 三、插槽 1.默认插槽 2.具名插槽 3.作用域插槽 四、Vuex 1.vuex是什么 2.vuex工作流程 3.vuex的API (1)state (2)state辅助函数mapState (…

Linux 练习六 (IPC 管道)

文章目录1 标准管道流2 无名管道(PIPE)3 命名管道(FIFO)3.1 创建删除管道文件3.2 打开和关闭FIFO文件3.3 管道案例:基于管道的客服端服务器程序使用环境:Ubuntu18.04 使用工具:VMWare workstati…

【C++】STL——string类的模拟实现

文章目录👉string类👈📕 概念📕 成员变量📕 构造函数、析构函数📕 size() 、getstr() 函数📕 拷贝构造📕 赋值重载📕 迭代器📕 运算符重载📕 尾插…

如何管控第三方软件,保护企业数据安全?

日前,密码管理供应商LastPass公布了关于其数据泄露事件的调查新进展。据其透露,这是一起“二次协同攻击”事件。LastPass在2022年8月、12月先后披露的两起违规事件,这两起事件的攻击链有关联。在此次攻击事件中,LastPass发现恶意黑…

王道计算机组成原理课代表 - 考研计算机 第五章 中央处理器 究极精华总结笔记

本篇博客是考研期间学习王道课程 传送门 的笔记,以及一整年里对 计算机组成 知识点的理解的总结。希望对新一届的计算机考研人提供帮助!!! 关于对 “中央处理器” 章节知识点总结的十分全面,涵括了《计算机组成原理》课…

C++基础——C++相比C语言的新特性梳理总结(C++新特性、输入输出方式、命名空间namespace)

【系列专栏】:博主结合工作实践输出的,解决实际问题的专栏,朋友们看过来! 《QT开发实战》 《嵌入式通用开发实战》 《从0到1学习嵌入式Linux开发》 《Android开发实战》 《实用硬件方案设计》 长期持续带来更多案例与技术文章分享…

论文翻译 | Momentum Contrast for Unsupervised Visual Representation Learning(前三章)

前言: 上一次读恺明大神的文章还是两年前,被ResNet的设计折服得不行,两年过去了,我已经被卷死在沙滩上 Momentum Contrast for Unsupervised Visual Representation Learning 摘要 我们提出了针对无监督表征学习的方法MOCO,利用…

上门按摩预约APP源码-东郊到家源码(开发,PHP,平台搭建)

一、什么是上门按摩预约APP源码? 上门按摩预约APP源码是一款家政服务类型的APP,可以帮忙用户在家就能享受按摩的服务。APP源码分两端,一端是用户端,另外一端是技师端。采用的技术,前端是安卓IOS,后端是PHP&…

java_Day004

1.二维数组 二维数组的创建与初始化(java是支持规则数组和不规则数组的) 例:int[][] array {{1,2},{2,3}{3,4,5}}; 结构如下: 二维数组的遍历: 例子: Testpublic void test21(){int[][] array new int[…

C++学习记录——십이 vector

文章目录1、vector介绍和使用2、vector模拟实现insert和erase和迭代器失效补齐其他函数深浅拷贝难点思考1、vector介绍和使用 vector可以管理任意类型的数组&#xff0c;是一个表示可变大小数组的序列容器。 通过vector文档来看它的使用。 #include <iostream> #inclu…

集群、分布式的理解

一、单机模式小型系统相对简单&#xff0c;所有的业务全部写在一个项目中&#xff0c;部署服务到一台服务器上&#xff0c;所有的请求业务都由这台服务器处理&#xff0c;这就是单机模式。显然&#xff0c;当业务增长到一定程度的时候&#xff0c;服务器的硬件会无法满足业务需…

强化学习 | 课堂笔记 | 第三课 MP的便利性,随机逼近方法

一、回顾 一、值函数、贝尔曼方程、贝尔曼最优方程 二、最优值函数 三、ADP 3.1 VI 3.2 PI 四、ADP可以使用的条件 五、Q函数 六、解决问题的方案 &#xff08;指的是解决“四 ADP可以使用的条件”中的三个问题&#xff09; 二、期望的计算 一、Markov过程的便利性 1…

新搭建Gitlab代码仓代码如何导入

这里写目录标题一级目录1.本地代码如何导入新Gitlab2.怎么将旧Gitlab代码导入新Gitlab一级目录 1.本地代码如何导入新Gitlab 修改本地代码 .git 目录下面的config 文件&#xff0c;主要是url参数&#xff0c;将url指向新的Gitlab仓库地址 [core]repositoryformatversion 0f…

【1096. 花括号展开 II】

来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 描述&#xff1a; 如果你熟悉 Shell 编程&#xff0c;那么一定了解过花括号展开&#xff0c;它可以用来生成任意字符串。 花括号展开的表达式可以看作一个由 花括号、逗号 和 小写英文字母 组成的字符串&#xff0c;定…

E900V21C(S905L-armbian)安装armbian-Ubuntu(WiFi)

基本上是s905L芯片的刷机都是如此&#xff0c;包括Q7等 在网上寻找好多的教程关于e900v21c的刷机包和教程都少的可怜&#xff0c;唯一的就是这个&#xff1a;山东联通版创维E900V21C盒子刷入Armbiam并安装宝塔和Docker&#xff0c;但他是不能用WiFi和蓝牙的然后就是寻找s90l的…

C++基础了解-01-基础语法

基础语法 一、基础语法 C 程序可以定义为对象的集合&#xff0c;这些对象通过调用彼此的方法进行交互。现在让我们简要地看一下什么是类、对象&#xff0c;方法、即时变量。 对象 - 对象具有状态和行为。例如&#xff1a;一只狗的状态 - 颜色、名称、品种&#xff0c;行为 -…

【LeetCode每日一题】——334.递增的三元子序列

文章目录一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【解题思路】七【题目提示】八【题目进阶】九【时间频度】十【代码实现】十一【提交结果】一【题目类别】 贪心算法 二【题目难度】 中等 三【题目编号】 334.递增的三元子序列 四【题…

Vue3视频播放组件(Video)

Vue2视频播放组件 可自定义设置以下属性&#xff1a; 视频文件url&#xff08;videoUrl&#xff09;&#xff0c;必传&#xff0c;支持网络地址https和相对地址 视频封面url&#xff08;videoCover&#xff09;&#xff0c;默认为null&#xff0c;支持网络地址https和相对地…

【nacos2.2.1本地启动】

nacos2.2.1本地启动填坑之行 下载nacos代码 nacos文档地址&#xff1a;https://nacos.io/zh-cn/docs/quick-start-spring.html github地址下载代码&#xff1a;https://github.com/alibaba/nacos.git appllo文章&#xff1a;https://blog.51cto.com/muxiaonong/3933418 下…

UEFI学习(三)-创建一个dxe driver-UDK2017

创建一个dxe driver 创建UEFI DXE driver DXE驱动的运行阶段 DXE驱动创建 创建UEFI DXE driver 在edk2中&#xff0c;我们可以了解到它有非常多种类的模块&#xff0c;每种模块运行于不同阶段&#xff0c;上一阶段&#xff0c;我们尝试了一下标准应用程序的工程模块&#xff0c…