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

装饰器模式:不改变原对象的基础上,灵活地给对象添加额外职责。装饰器相比于生成子类更加灵活。即将实现同一接口的父类当做参数传入包装器对象,动态创建出新的对象。

给对象添加新行为最简单直观的办法就是扩展本体对象,通过继承的方式达到目的。但使用继承有两个弊端:

  1. 继承是静态的,在编译期间就已经确定,无法在运行时改变对象的行为。
  2. 子类只能有一个父类,当需要添加的新功能太多时,易导致类的数量剧增。

使用装饰器模式,我们通过将现有对象放置在实现了相同一套接口的包装器对象中来动态地向现有对象添加新行为。在包装器中进行我们代码的扩展,有助于重用功能并且不会修改现有对象的代码,符合“开闭原则”。

装饰器模式中主要有如下几个角色:

  1. 客户端:会用多层装饰器来封装组件, 最后调用装饰好的包装器的方法,启动执行。
  2. 组件接口:Component声明装饰器对象和被装饰的组件对象要实现的公用接口。
  3. 组件实现:具体的组件实现类它的Operation方法中定义了组件的基础行为, 装饰类可以增强这些行为。
  4. 基础装饰类:拥有一个指向被封装对象的成员变量。 在自己的Operation方法中调用被装饰对象的Operation方法
  5. 具体装饰类:重写父类的Operation方法实现增强逻辑。类图里已经给出了要实现的主要逻辑,第四步的基础装饰类并不需要一定存在,完全可以由具体装饰类来持有对被装饰对象的引用,并实现增强逻辑,这样一来整体的结构会更简单一些。

去掉基础装饰类就是代理模式

定义一个游戏主机的产品接口,它就是上面类图中组件和装饰器的公共接口。

// PS5 产品接口
type PS5 interface {StartGPUEngine()GetPrice() int64
}

提供一个基础的产品实现类作为装饰器模式中的组件

// CD 版 PS5主机
type PS5WithCD struct{}func (p PS5WithCD) StartGPUEngine() {fmt.Println("start engine")
}
func (p PS5WithCD) GetPrice() int64 {return 5000
}

提供一个数字版游戏主机的实现作为组件实现类。

// PS5 数字版主机
type PS5WithDigital struct{}func (p PS5WithDigital) StartGPUEngine() {fmt.Println("start normal gpu engine")
}func (p PS5WithDigital) GetPrice() int64 {return 3600
}

用两个装饰器实现的Plus版和主题配色版的两个增强。

// Plus 版的装饰器
func (p *PS5MachinePlus) SetPS5Machine(ps5 PS5) {p.ps5Machine = ps5
}func (p PS5MachinePlus) StartGPUEngine() {p.ps5Machine.StartGPUEngine()fmt.Println("start plus plugin")
}func (p PS5MachinePlus) GetPrice() int64 {return p.ps5Machine.GetPrice() + 500
}// 主题色版的装饰器
type PS5WithTopicColor struct {ps5Machine PS5
}func (p *PS5WithTopicColor) SetPS5Machine(ps5 PS5) {p.ps5Machine = ps5
}func (p PS5WithTopicColor) StartGPUEngine() {p.ps5Machine.StartGPUEngine()fmt.Println("尊贵的主题色主机,GPU启动")
}func (p PS5WithTopicColor) GetPrice() int64 {return p.ps5Machine.GetPrice() + 200
}

两个增强还可以叠加在一起,组合出即高配主题限定版主机.

func main() {ps5MachinePlus := PS5MachinePlus{}ps5MachinePlus.SetPS5Machine(PS5WithCD{})// ps5MachinePlus.SetPS5Machine(PS5WithDigital{}) // 可以在更换主机ps5MachinePlus.StartGPUEngine()price := ps5MachinePlus.GetPrice()fmt.Printf("PS5 CD 豪华Plus版,价格: %d 元\n\n", price)ps5WithTopicColor := PS5WithTopicColor{}ps5WithTopicColor.SetPS5Machine(ps5MachinePlus)ps5WithTopicColor.StartGPUEngine()price = ps5WithTopicColor.GetPrice()fmt.Printf("PS5 CD 豪华Plus 经典主题配色版,价格: %d 元\n", price)
}

