从0开始学PHP面向对象内容之常用设计模式(组合,外观,代理)

在这里插入图片描述

二、结构型设计模式

4、组合模式(Composite)

组合模式(Composite Pattern)是一种结构型设计模式,它将对象组合成树形结构以表示”部分–整体“的层次结构。通过组合模式,客户端可以以一致的方式处理单个对象和对象的组合

组合模式的核心概念

1、组合模式允许客户端同意对待单个对象和对象组合,而不需要分别对待。
2、树形结构是其核心,通过递归调用处理每个对象节点。
3、组合模式适用于需要表示”部分–整体“关系的场景,例如文件系统,组织结构系统等

组成角色

1、组件(Componet):定义所有检点的通用接口,声明默认行为。
2、叶子节点(Leaf):表示树的叶子节点,具体的对象,不能包含子节点。
3、组合节点(Composite):表示树的中间节点,可以包含其他叶子节点或组合节点
4、客户端(Client):使用组件接口来统一操作树形结构中的元素

实现

以下以“文件系统”为例,展示组合模式的实现
1、定义接口:定义所有节点的通用接口

// 组件接口
interface FileSystemComponent {public function display($indent = 0);
}

2、叶子节点:表示单个文件,不能包含子节点。

// 叶子节点
class File implements FileSystemComponent {private $name;public function __construct($name) {$this->name = $name;}public function display($indent = 0) {echo str_repeat(" ", $indent) . "File: " . $this->name . PHP_EOL;}
}

3、组合节点:表示文件夹,可以包含文件或子文件夹

// 组合节点
class Directory implements FileSystemComponent {private $name;private $children = [];public function __construct($name) {$this->name = $name;}public function add(FileSystemComponent $component) {$this->children[] = $component;}public function display($indent = 0) {echo str_repeat(" ", $indent) . "Directory: " . $this->name . PHP_EOL;foreach ($this->children as $child) {$child->display($indent + 2);}}
}

4、客户端:使用组合模式创建和操作文件系统

// 创建文件和目录
$root = new Directory("root");$home = new Directory("home");
$root->add($home);$file1 = new File("file1.txt");
$file2 = new File("file2.txt");$home->add($file1);
$home->add($file2);$subDir = new Directory("documents");
$home->add($subDir);$file3 = new File("resume.docx");
$subDir->add($file3);// 显示文件系统结构
$root->display();

输出结果

Directory: rootDirectory: homeFile: file1.txtFile: file2.txtDirectory: documentsFile: resume.docx

组合模式的应用场景

1、user_deposit:文件和文件夹的层次结构
2、图形界面(GUI):界面中的窗口,按钮,文本框等组件的层次结构
3、组织架构:公司部门与员工的层次关系。
4、菜单系统:菜单与子菜单的层次结构

扩展

1、添加移除功能:允许动态添加、移除子节点

class Directory implements FileSystemComponent {public function remove(FileSystemComponent $component) {$this->children = array_filter($this->children, fn($child) => $child !== $component);}
}

2、缓存机制:在组合节点中添加缓存,提高查询效率

class Directory {private $sizeCache;public function calculateSize() {if ($this->sizeCache === null) {$this->sizeCache = array_reduce($this->children, fn($carry, $child) => $carry + $child->calculateSize(), 0);}return $this->sizeCache;}
}

小结

组合模式通过树形结构将单个对象与组合对象统一处理,简化了客户端代码的复杂性,尤其适用于具有层次关系的系统。PHP实现组合模式非常灵活,可以根据实际需求动态调整子节点的添加、移除以及递归行为,极大地提高了代码的扩展性和复用性。

5、外观模式(Facade)

外观模式(Face Pattern)是一种结构型设计模式,通过为子系统中的一组复杂接口提供一个一致的接口,简化了客户端与子系统之间的交互,它隐藏了子系统的复杂性,使得客户端只需要与外观对象交互即可完成操作

外观模式的定义

1、核心思想:为复杂系统提供一个统一的高层接口,使得客户端可以通过该接口访问子系统,而无需直接与子系统交互
2、主要目的:降低系统的复杂性,提高系统的可维护性和易用性

外观模式的组成

1、外观类(Facade):提供一个简单的接口,封装子系统的功能。
2、子系统类(Subsystem):完成系统的实际功能,但客户端无需访问这些类
3、客户端(Client ):通过外观类与子系统交互而不直接依赖子系统的具体实现

