当前位置: 首页 > news >正文

从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面向对象内容之常用设计模式(适配器,桥接,装饰器)

二&#xff0c;结构型设计模式 上两期咱们讲了创建型设计模式&#xff0c;都有 单例模式&#xff0c;工厂模式&#xff0c;抽象工厂模式&#xff0c;建造者模式&#xff0c;原型模式五个设计模式。 这期咱们讲结构型设计模式 1、适配器模式&#xff08;Adapter&#xff09; …...

玩转数字与运算:用C语言实现24点游戏的扑克牌魅力

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…...

前端入门之VUE--基础与核心

前言 VUE是前端用的最多的框架&#xff1b;这篇文章是本人大一上学习前端的笔记&#xff1b;欢迎点赞 收藏 关注&#xff0c;本人将会持续更新。 Vue学习笔记 用于构建用户界面的渐进式框架 构建用户界面&#xff1a;基于数据动态渲染页面渐进式&#xff1a;循序渐近的学…...

logback 初探学习

logback 三大模块 记录器&#xff08;Logger&#xff09;、追加器&#xff08;Appender&#xff09;和布局&#xff08;Layout&#xff09; 配置文件外层最基本的标签如图示 xml中定义的就是这个三个东西下面进入学习 包引入参考springboot 官方文档 Logging :: Spring Boo…...

在Elasticsearch中,是怎么根据一个词找到对应的倒排索引的?

大家好&#xff0c;我是锋哥。今天分享关于【在Elasticsearch中&#xff0c;是怎么根据一个词找到对应的倒排索引的&#xff1f;】面试题。希望对大家有帮助&#xff1b; 在Elasticsearch中&#xff0c;是怎么根据一个词找到对应的倒排索引的&#xff1f; 在 Elasticsearch 中…...

1992-2021年 各省市县经过矫正的夜间灯光数据(GNLD、VIIRS)区域汇总:省份、城市、区县面板数据

1992-2021年 各省市县经过矫正的夜间灯光数据&#xff08;GNLD、VIIRS&#xff09;区域汇总&#xff1a;省份、城市、区县面板数据 .r.rar https://download.csdn.net/download/2401_84585615/90001905 从1992年至2021年&#xff0c;中国各省份、城市及区县的夜间灯光数据经过…...

linux实战-黑链——玄机靶场

黑链的特征&#xff1a; 隐藏链接&#xff1a;黑链通常隐藏在网站页面中&#xff0c;使用CSS、JavaScript或其他手段使其对普通用户不可见&#xff0c;但仍然能被搜索引擎爬虫检测到。恶意内容&#xff1a;这些链接指向的内容可能包含恶意软件、钓鱼页面或其他不良内容&#x…...

鸿蒙NEXT开发案例:字数统计

【引言】 本文将通过一个具体的案例——“字数统计”组件&#xff0c;来探讨如何在鸿蒙NEXT框架下实现这一功能。此组件不仅能够统计用户输入文本中的汉字、中文标点、数字、以及英文字符的数量&#xff0c;还具有良好的用户界面设计&#xff0c;使用户能够直观地了解输入文本…...

uniapp vue2项目迁移vue3项目

uniapp vue2项目迁移vue3项目&#xff0c;必须适配的部分 一、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类的模拟,深浅拷贝问题)

⭐本篇重点&#xff1a;string类的模拟&#xff0c;自己实现一个简单的string类 ⭐本篇代码&#xff1a;c学习/05.string类的学习 橘子真甜/c-learning-of-yzc - 码云 - 开源中国 (gitee.com) 目录 一. 经典string类的模拟 1.1 深浅拷贝问题 1.2 使用深拷贝完成经典string类的…...

神经网络10-Temporal Fusion Transformer (TFT)

Temporal Fusion Transformer (TFT) 是一种专为时序数据建模而设计的深度学习模型&#xff0c;它结合了Transformer架构和其他技术&#xff0c;旨在有效地处理和预测时序数据中的复杂模式。TFT 于 2020 年由 Google Research 提出&#xff0c;旨在解决传统模型在时序预测中的一…...