装饰器和代理在结构上类似,在行为上跟职责链模式类似

  • 装饰器模式强调自身功能的扩展。
  • 代理模式强调对代理过程的控制。

但装饰器的使用必将会给程序带来更高的复杂性,更低的可读性,子类集成的代码结构会更直白易懂一些,而且虽然装饰器符合“开闭原则”,但是它会给程序带来更多的类,动态装饰在多层装饰时会更复杂,对于大型项目来说也是更好维护,我最近写一个项目就是,实现原型后要对基础Entry类进行更加具体的拓展,这无疑要对代码进行重构,后续可能进一步升级项目功能,那就需要不断重构,使用装饰器模式可以使代码健壮性良好,有利于进一步维护。

参考公众号网管叨bi叨

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

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

相关文章

编程笔记 html5cssjs 018 HTML颜色

编程笔记 html5&css&js 018 HTML颜色 一、HTML 颜色二、HTML中设置颜色值注意 颜色是视觉中重要因素,尤其是处理人机界面中,更是要处理颜色设置和搭配。在网页中,提供了设置颜色的一些方案,需要我们认真学习和掌握。 一、…

HTML5和JS实现新年礼花效果

HTML5和JS实现新年礼花效果 2023兔年再见&#xff0c;2024龙年来临了&#xff01; 祝愿读者朋友们在2024年里&#xff0c;身体健康&#xff0c;心灵愉悦&#xff0c;梦想成真。 下面是用HTML5和JS实现新年礼花效果&#xff1a; 源码如下&#xff1a; <!DOCTYPE html>…

MySQL数据库学习一

1 什么是数据库的事务&#xff1f; 1.1 事务的典型场景 在项目里面&#xff0c;什么地方会开启事务&#xff0c;或者配置了事务&#xff1f;无论是在方法上加注解&#xff0c;还 是配置切面。 <tx:advice id"txAdvice" transaction-manager"transactionMa…

个人简历范本(精选5篇)

HR浏览一份简历也就25秒左右&#xff0c;如果你连「好简历」都没有&#xff0c;怎么能找到好工作呢&#xff1f; 如果你不懂得如何在简历上展示自己&#xff0c;或者觉得怎么改简历都不出彩&#xff0c;那请你一定仔细读完。 个人求职简历第 1 篇 男 22 本科 AI简历 市场营…

007、控制流

先看下本篇学习内容&#xff1a; 通过条件来执行 或 重复执行某些代码 是大部分编程语言的基础组成部分。在Rust中用来控制程序执行流的结构主要就是 if表达式 与 循环表达式。 1. if表达式 if表达式允许我们根据条件执行不同的代码分支。我们提供一个条件&#xff0c;并且做出…

【NTN 卫星通信】Oneweb星座以及Oneweb与Starlink比较

1 什么是OneWeb OneWeb于2012年以WorldVu的名义成立&#xff0c;于2020年开始构建其星座。然而&#xff0c;对于这家英国公司来说&#xff0c;这是一个艰难的旅程&#xff0c;OneWeb于2020年3月宣布破产&#xff0c;并认为covid-19大流行是一个主要因素。OneWeb星座当时仅完成…

一次降低进程IO延迟的性能优化实践——基于block层bfq调度器

如果有个进程正频繁的读写文件&#xff0c;此时你vim查看一个新文件&#xff0c;将会出现明显卡顿。即便你vim查看的文件只有几十M&#xff0c;也可能会出现卡顿。相对的&#xff0c;线上经常遇到IO敏感进程偶发IO超时问题。这些进程一次读写的文件数据量很少&#xff0c;正常几…

Redis的缓存过期淘汰策略

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱吃芝士的土豆倪&#xff0c;24届校招生Java选手&#xff0c;很高兴认识大家&#x1f4d5;系列专栏&#xff1a;Spring源码、JUC源码、Kafka原理、分布式技术原理、数据库技术&#x1f525;如果感觉博主的文章还不错的…

RocketMQ(Linux版本5.1.4)

1、停止之前的运行服务 [roottssvr1-c1 rocketmq-all-4.7.0-bin-release]# sh bin/mqshutdown namesrv No mqnamesrv running. [roottssvr1-c1 rocketmq-all-4.7.0-bin-release]# [roottssvr1-c1 rocketmq-all-4.7.0-bin-release]# [roottssvr1-c1 rocketmq-all-4.7.0-bin-r…