实现

以下通过一个“智能家居系统”的例子展示外观模式的实现。
子系统类:包含 灯光,空调等

class Light {public function on() {echo "Light is turned on.\n";}public function off() {echo "Light is turned off.\n";}
}class AirConditioner {public function on() {echo "Air Conditioner is turned on.\n";}public function off() {echo "Air Conditioner is turned off.\n";}
}class Television {public function on() {echo "Television is turned on.\n";}public function off() {echo "Television is turned off.\n";}
}

外观类 :使用场景 开始场景(打开),结束场景(关闭)

class SmartHomeFacade {private $light;private $airConditioner;private $television;public function __construct() {$this->light = new Light();$this->airConditioner = new AirConditioner();$this->television = new Television();}public function startDay() {echo "Starting the day...\n";$this->light->on();$this->airConditioner->on();$this->television->on();}public function endDay() {echo "Ending the day...\n";$this->television->off();$this->airConditioner->off();$this->light->off();}
}

客户端代码

$smartHome = new SmartHomeFacade();// 启动智能家居
$smartHome->startDay();// 结束智能家居
$smartHome->endDay();

运行结果

Starting the day...
Light is turned on.
Air Conditioner is turned on.
Television is turned on.
Ending the day...
Television is turned off.
Air Conditioner is turned off.
Light is turned off.

外观模式的应用场景

1、复杂系统的简化接口:大型系统中,多个子系统需要对外提供功能时,可以通过外观类统一接口,降低复杂度
2、模块解耦:不同模块之间通过外观类交互,而不直接依赖子系统的具体实现。
3、跨层访问:在分层架构中,外观模式可以用作每一层的入口点

小结

外观模式通过隐藏子系统的实现细节,为客户端提供了一个简单易用的接口。
它是“高内聚、低耦合”的典范,可以显著降低客户端与子系统之间的耦合度。
在实际开发中,外观模式常用于大型复杂系统、分层架构中,提供模块化和易用性的统一入口。

6、代理模式(Proxy)

代理模式(Proxy Pattern)是一种结构型设计模式,它为其他对象提供一种代理以控制对这个对象的访问。通过代理模式,客户端可以通过代理对象间接与真实对象交互,从而实现对对象的访问控制、延迟加载、功能增强等需求。

代理模式定义

1、核心思想:代理对象是实际对象的代表,负责对真实对象的访问或操作,同时可以添加额外的功能
2、主要目的:控制访问,性能优化或者为对象提供附加功能。

代理模式组成

1、抽象主题(Subject):定义代理类和真实主题的共同接口
2、真实主题(RealSubject):实现抽象主题的具体功能,是实际被访问的对象
3、代理类(Proxy):实现抽象主题,控制对真实主题的访问

代理模式的类型

1、远程代理(Remote Proxy)

1、定义:为位于不同地址空间的对象提供本地代理。
2、示例:远程调用(RPC)或Web服务代理。
3、场景:通过网络访问远程对象(如RPC、RMI)。