“iOS profile文件与私钥证书文件不匹配”总结打ipa包出现的问题

目录 文件和证书未加载或特殊字符问题 证书过期或Profile文件错误 确认开发者证书和私钥是否匹配 创建证书选择错误问题 申请苹果 AppId时勾选服务不全问题 ​总结 在上线ios平台的时候&#xff0c;在Hbuilder中打包遇见了问题&#xff0c;生成ipa文件时候&#xff0c;一…...

《图像梯度与常见算子全解析:原理、用法及效果展示》

简介:本文深入探讨图像梯度相关知识&#xff0c;详细介绍图像梯度是像素灰度值在不同方向的变化速度&#xff0c;并以 “pig.JPG” 图像为例&#xff0c;通过代码展示如何选取图像部分区域并分析其像素值以论证图像梯度与边缘信息的关联。接着全面阐述了 Sobel 算子&#xff0c…...

【c++篇】:探索c++中的std::string类--掌握字符串处理的精髓

✨感谢您阅读本篇文章&#xff0c;文章内容是个人学习笔记的整理&#xff0c;如果哪里有误的话还请您指正噢✨ ✨ 个人主页&#xff1a;余辉zmh–CSDN博客 ✨文章所属专栏&#xff1a;c篇–CSDN博客 文章目录 前言一.std::string对象的创建二.std::string对象的访问三.std::str…...

LlamaIndex ollama 搭建本地RAG应用,建立本地知识库

目录 简介安装前的准备下载ollama创建llamaindex conda环境&#xff0c;为后面编码作准备 环境变量迁移ollama到其他盘运行ollama方式一方式二禁止ollama开机自启动运行第一个模型 Chatbox聊天下载Chatbox配置ollama地址和模型验证 建立自身特定知识数据搭配大语言模型创建项目…...

draggable的el-dialog实现对话框标题可以选择

请看图 这个对话框使用了el-dialog并且draggable属性设置成了true&#xff0c;所以标题栏这里就可以拖动&#xff0c;现在用户想选中标题栏的文本进而复制。我看到这个需求头都大了。 我能想到的方案有三个&#xff1a;1. 取消draggable为true 2. 标题文案后面加一个复制按钮 …...

2024年Android面试总结

2024年Android面试总结 1.动画类型有哪些&#xff1f;插值器原理&#xff1f; 2.StringBuffer和StringBuilder区别&#xff1f; 3.jvm内存模型&#xff1f; 4.线程池7大核心参数及原理&#xff1f; 5.Android多进程通信方式有哪些&#xff1f;各自的优缺点&#xff1f; 6…...

树莓派3:64位系统串口(UART)使用问题的解决方法

前言 当我们要使用串口进行zigbee的短距离通信时,发现无法使用串口. 原因 树莓派3bCPU内部有两个串口,一个硬件串口(就是我们平时使用的UART),还有一个迷你串口(mini-uart),在老版本的树莓派中把硬件串口分配在GPIO上,可以单独使用.但是在新的树莓派中官方把硬件串口给了蓝牙…...

SemiDrive E3 硬件设计系列---唤醒电路设计

一、前言 E3 系列芯片是芯驰半导体高功能安全的车规级 MCU&#xff0c;对于 MCU 的硬件设计部分&#xff0c;本系列将会分模块进行讲解&#xff0c;旨在介绍 E3 系列芯片在硬件设计方面的注意事项与经验&#xff0c;本文主要讲解 E3 硬件设计中唤醒电路部分的设计。 二、RTC 模…...

淘宝接口高并发采集核心要点解读,开启电商数据智能应用新纪元

一、引言 在电商蓬勃发展的今天&#xff0c;淘宝作为全球知名的电商巨头&#xff0c;其平台上的数据犹如一座蕴藏无限价值的宝藏。准确且高效地采集淘宝接口数据&#xff0c;并通过高并发技术实现大规模数据获取&#xff0c;对于电商企业的精准营销、市场趋势分析、竞品监测以及…...

C#里怎么样快速使用LINQ实现查询?

C#里怎么样快速使用LINQ实现查询? 在C#里使用LINQ,是一个方便的功能, 不过,要学会使用这部分的功能,需要比较多的学习时间,否则,使用起就比较难。 因为它的表现方式,与编程语言通用的功能,还是差别比较大。 当数据量比较小,没有特定的顺序时,使用LINQ访问会比较好…...

2024新版微软edge浏览器输入百度网址时自动补全tn=68018901……小尾巴的解决

以前一直是Windows11 21h2版本&#xff0c;浏览器内输入baidu不会自动补全tnxx的百度推广小尾巴。然后前几天在BIOS内开启了tpm2.0&#xff0c;升级Windows11到了24h2版本。 发现在edge浏览器内只要输入b&#xff0c;就会自动补全为baidu.com?tnXXX的这么一个百度推广形式。开…...

uni-app打包H5自定义微信分享

1、配置分享信息 修改uni-app的index.html,添加Open Graph(OG)标签来配置分享信息。 <!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8" /><meta name="description" content="标题"/>…...

大模型专栏--大模型应用场景

紧接着第一篇&#xff0c;什么是大模型&#xff0c;这篇文章讨论一下大模型的应用场景和应用方式有哪些&#xff1f; 基础使用 随着 GPT 的出现&#xff0c;AI 大模型已经越来越多得出现在日常生活和学术研究&#xff0c;工作中。 按照使用方向有以下几种&#xff1a; 自然语…...

骑砍2霸主MOD开发(29)-顶点动画

一.定制化顶点动画(MorphAnimation) 定制化顶点动画用于人物Agent的面部表情. 1.创建MorphAnimation对应静态资源morph_animation.tpac 2.Agent设置对应MorphAnimation [EngineMethod("set_agent_facial_animation", false)] void SetAgentFacialAnimation(UIntPtr …...

-Dspring.profiles.active=dev与--spring.profiles.active=dev的区别

在Spring Boot应用程序中&#xff0c;-Dspring.profiles.activedev和--spring.profiles.activedev都用于指定要激活的Spring配置文件&#xff08;profile&#xff09;&#xff0c;但它们在不同的环境中使用&#xff0c;并且有不同的作用域。 -Dspring.profiles.activedev&#…...

面向对象高级(2)单例设计对象与代码块

面向对象高级&#xff08;2&#xff09; 单例设计模式、main方法与代码块 引言&#xff1b; 设计模式&#xff1a;特定环境下特定问题的处理方法。可理解为一种经典的可以参照的模板。单例设计模式则是只存在单个对象实例、且只有一种方法获取对象实例的一种设计模式。 单例设…...

47小型项目的规划与实施

每天五分钟学Linux | 第四十七课&#xff1a;小型项目的规划与实施 大家好&#xff01;欢迎再次来到我们的“每天五分钟学Linux”系列教程。在前面的课程中&#xff0c;我们学习了并发编程的知识&#xff0c;包括如何管理和使用进程与线程。今天&#xff0c;我们将探讨如何规划…...

堤防安全监测系统方案

一、背景情况 堤防是开发利用水资源和防治水灾害的重要工程措施之一&#xff0c;对防洪、供水、生态、发电、航运等至关重要。我国现有堤防9.8万多座&#xff0c;其中大中型堤防4700多座、小型堤防9.4万座&#xff0c;80%以上修建于上世纪50至70年代。由于堤防管护力量薄弱&am…...

聊聊Flink:这次把Flink的window分类(滚动、滑动、会话、全局)、窗口函数讲透

一、窗口 窗口&#xff08;Window&#xff09;是处理无界流的关键所在。窗口将流分成有限大小的“桶”&#xff0c;我们可以在其上应用算子计算。Flink可以使用window()和windowAll()定义一个窗口&#xff0c;二者都需要传入一个窗口分配器WindowAssigner&#xff0c;WindowAs…...