从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 模…...
淘宝接口高并发采集核心要点解读,开启电商数据智能应用新纪元
一、引言 在电商蓬勃发展的今天,淘宝作为全球知名的电商巨头,其平台上的数据犹如一座蕴藏无限价值的宝藏。准确且高效地采集淘宝接口数据,并通过高并发技术实现大规模数据获取,对于电商企业的精准营销、市场趋势分析、竞品监测以及…...
SciencePlots——绘制论文中的图片
文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了:一行…...
Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...
【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...
ip子接口配置及删除
配置永久生效的子接口,2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...
Java编程之桥接模式
定义 桥接模式(Bridge Pattern)属于结构型设计模式,它的核心意图是将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过组合关系来替代继承关系,从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...
【网络安全】开源系统getshell漏洞挖掘
审计过程: 在入口文件admin/index.php中: 用户可以通过m,c,a等参数控制加载的文件和方法,在app/system/entrance.php中存在重点代码: 当M_TYPE system并且M_MODULE include时,会设置常量PATH_OWN_FILE为PATH_APP.M_T…...
Qemu arm操作系统开发环境
使用qemu虚拟arm硬件比较合适。 步骤如下: 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载,下载地址:https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...
苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会
在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...