2、虚拟代理(Virtual Proxy

1、定义:在需要时才创建对象(延迟加载)。
2、示例:大图像的延迟加载。
3、场景:需要延迟加载资源时(如大文件或复杂对象)。

3、保护代理(Protection Proxy)

1、定义:控制对对象的访问权限。
2、示例:基于用户权限的访问控制。
3、场景:控制对敏感资源的访问,通常结合权限控制。

4、智能引用代理(Smart Proxy):

1、定义:在访问对象时提供附加功能(如日志记录、统计)。
2、示例:记录对象调用次数
3、场景:在访问真实对象前后,执行附加逻辑(如日志记录、调用统计)。

代理模式的设计要点

1、 共享接口:代理类和真实对象应实现相同的接口或继承自相同的抽象类。
2、透明性:客户端代码无需感知代理类的存在,操作与直接访问真实对象一致。
3、延迟加载:虚拟代理应尽量推迟真实对象的创建,减少资源浪费。

实现

以下通过一个“图像查看器”的例子展示代理模式的实现
抽象主题

interface Image {public function display();
}

真实主题

class RealImage implements Image {private $fileName;public function __construct($fileName) {$this->fileName = $fileName;$this->loadFromDisk($fileName);}private function loadFromDisk($fileName) {echo "Loading image from disk: $fileName\n";}public function display() {echo "Displaying image: $this->fileName\n";}
}

代理类

class ProxyImage implements Image {private $realImage;private $fileName;public function __construct($fileName) {$this->fileName = $fileName;}public function display() {if ($this->realImage === null) {$this->realImage = new RealImage($this->fileName);}$this->realImage->display();}
}

客户端代码

$image = new ProxyImage("photo.jpg");// 第一次调用,会加载图像
$image->display();// 第二次调用,不会重新加载图像
$image->display();

运行结果:

Loading image from disk: photo.jpg
Displaying image: photo.jpg
Displaying image: photo.jpg

代理模式的扩展

动态代理:使用 PHP 的魔术方法(如 __call)实现通用代理,拦截方法调用。

class DynamicProxy {private $realObject;public function __construct($realObject) {$this->realObject = $realObject;}public function __call($name, $arguments) {echo "Logging: Calling method $name\n";return call_user_func_array([$this->realObject, $name], $arguments);}
}// 示例
$realImage = new RealImage("example.jpg");
$proxy = new DynamicProxy($realImage);
$proxy->display();

运行结果:

Loading image from disk: example.jpg
Logging: Calling method display
Displaying image: example.jpg

小结

代理模式通过在真实对象和客户端之间增加代理对象,实现了对对象访问的控制、延迟加载、权限校验等功能。在实际开发中,代理模式广泛应用于远程调用、资源管理、权限控制等场景,特别是在需要解耦客户端与真实对象时,是一个非常实用的设计模式。

总结

代理模式与其他模式的对比
在这里插入图片描述

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

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

相关文章

femor 第三方Emby应用全平台支持v1.0.54更新

femor v1.0.54 版本更新 mpv播放器增加切换后台和恢复时隐藏状态栏的功能修复服务器首页因为连接超时异常的问题 获取路径:【femor 历史版本收录】

如何搭建一个小程序:从零开始的详细指南

在当今数字化时代,小程序以其轻便、无需下载安装即可使用的特点,成为了连接用户与服务的重要桥梁。无论是零售、餐饮、教育还是娱乐行业,小程序都展现了巨大的潜力。如果你正考虑搭建一个小程序,本文将为你提供一个从零开始的详细…

nrm镜像管理工具使用方法

nrm(NPM Registry Manager)是一款专门用于管理 npm 包镜像源的命令行工具。在使用 npm 安装各种包时,默认会从官方的 npm 仓库(registry)获取资源,但有时候由于网络环境等因素,访问官方源可能速…

OpenCV截取指定图片区域

import cv2 img cv2.imread(F:/2024/Python/demo1/test1/man.jpg) cv2.imshow(Image, img) # 显示图片 #cv2.waitKey(0) # 等待按键x, y, w, h 500, 100, 200, 200 # 示例坐标 roi img[y:yh, x:xw] # 截取指定区域 cv2.imshow(ROI, roi) cv2.waitKey(0) cv…

易速鲜花聊天客服机器人的开发(下)

目录 “聊天机器人”项目说明 方案 1 :通过 Streamlit 部署聊天机器人 方案2 :通过 Gradio 部署聊天机器人 总结 上一节,咱们的聊天机器人已经基本完成,这节课,我们要看一看如何把它部署到网络上。 “聊天机器人”…

STM32笔记(串口IAP升级)

一、IAP简介 IAP(In Application Programming)即在应用编程, IAP 是用户自己的程序在运行过程中对 User Flash 的部分区域进行烧写,目的是为了在产品发布后可以方便地通过预留的通信口对产 品中的固件程序进行更新升级。 通常实…

斐波那契堆与二叉堆在Prim算法中的性能比较:稀疏图与稠密图的分析

斐波那契堆与二叉堆在Prim算法中的性能比较:稀疏图与稠密图的分析 引言基本概念回顾Prim算法的时间复杂度分析稀疏图中的性能比较稠密图中的性能比较|E| 和 |V| 的关系伪代码与C代码示例结论引言 在图论中,Prim算法是一种用于求解最小生成树(MST)的贪心算法。其性能高度依…

使用argo workflow 实现springboot 项目的CI、CD

文章目录 基础镜像制作基础镜像设置镜像源并安装工具git下载和安装 Maven设置环境变量设置工作目录默认命令最终dockerfile 制作ci argo workflow 模版volumeClaimTemplatestemplatesvolumes完整workflow文件 制作cd argo workflow 模版Workflow 结构Templates 定义创建 Kubern…

BUUCTF—Reverse—不一样的flag(7)

是不是做习惯了常规的逆向题目?试试这道题,看你在能不能在程序中找到真正的flag!注意:flag并非是flag{XXX}形式,就是一个’字符串‘,考验眼力的时候到了! 注意:得到的 flag 请包上 f…

insmod一个ko提供基础函数供后insmod的ko使用的方法

一、背景 在内核模块开发时,多个不同的内核模块,有时候可能需要都共用一些公共的函数,比如申请一些平台性的公共资源。但是,这些公共的函数又不方便去加入到内核镜像里,这时候就需要把这些各个内核模块需要用到的一些…

LangGraph中的State管理

本教程将介绍如何使用LangGraph库构建和测试状态图。我们将通过一系列示例代码,逐步解释程序的运行逻辑。 1. 基本状态图构建 首先,我们定义一个状态图的基本结构和节点。 定义状态类 from langgraph.graph import StateGraph, START, END from typi…

MATLAB中Simulink的基础知识

Simulink是MATLAB中的一种可视化仿真工具, 是一种基于MATLAB的框图设计环境,是实现动态系统建模、仿真和分析的一个软件包,被广泛应用于线性系统、非线性系统、数字控制及数字信号处理的建模和仿真中。 Simulink提供一个动态系统建模、仿真和…

最小生成树-Prim与Kruskal算法

文章目录 什么是最小生成树?Prim算法求最小生成树Python实现: Kruskal算法求最小生成树并查集 Python实现: Reference 什么是最小生成树? 在图论中,树是图的一种,无法构成闭合回路的节点-边连接组合称之为…

关闭AWS账号后,服务是否仍会继续运行?

在使用亚马逊网络服务(AWS)时,用户有时可能会考虑关闭自己的AWS账户。这可能是因为项目结束、费用过高,或是转向使用其他云服务平台。然而,许多人对关闭账户后的服务状态感到困惑,我们九河云和大家一起探讨…

Could not locate device support files.

报错信息:Failure Reason: The device may be running a version of iOS (13.6.1 17G80) that is not supported by this version of Xcode.[missing string: 869a8e318f07f3e2f42e11d435502286094f76de] 问题:xcode15升级到xcode16之后,13.…

Linux文件基础

目录 一、文件类型 二、文件权限 三、权限修改 Linux中一切皆文件,文件目录分布呈树状数据结构,/是根目录,目录的源头 一、文件类型 类型字符说明普通-Linux中最多的一种文件类型,包括 纯文本文件(ASCII)、二进制文件(binary…

自然语言处理基础之文本预处理

一. NLP介绍 1957年, 怛特摩斯会议 二. 文本预处理 文本预处理及作用 将文本转换成模型可以识别的数据 文本转化成张量(可以利用GPU计算), 规范张量的尺寸. 科学的文本预处理可以有效的指导模型超参数的选择, 提升模型的评估指标 文本处理形式 分词 词性标注 命名实体识别…

外卖点餐系统小程序

目录 开发前准备 项目展示项目分析项目初始化封装网络请求 任务1 商家首页 任务分析焦点图切换中间区域单击跳转到菜单列表底部商品展示 任务2 菜单列表 任务分析折扣信息区设计菜单列表布局请求数据实现菜单栏联动单品列表功能 任务3 购物车 任务分析设计底部购物车区域添加商…

彻底理解如何保证ElasticSearch和数据库数据一致性问题

一.业务场景举例 需求: 一个卖房业务,双十一前一天,维护楼盘的运营人员突然接到合作开发商的通知,需要上线一批热门的楼盘列表,上传完成后,C端小程序支持按楼盘的名称、户型、面积等产品属性全模糊搜索热门…

单片机将图片数组调出来显示MPU8_8bpp_Memory_Write

界面显示图片是很常见的需求,使用外挂的FLASH是最常用的方法。但是如果图片需求不大,比如说我们只要显示一个小图标,那么为了节省硬件成本,是不需要外挂一颗FLASH芯片的,我们可以将图标转成数组,存在单片机…