从0开始学PHP面向对象内容之常用设计模式(适配器,桥接,装饰器)

二,结构型设计模式
上两期咱们讲了创建型设计模式,都有 单例模式,工厂模式,抽象工厂模式,建造者模式,原型模式五个设计模式。
这期咱们讲结构型设计模式
1、适配器模式(Adapter)
什么是适配器模式?
适配器模式是一种结构型设计模式,用于将一个类的接口转换为另一个接口,以满足客户端的使用需求,它允许本来由于接口不兼容而不能一起工作的类可以协同工作。
适配器模式的核心概念
1、目标接口(Target):客户端需要的接口。
2、适配者(Adaptee):已有的类,其他接口与目标接口普不兼容
3、适配器(Adapter):将适配者接口转换为目标接口
适配器模式的类型
对象适配器:通过组合(包含适配者对象)实现适配
类适配器:通过继承适配者实现适配(php不支持多继承,因此 类的适配器较少使用,其他语言可能会多一些)
适配器模式的结构
Client端:客户端,使用Target接口
Target:目标接口
Adaptee:适配者类,具有不兼容接的接口
Adapter:适配器类,实现Target接口,并包含Adaptee的引用
使用场景
1、当你希望使用现有的类,但接口不符合需求
2、当你想复用现有的类,而无需修改它
3、需要兼容多个版本或不同的接口系统
实现
<?php
// 目标接口 (Target)
interface Target {public function request();
}// 适配者 (Adaptee)
class Adaptee {public function specificRequest() {return "Adaptee's specific behavior";}
}// 适配器 (Adapter)
class Adapter implements Target {private $adaptee;public function __construct(Adaptee $adaptee) {$this->adaptee = $adaptee;}public function request() {// 将适配者的方法适配为目标方法return $this->adaptee->specificRequest();}
}// 客户端代码 (Client)
function clientCode(Target $target) {echo $target->request();
}// 使用适配器模式
$adaptee = new Adaptee();
$adapter = new Adapter($adaptee);
clientCode($adapter);
输出
Adaptee’s specific behavior
应用案例
1、数据库适配器:PHP 中常用的 PDO 就是一个数据库适配器,统一了对多种数据库的操作接口。
2、日志适配器:适配不同的日志系统(如 Monolog 和其他日志库)。
3、跨平台接口:将平台 A 的 API 转换为平台 B 的 API 形式。
小结
优点
1、适配器隔离了客户端与具体类的实现,遵循开闭原则
2、提高代码的复用性,现有的类可以被重复利用。
3、增强代码的灵活性,使得类之间协作更方便
缺点
增加了系统的复杂性
对于复杂的适配逻辑,可能导致适配器代码较为繁琐
2、桥接模式(Bridge)
什么是桥接模式
桥接模式是一种结构型设计模式,它通过将抽象部分与实现部分分离,使它们可以独立变化。它的核心思想是使用组合而非继承来解决类的多维度变化问题。
桥接模式的概念
1、抽象部分(Abstraction):定义高层的控制逻辑,依赖于实现部分(Implementor)。
2、实现部分(Implementor):定义具体的实现接口,不与抽象部分直接耦合
3、细化抽象:抽象部分的具体子类
4、具体实现:实现部分的具体实现
通过将这两部分分离,可以独立扩展两者,而不会互相影响
桥接模式的结构
1、Abstraction:抽象类,维护对Implementor的引用。
2、Implementor:实现接口,为具体实现提供方法。
3、RefinedAbstraction:抽象类的扩展,实现具体的功能。
4、ConcreteImplementor:实现接口的具体类
使用场景
1、类有多个纬度的变化,且每个纬度都需要独立扩展
2、希望避免使用继承来扩展类时。
3、需要再运行时切换
实现
以下是一个简单的例子:实现多种形状(Shape),支持不同的颜色(Color)
<?php
// 实现接口 (Implementor)
interface Color {public function applyColor();
}// 具体实现类 (ConcreteImplementor)
class Red implements Color {public function applyColor() {return "Red";}
}class Blue implements Color {public function applyColor() {return "Blue";}
}// 抽象类 (Abstraction)
abstract class Shape {protected $color;public function __construct(Color $color) {$this->color = $color;}abstract public function draw();
}// 细化抽象类 (RefinedAbstraction)
class Circle extends Shape {public function draw() {return "Circle colored in " . $this->color->applyColor();}
}class Square extends Shape {public function draw() {return "Square colored in " . $this->color->applyColor();}
}// 客户端代码 (Client)
$redColor = new Red();
$blueColor = new Blue();$redCircle = new Circle($redColor);
$blueSquare = new Square($blueColor);echo $redCircle->draw(); // 输出: Circle colored in Red
echo $blueSquare->draw(); // 输出: Square colored in Blue
桥接模式的实现过程
1、定义实现接口:实现部分的接口,为具体实现提供规范
2、实现具体类:具体实现的接口,具有独立的功能
3、定义抽象类:抽象部分的基类,包含实现接口的引用
4、实现细化类:抽象类的具体子类,实现客户端需要的具体功能
5、组合抽象与实现:通过组合的方式,将实现部分传递给抽象部分
实际应用
1、图形库:将图形(形状)和渲染方式分离,例如形状可以时圆形,矩形而渲染方式可以时适量渲染,栅格渲染
2、设备和控制器:控制器(抽象部分)独立于设备(实现部分),如遥控器与电视机
3、日志系统:日志框架可以有多种日志目标(文件,数据库),日志格式和目标分离
小结
优点:
1、分离抽象与实现:两者可以独立扩展符合单一职责原则
2、动态切换实现;运行时可以轻松替换实现部分
3、减少子类数量:避免以为多维度扩展导致的类爆炸
缺点:
增加复杂性:抽象与实现的分离增加了系统的复杂性
可能导致过度设计:如果维度不多或变化不频繁,使用桥接模式可能显得多余
3、 装饰器模式(Decorator)
什么是装饰器模式
装饰器模式是一种结构型设计模式,它允许动态地向对象添加新功能,而不需要修改对象地定义或使用继承,装饰器模式使用一种对象包装另一种对象地方式,为被包装对象提供额外地功能
装饰器模式地核心概念
1、组件(Component):定义对象接口
2、具体组件(Concrete Component):实现组件接口地类,是被装饰地对象
2、装饰器(Decorator):实现组件接口,同时包含一个指向组件对象地引用,用户扩展组件功能
4、具体装饰器(Concrete Decorator):实现装饰器功能,向被装饰对象添加额外地功能
使用场景
1、不希望修改已有代码但需要增加功能时
2、希望在运行时动态扩展对象功能时
3、需要组合多个装饰功能,并保持功能独立
实现
以下是一个简单的例子:装饰一段文本,支持多种功能如加粗、斜体等。
<?php
// 组件接口 (Component)
interface Text {public function render(): string;
}// 具体组件 (ConcreteComponent)
class PlainText implements Text {private $text;public function __construct(string $text) {$this->text = $text;}public function render(): string {return $this->text;}
}// 装饰器 (Decorator)
abstract class TextDecorator implements Text {protected $text;public function __construct(Text $text) {$this->text = $text;}
}// 具体装饰器 (ConcreteDecorator)
class BoldText extends TextDecorator {public function render(): string {return "<b>" . $this->text->render() . "</b>";}
}class ItalicText extends TextDecorator {public function render(): string {return "<i>" . $this->text->render() . "</i>";}
}// 客户端代码 (Client)
$plainText = new PlainText("Hello, World!");// 添加加粗功能
$boldText = new BoldText($plainText);
echo $boldText->render(); // 输出: <b>Hello, World!</b>// 添加斜体功能
$italicText = new ItalicText($boldText);
echo $italicText->render(); // 输出: <i><b>Hello, World!</b></i>
实际应用
1、**日志系统:**装饰日志功能:将日志存储到文件、发送到远程服务器或格式化为 JSON。
2、用户界面(UI)组件:如 Qt 和
Swing,按钮可以动态添加边框、阴影等样式。
3、数据流处理:PHP 中的 Stream,通过包装实现加密、压缩等功能。
4、动态权限检查:为服务接口动态添加权限验证、日志记录等功能。
小结
优点
1、开闭原则:无需修改原始对象即可扩展功能
2、高扩展性:可以创建任意数量的装饰器类,并以灵活的方式组合
3、运动时动态性:可以动态的为对象添加或移除功能
缺点
1、增加复杂性:多层装饰器会导致系统复杂度上升,调试变得困难
2、依赖组件接口:装饰器与被装饰的对象都必须实现相同接口
总结
桥接模式,适配器模式,装饰器模式对比
相关文章:
从0开始学PHP面向对象内容之常用设计模式(适配器,桥接,装饰器)
二,结构型设计模式 上两期咱们讲了创建型设计模式,都有 单例模式,工厂模式,抽象工厂模式,建造者模式,原型模式五个设计模式。 这期咱们讲结构型设计模式 1、适配器模式(Adapter) …...
玩转数字与运算:用C语言实现24点游戏的扑克牌魅力
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...
前端入门之VUE--基础与核心
前言 VUE是前端用的最多的框架;这篇文章是本人大一上学习前端的笔记;欢迎点赞 收藏 关注,本人将会持续更新。 Vue学习笔记 用于构建用户界面的渐进式框架 构建用户界面:基于数据动态渲染页面渐进式:循序渐近的学…...
logback 初探学习
logback 三大模块 记录器(Logger)、追加器(Appender)和布局(Layout) 配置文件外层最基本的标签如图示 xml中定义的就是这个三个东西下面进入学习 包引入参考springboot 官方文档 Logging :: Spring Boo…...
在Elasticsearch中,是怎么根据一个词找到对应的倒排索引的?
大家好,我是锋哥。今天分享关于【在Elasticsearch中,是怎么根据一个词找到对应的倒排索引的?】面试题。希望对大家有帮助; 在Elasticsearch中,是怎么根据一个词找到对应的倒排索引的? 在 Elasticsearch 中…...
1992-2021年 各省市县经过矫正的夜间灯光数据(GNLD、VIIRS)区域汇总:省份、城市、区县面板数据
1992-2021年 各省市县经过矫正的夜间灯光数据(GNLD、VIIRS)区域汇总:省份、城市、区县面板数据 .r.rar https://download.csdn.net/download/2401_84585615/90001905 从1992年至2021年,中国各省份、城市及区县的夜间灯光数据经过…...
linux实战-黑链——玄机靶场
黑链的特征: 隐藏链接:黑链通常隐藏在网站页面中,使用CSS、JavaScript或其他手段使其对普通用户不可见,但仍然能被搜索引擎爬虫检测到。恶意内容:这些链接指向的内容可能包含恶意软件、钓鱼页面或其他不良内容&#x…...
鸿蒙NEXT开发案例:字数统计
【引言】 本文将通过一个具体的案例——“字数统计”组件,来探讨如何在鸿蒙NEXT框架下实现这一功能。此组件不仅能够统计用户输入文本中的汉字、中文标点、数字、以及英文字符的数量,还具有良好的用户界面设计,使用户能够直观地了解输入文本…...
uniapp vue2项目迁移vue3项目
uniapp vue2项目迁移vue3项目,必须适配的部分 一、main.js 创建应用实例 // 之前 - Vue 2 import Vue from vue import App from ./App Vue.config.productionTip false // vue3 不再需要 App.mpType app // vue3 不再需要 const app new Vue({ ...App }) …...
16.C++STL 3(string类的模拟,深浅拷贝问题)
⭐本篇重点:string类的模拟,自己实现一个简单的string类 ⭐本篇代码:c学习/05.string类的学习 橘子真甜/c-learning-of-yzc - 码云 - 开源中国 (gitee.com) 目录 一. 经典string类的模拟 1.1 深浅拷贝问题 1.2 使用深拷贝完成经典string类的…...
神经网络10-Temporal Fusion Transformer (TFT)
Temporal Fusion Transformer (TFT) 是一种专为时序数据建模而设计的深度学习模型,它结合了Transformer架构和其他技术,旨在有效地处理和预测时序数据中的复杂模式。TFT 于 2020 年由 Google Research 提出,旨在解决传统模型在时序预测中的一…...
“iOS profile文件与私钥证书文件不匹配”总结打ipa包出现的问题
目录 文件和证书未加载或特殊字符问题 证书过期或Profile文件错误 确认开发者证书和私钥是否匹配 创建证书选择错误问题 申请苹果 AppId时勾选服务不全问题 总结 在上线ios平台的时候,在Hbuilder中打包遇见了问题,生成ipa文件时候,一…...
《图像梯度与常见算子全解析:原理、用法及效果展示》
简介:本文深入探讨图像梯度相关知识,详细介绍图像梯度是像素灰度值在不同方向的变化速度,并以 “pig.JPG” 图像为例,通过代码展示如何选取图像部分区域并分析其像素值以论证图像梯度与边缘信息的关联。接着全面阐述了 Sobel 算子,…...
【c++篇】:探索c++中的std::string类--掌握字符串处理的精髓
✨感谢您阅读本篇文章,文章内容是个人学习笔记的整理,如果哪里有误的话还请您指正噢✨ ✨ 个人主页:余辉zmh–CSDN博客 ✨文章所属专栏:c篇–CSDN博客 文章目录 前言一.std::string对象的创建二.std::string对象的访问三.std::str…...
LlamaIndex ollama 搭建本地RAG应用,建立本地知识库
目录 简介安装前的准备下载ollama创建llamaindex conda环境,为后面编码作准备 环境变量迁移ollama到其他盘运行ollama方式一方式二禁止ollama开机自启动运行第一个模型 Chatbox聊天下载Chatbox配置ollama地址和模型验证 建立自身特定知识数据搭配大语言模型创建项目…...
draggable的el-dialog实现对话框标题可以选择
请看图 这个对话框使用了el-dialog并且draggable属性设置成了true,所以标题栏这里就可以拖动,现在用户想选中标题栏的文本进而复制。我看到这个需求头都大了。 我能想到的方案有三个:1. 取消draggable为true 2. 标题文案后面加一个复制按钮 …...
2024年Android面试总结
2024年Android面试总结 1.动画类型有哪些?插值器原理? 2.StringBuffer和StringBuilder区别? 3.jvm内存模型? 4.线程池7大核心参数及原理? 5.Android多进程通信方式有哪些?各自的优缺点? 6…...
树莓派3:64位系统串口(UART)使用问题的解决方法
前言 当我们要使用串口进行zigbee的短距离通信时,发现无法使用串口. 原因 树莓派3bCPU内部有两个串口,一个硬件串口(就是我们平时使用的UART),还有一个迷你串口(mini-uart),在老版本的树莓派中把硬件串口分配在GPIO上,可以单独使用.但是在新的树莓派中官方把硬件串口给了蓝牙…...
SemiDrive E3 硬件设计系列---唤醒电路设计
一、前言 E3 系列芯片是芯驰半导体高功能安全的车规级 MCU,对于 MCU 的硬件设计部分,本系列将会分模块进行讲解,旨在介绍 E3 系列芯片在硬件设计方面的注意事项与经验,本文主要讲解 E3 硬件设计中唤醒电路部分的设计。 二、RTC 模…...
淘宝接口高并发采集核心要点解读,开启电商数据智能应用新纪元
一、引言 在电商蓬勃发展的今天,淘宝作为全球知名的电商巨头,其平台上的数据犹如一座蕴藏无限价值的宝藏。准确且高效地采集淘宝接口数据,并通过高并发技术实现大规模数据获取,对于电商企业的精准营销、市场趋势分析、竞品监测以及…...
观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...
最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...
【Go语言基础【12】】指针:声明、取地址、解引用
文章目录 零、概述:指针 vs. 引用(类比其他语言)一、指针基础概念二、指针声明与初始化三、指针操作符1. &:取地址(拿到内存地址)2. *:解引用(拿到值) 四、空指针&am…...
C++实现分布式网络通信框架RPC(2)——rpc发布端
有了上篇文章的项目的基本知识的了解,现在我们就开始构建项目。 目录 一、构建工程目录 二、本地服务发布成RPC服务 2.1理解RPC发布 2.2实现 三、Mprpc框架的基础类设计 3.1框架的初始化类 MprpcApplication 代码实现 3.2读取配置文件类 MprpcConfig 代码实现…...
【Post-process】【VBA】ETABS VBA FrameObj.GetNameList and write to EXCEL
ETABS API实战:导出框架元素数据到Excel 在结构工程师的日常工作中,经常需要从ETABS模型中提取框架元素信息进行后续分析。手动复制粘贴不仅耗时,还容易出错。今天我们来用简单的VBA代码实现自动化导出。 🎯 我们要实现什么? 一键点击,就能将ETABS中所有框架元素的基…...
Python训练营-Day26-函数专题1:函数定义与参数
题目1:计算圆的面积 任务: 编写一个名为 calculate_circle_area 的函数,该函数接收圆的半径 radius 作为参数,并返回圆的面积。圆的面积 π * radius (可以使用 math.pi 作为 π 的值)要求:函数接收一个位置参数 radi…...
前端开发者常用网站
Can I use网站:一个查询网页技术兼容性的网站 一个查询网页技术兼容性的网站Can I use:Can I use... Support tables for HTML5, CSS3, etc (查询浏览器对HTML5的支持情况) 权威网站:MDN JavaScript权威网站:JavaScript | MDN...
