二、结构型设计模式
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: root
- Directory: home
- File: file1.txt
- File: file2.txt
- Directory: documents
- File: 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
复制代码 小结
代理模式通过在真实对象和客户端之间增加代理对象,实现了对对象访问的控制、耽误加载、权限校验等功能。在现实开发中,代理模式广泛应用于长途调用、资源管理、权限控制等场景,特别是在需要解耦客户端与真实对象时,是一个非常实用的设计模式。
总结
代理模式与其他模式的对比
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |