结构型设计模式:装饰器模式

设计模式专栏目录

创建型设计模式-单例模式/工厂模式/抽象工厂
行为型设计模式:模板设计模式/观察者设计模式/策略设计模式
结构型设计模式:装饰器模式
C#反射机制实现开闭原则的简单工厂模式

目录

  • 设计模式专栏目录
  • 设计模式分类
  • 设计模式的设计原则
  • 装饰器模式

设计模式分类

设计模式可以分为三种类型:创建型设计模式、结构型设计模式和行为型设计模式。

创建型设计模式:这些模式涉及到对象的创建机制,包括简单工厂模式、工厂方法模式、抽象工厂模式、单例模式、建造者模式和原型模式。

结构型设计模式:这些模式涉及到类和对象的组合,包括适配器模式、桥接模式、组合模式、装饰器模式、外观模式、享元模式和代理模式。

行为型设计模式:这些模式涉及到对象之间的通信和交互,包括责任链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式模板方法模式和访问者模式。

本文是对结构型设计模式中的装饰器、组合设计模式的一个总结。每个设计模式的定义都比较晦涩,可以直接看代码理解。

设计模式的设计原则

依赖倒置:高层模块不应该依赖低层模块,两者都应该依赖抽象; 抽象不应该依赖具体实现,具体实现应该依赖于抽象; (记住依赖抽象就好了)
开放封闭:一个类应该对扩展(组合和继承)开放,对修改关闭;
面向接口:不将变量类型声明为某个特定的具体类,而是声明为某个接口;
客户程序无需获知对象的具体类型,只需要知道对象所具有的接口;
减少系统中各部分的依赖关系,从而实现“高内聚、松耦合”的类型设计方案;(记住只暴露接口,只调用接口)
封装变化点:将稳定点和变化点分离,扩展修改变化点;让稳定点和变化点的实现层次分离;
单一职责:一个类应该仅有一个引起它变化的原因; (就是变化点不要太多)
里氏替换:子类型必须能够替换掉它的父类型;主要出现在子类覆盖父类实现,原来使用父类型的程序可能出现错误;覆盖了父类方法却没有实现父类方法的职责;( 就是子类可以覆盖父类的方法,但是得保证父类必要的功能)
接口隔离:不应该强迫客户依赖于它们不用的方法;
一般用于处理一个类拥有比较多的接口,而这些接口涉及到很多职责;
客户端不应该依赖它不需要的接口。
一个类对另一个类的依赖应该建立在最小的接口上。
组合优于继承:继承耦合度高,组合耦合度低;

装饰器模式

动态的给对象添加一些额外的责任,就增加功能来说,装饰比生成子类更为灵活。

用一个菜品计算成本(包括食物和各种调料)的例子说明这个设计模式:

在餐馆需要给食物计算成本,比如面条和加的各种调料:

#include <iostream>
#include <string>

using namespace std;

// 食品类
class Food {
protected:
	string des;
	double price;

public:
	virtual double cost() = 0;
	string getDes() {
		return des;
	}
	void setDes(string des) {
		this->des = des;
	}
	double getPrice() {
		return price;
	}
	void setPrice(double price) {
		this->price = price;
	}
};

// 面条类
class Noodles : public Food {
public:
	double cost() override {
		return getPrice();
	}
};

// 中式面条类
class ChineseNoodles : public Noodles {
public:
	ChineseNoodles() {
		setDes("中式面条");
		setPrice(25.00);
	}
};

// 装饰器类
class Decorator : public Food {
protected:
	Food* desFood;

public:
	Decorator(Food* desFood) {
		this->desFood = desFood;
	}
	double cost() override {
		cout << desFood->getDes() << "价格:" << desFood->getPrice() << "  配料如下:"
			<< getDes() << "  价格:" << getPrice() << "  总价" << (getPrice() + desFood->cost()) << endl;
		return getPrice() + desFood->cost();
	}
};

// 孜然类
class Cumin : public Decorator {
public:
	Cumin(Food* desFood) : Decorator(desFood) {
		setDes("孜然");
		setPrice(2.00);
	}
};
// 胡椒类
class Peper : public Decorator {
public:
	Peper(Food* desFood) : Decorator(desFood) {
		setDes("胡椒");
		setPrice(3.00);
	}
};

int main() {
	// 先定义一个被装饰者,返回对象要为最顶层的对象,这样被装饰者才能接受
	Food* noodles = new ChineseNoodles();
	// 定义一个装饰者对象
	Food* cumin = new Cumin(noodles);
	// 输出为:中式面条价格:25配料如下:孜然价格:2总价27
	cout << "-----------面条+孜然------------------------" << endl;
	cumin->cost();
	cout << "-----------面条+胡椒------------------------" << endl;
	Food* peper = new Peper(noodles);
	peper->cost();
	cout << "-----------面条+胡椒+孜然------------------------" << endl;
	peper = new Peper(cumin);
	cout << "面条+胡椒+孜然价格:" <<peper->cost();

	delete cumin;
	delete noodles;
	delete peper;

	return 0;
}