Debezium发布历史39

原文地址&#xff1a; https://debezium.io/blog/2018/09/19/debezium-0-8-3-final-released/ 欢迎关注留言&#xff0c;我是收集整理小能手&#xff0c;工具翻译&#xff0c;仅供参考&#xff0c;笔芯笔芯. Debezium 0.8.3.Final 发布 2018 年 9 月 19 日 作者&#xff1a; …

LOJ #6278 数列分块2题解 2024年第一篇题解

Part #0 . 前言 \text{Part \#0 . 前言} Part #0 . 前言 数列分块1 分块是一种优雅的暴力。 Part #1 . 数列分块入门2 \text{Part \#1 . 数列分块入门2} Part #1 . 数列分块入门2 传送门 观察题目&#xff0c;我们可以发现题目是一个区间查询&#xff0c;区间修改。 首先&a…

数据结构式新年贺词

冒泡排序&#xff0c;选择排序&#xff0c;插入排序&#xff0c;快速排序&#xff0c;堆排序&#xff0c;归并排序&#xff0c;希尔排序&#xff0c;桶排序&#xff0c;基数排序新年帮您排忧解难。 有向图&#xff0c;无向图&#xff0c;有环图&#xff0c;无环图&#xff0c;…

汽车保养软件app开发步骤

“增强您的动力&#xff0c;为您的旅程加油——每一刻都讲述着关爱的故事。构建汽车维护软件app&#xff0c;为您的车辆提供数字化的维修站&#xff0c;从而开启长寿之路。智能驾驶、互联驾驶、自信驾驶。” 疯狂地搜索旧收据并猜测上次换油时间的日子已经一去不复返了。如果您…

51单片机点灯入门教程——2. 呼吸灯效果

基本说明 本章使用芯片&#xff1a;STC8H8K64U核心板 芯片手册&#xff1a;点此查看 Keil 开发环境配置&#xff1a;点此查看 本章学习内容&#xff1a;利用库函数&#xff0c;开发C程序&#xff0c;实现呼吸灯效果。 代码实例 需求&#xff1a;使用串口来控制呼吸灯效果&…

ElasticSearch Nested类型全文检索、聚合查询

ElasticSearch Nested类型全文检索、聚合查询 Nested类型全文检索 创建索引 PUT /products1 {"mappings": {"properties": {"fulltext": {"type": "text"},"name": {"type": "text","…

JavaScript 基础通关

快速熟悉 JavaScript 的基础语法&#xff0c;比较高级的比如事件放在后面的笔记中。 JavaScript 1. JavaScript 介绍 1.1 JavaScript 基本介绍 JavaScript 是一门运行在客户端&#xff08;浏览器&#xff09;的编程语言&#xff0c;实现人机交互的效果。实现网页特效、表单验…

Python入门学习篇(十四)——模块文件操作

1 模块 1.1 理解 包: python中带有__init__.py文件的文件夹 模块: 文件名(不包含.py后缀),如python官方的time.py中time就是模块1.2 示例代码 import datetime# 调用datetime模块中的datetime类的now()方法 t datetime.datetime.now() # 格式化输出日期和时间 strftime(&qu…

基于BP神经网络的磨具变形量分析,BP神经网络详细原理

目录 摘要 BP神经网络参数设置及各种函数选择 参数设置 训练函数 传递函数 学习函数 性能函数 显示函数 前向网络创建函数 BP神经网络训练窗口详解 训练窗口例样 训练窗口四部详解 基于BP神经网络的磨具变形量分析 完整代码下载链接:基于BP神经网络的磨具变形量分析(代码完整…

Vue2中使用echarts,并从后端获取数据同步

一、安装echarts npm install echarts -S 二、导入echarts 在script中导入&#xff0c;比如&#xff1a; import * as echarts from "echarts"; 三、查找要用的示例 比如柱状图 四、初始化并挂载 <template><div id"total-orders-chart" s…

开发Python网络爬虫应用,爬取链家新房楼盘信息保存到mongodb中,并分析相关数据

这里写自定义目录标题 爬取代码分析数据问题 爬取代码 import requests import time from lxml import html from pymongo import MongoClient import randomBASEURL https://cq.fang.lianjia.com/loupan/# 获取某市区域的所有链接 def get_areas(url):print(获取区县列表)# …