在这里插入图片描述

“面条+胡椒+孜然”的例子日志打印比较乱,是由于装饰器类cost打印有嵌套,所以日志打印比较乱。

在这里插入图片描述

结构:

  • 被装饰者抽象接口(Food):提供基础功能方法,和装饰方法接口。
  • 具体的被装饰者(Noodles):继承抽象类,实现方法接口。
  • 装饰者公共类(Decorator):实现统一的装饰方法。
  • 具体的修饰者类:定制化装饰者属性。

使用场景:在软件开发过程中,有时想用一些现存的组件(已经定义好的对象)。这些组件可能只是完成一些核心功能。但在不改变其架构的情况下,可以动态地扩展其功能。所以这些都可以采用装饰模式来实现。

特点:

装饰者设计模式是通过组合+继承的形式实现的。

装饰类和被装饰类可以独立发展,不会相互耦合。

装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Spring Boot——Spring Boot启动原理

系列文章目录 Spring Boot启动原理 系列文章目录一、Spring Boot启动的宏观流程图二、Spring Boot启动流程2.1 初始化new SpringApplication2.1.1Spring Boot入口2.1.2初始化SpringApplication2.1.2.1判断当前应用程序类型2.1.2.2设置应用程序的所有初始化器(initializers)2.1.…

Lab———Git使用指北

Lab———Git使用指北 &#x1f916;:使用IDEA Git插件实际工作流程 &#x1f4a1; 本文从实际使用的角度出发&#xff0c;以IDEA Git插件为基本讲述了如果使用IDEA的Git插件来解决实际开发中的协作开发问题。本文从 远程仓库中拉取项目&#xff0c;在本地分支进行开发&#x…

OpenCvSharp (C# OpenCV) 二维码畸变矫正--基于透视变换(附源码)

导读 本文主要介绍如何使用OpenCvSharp中的透视变换来实现二维码的畸变矫正。 由于CSDN文章中贴二维码会导致显示失败,大家可以直接点下面链接查看图片: C# OpenCV实现二维码畸变矫正--基于透视变换 (详细步骤 + 代码) 实现步骤 讲解实现步骤之前先看下效果(左边是原图,右边…

CSS 瀑布流效果效果

示例 <!DOCTYPE html> <html lang="cn"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>瀑布流效果</title><style>…

Windows安装PyTorch

文章目录 前言CPU版本安装安装步骤测试CPU版PyTorch是否安装成功 GPU版本安装新建一个conda环境安装torch法一&#xff1a;在线安装(建议用法二)法二&#xff1a;下载torch、torchvision后本地安装(建议使用此方法)Jupyter Lab虚拟环境的配置测试是否安装成功 前言 此份文档适…

Java 版 spring cloud +spring boot 工程系统管理 工程项目管理系统源码 工程项目各模块及其功能点清单

工程项目各模块及其功能点清单 一、系统管理 1、数据字典&#xff1a;实现对数据字典标签的增删改查操作 2、编码管理&#xff1a;实现对系统编码的增删改查操作 3、用户管理&#xff1a;管理和查看用户角色 4、菜单管理&#xff1a;实现对系统菜单的增删改查操…

【JavaEE初阶】HTTP请求的构造及HTTPS

文章目录 1.HTTP请求的构造1.1 from表单请求构造1.2 ajax构造HTTP请求1.3 Postman的使用 2. HTTPS2.1 什么是HTTPS?2.2 HTTPS中的加密机制(SSL/TLS)2.2.1 HTTP的安全问题2.2.2 对称加密2.2.3 非对称加密2.2.3 中间人问题2.2.5 证书 1.HTTP请求的构造 常见的构造HTTP 请求的方…

EMO:重新思考高效的基于注意力的移动块模型

文章目录 摘要1、介绍2、方法论:归纳法和演绎法2.1、通用效率模型标准2.2、元移动块2.3、微设计:倒置残余移动块2.4、面向密集预测的EMO宏观设计 3、实验3.1、图像分类3.2、下游任务3.3、额外的消融和解释分析 4、相关工作5、结束语及未来工作 摘要 论文链接&#xff1a;https…

Ubuntu更改虚拟机网段(改成桥接模式无法连接网络)

因为工作需要&#xff0c;一开始在安装vmware和虚拟机时&#xff0c;是用的Nat网络。 现在需要修改虚拟机网段&#xff0c;把ip设置成和Windows端同一网段&#xff0c;我们就要去使用桥接模式。 环境&#xff1a; Windows10、Ubuntu20.04虚拟机编辑里打开虚拟网络编辑器&#…

在Mac上搭建Gradle环境

在Mac上搭建Gradle环境&#xff1a; 步骤1&#xff1a;下载并安装Java开发工具包&#xff08;JDK&#xff09; Gradle运行需要Java开发工具包&#xff08;JDK&#xff09;。您可以从Oracle官网下载适合您的操作系统版本的JDK。请按照以下步骤进行操作&#xff1a; 打开浏览器…

520 · 一致性哈希 II

链接&#xff1a;LintCode 炼码 - ChatGPT&#xff01;更高效的学习体验&#xff01; 题解&#xff1a; class Solution{private:int n;const int mVirtualNodeCount;map<int, int> mVirtualNodeToMachineIdMap;set<int> mVirtualNodeSet;public:Solution(int n…

SpringBoot房屋租赁系统【附ppt|万字文档(LW)和搭建文档】

主要功能 前台登录&#xff1a; ①首页&#xff1a;公告信息、房屋信息展示、查看更多等 ②房屋信息、房屋类型、我要当房主、公告信息、留言反馈等 ③个人中心&#xff1a;可以查看自己的信息、更新图片、更新信息、退出登录、我的收藏 后台登录&#xff1a; ①首页、个人中心…

软件测试-基础阶段学习

目录 一、测试介绍 二、测试常用分类 三、模型 四、测试流程 五、测试用例 六、用例设计方法 七、缺陷 八、html 资料获取方法 阶段目标 能独立针对web项目实施功能测试 一、测试介绍 什么是软件测试 使用技术手段验证软件是否满足需求 测试主流技能 功能测试自…

golang,gin框架的请求参数(一)--推荐

golang&#xff0c;gin框架的请求参数&#xff08;一&#xff09; gin框架的重要性不过多的强调&#xff0c;重点就gin使用中的参数传递&#xff0c;获取进行梳理文件&#xff0c;满足使用需求。 获取前端请求参数的几种方法&#xff1a; 一、获取参数【浏览器地址获取参数】…

【业务功能篇58】Springboot + Spring Security 权限管理 【中篇】

4.2.3 认证 4.2.3.1 什么是认证&#xff08;Authentication&#xff09; 通俗地讲就是验证当前用户的身份&#xff0c;证明“你是你自己”&#xff08;比如&#xff1a;你每天上下班打卡&#xff0c;都需要通过指纹打卡&#xff0c;当你的指纹和系统里录入的指纹相匹配时&…

图注意力网络论文详解和PyTorch实现

图神经网络(gnn)是一类功能强大的神经网络&#xff0c;它对图结构数据进行操作。它们通过从节点的局部邻域聚合信息来学习节点表示(嵌入)。这个概念在图表示学习文献中被称为“消息传递”。 消息(嵌入)通过多个GNN层在图中的节点之间传递。每个节点聚合来自其邻居的消息以更新其…

【小白必看】Python爬虫实战之批量下载女神图片并保存到本地

文章目录 前言运行结果部分图片1. 引入所需库2. 发送请求获取网页内容3. 解析网页内容并提取图片地址和名称4. 下载并保存图片完整代码关键代码讲解 结束语 前言 爬取网络上的图片是一种常见的需求&#xff0c;它可以帮助我们批量下载大量图片并进行后续处理。本文将介绍如何使…

django学习笔记(1)

django创建项目 先创建一个文件夹用来放django的项目&#xff0c;我这里是My_Django_it 之后打开到该文件下&#xff0c;并用下面的指令来创建myDjango1项目 D:\>cd My_Django_itD:\My_Django_it>"D:\zzu_it\Django_learn\Scripts\django-admin.exe" startpr…

echarts遇到的问题

文章目录 折线图-区域面积图 areaStyley轴只有整数y轴不从0开始y轴数值不确定&#xff0c;有大有小&#xff0c;需要动态处理折线-显示label标线legend的格式化和默认选中状态x轴的lable超长处理x轴的相关设置 echarts各个场景遇到的问题 折线图-区域面积图 areaStyle areaStyl…

分库分表之基于Shardingjdbc+docker+mysql主从架构实现读写分离(二)

说明&#xff1a;如果实现了docker部署mysql并完成主从复制的话再继续&#xff0c;本篇文章主要说明springboot配置实现Shardingjdbc进行读写分离操作。 如果没实现docker部署mysql实现主从架构的话点击我 Shardingjdbc配置介绍&#xff08;版本&#xff1a;5.3.2&#xff09;…