php设计模式-组合模式的运用
创始人
2024-05-31 20:26:25
0

请添加图片描述

介绍

PHP的组合模式是一种设计模式,用于将对象组合成树形结构以表示“部分-整体”的层次结构。该模式允许客户端统一处理单个对象和组合对象,使得客户端在处理对象时不需要知道对象是否为单个对象还是组合对象。

在组合模式中,有两种类型的对象:组合对象和叶子对象。组合对象是由多个叶子对象组成的对象,它具有与叶子对象相同的接口。而叶子对象是组合对象中最基本的对象,它不能再包含其他对象。

组合模式通常由以下几个角色组成:

抽象组件(Component):定义组合中所有对象的通用接口,可以是抽象类或接口。

叶子组件(Leaf):表示组合中的叶子节点对象,它不能包含任何子对象。

组合组件(Composite):表示组合中的非叶子节点对象,它通常包含多个叶子节点或其他组合对象。

客户端(Client):通过抽象组件接口操作组合中的对象,而不需要知道具体的对象类型。

使用组合模式可以方便地处理层次结构对象,使得客户端可以透明地处理单个对象和组合对象,从而简化了客户端的代码实现。例如,在处理一个树形结构的目录时,可以使用组合模式来方便地处理整个目录结构,无需关注目录中的每个文件或子目录。

场景在这里插入图片描述

组合模式适用于以下场景:

树形结构:当我们需要处理具有层次结构的对象时,可以使用组合模式。例如,图形用户界面中的窗口、控件和组合控件就可以使用组合模式来实现。

部分-整体关系:当我们需要将一些对象视为一个整体时,并且希望能够像处理单个对象一样处理整体,可以使用组合模式。例如,汽车零件和汽车可以被组合成一个整体,并且可以像处理单个零件一样处理整个汽车。

统一接口:当我们需要将对象和组合对象视为具有统一接口的对象时,可以使用组合模式。例如,在文件系统中,文件和目录都有相同的操作接口,因此可以使用组合模式来实现它们。

需要忽略对象集合与单个对象之间的差异:当我们需要忽略对象集合与单个对象之间的差异时,可以使用组合模式。例如,将公司中的所有员工视为相同的对象,以便能够像处理单个员工一样处理整个公司。

可以动态添加和删除对象:当我们需要能够动态添加和删除对象时,可以使用组合模式。例如,在菜单系统中,菜单和子菜单可以被动态添加和删除,因此可以使用组合模式来实现它们。

运用

在这里插入图片描述

组合模式在购物车的运用

在购物车中,我们需要处理一组商品对象,这些商品对象可以是单个商品或商品的组合,例如套餐或礼篮。同时,我们需要能够对购物车中的商品进行添加、删除和计算总价等操作,这些操作可以使用组合模式来实现。

我们可以定义一个抽象类或接口,表示商品和商品组合的公共行为,例如计算价格和获取商品列表。然后,我们可以创建具体的商品类和商品组合类,它们都实现了这个抽象类或接口。商品组合类中包含一组商品对象,可以通过添加或删除单个商品或商品组合来构建更复杂的商品组合。这种嵌套结构形成了一棵树形结构,树的节点是商品或商品组合。

最后,我们可以创建一个购物车类,它包含购物车中的所有商品对象,并提供添加、删除和计算总价等操作。购物车类中的操作可以递归地遍历商品组合树,处理每个商品对象。这样,我们就可以使用组合模式来实现购物车逻辑。

// 抽象类或接口
abstract class Product {abstract public function getPrice();abstract public function getProducts();
}// 商品类
class Item extends Product {private $name;private $price;public function __construct($name, $price) {$this->name = $name;$this->price = $price;}public function getPrice() {return $this->price;}public function getProducts() {return array($this);}
}// 商品组合类
class Combo extends Product {private $name;private $products = array();public function __construct($name) {$this->name = $name;}public function addProduct(Product $product) {$this->products[] = $product;}public function removeProduct(Product $product) {$key = array_search($product, $this->products, true);if ($key !== false) {unset($this->products[$key]);}}public function getPrice() {$totalPrice = 0;foreach ($this->products as $product) {$totalPrice += $product->getPrice();}return $totalPrice;}public function getProducts() {return $this->products;}
}// 购物车类
class ShoppingCart {private $products = array();public function addProduct(Product $product) {$this->products[] = $product;}public function removeProduct(Product $product) {$key = array_search($product, $this->products, true);if ($key !== false) {unset($this->products[$key]);}}public function getTotalPrice() {$totalPrice = 0;foreach ($this->products as $product) {$totalPrice += $product->getPrice();}return $totalPrice;}
}// 示例用法
$item1 = new Item('Product A', 10);
$item2 = new Item('Product B', 20);
$item3 = new Item('Product C', 30);$combo1 = new Combo('Combo 1');
$combo1->addProduct($item1);
$combo1->addProduct($item2);$combo2 = new Combo('Combo 2');
$combo2->addProduct($item2);
$combo2->addProduct($item3);$cart = new ShoppingCart();
$cart->addProduct($item1);
$cart->addProduct($combo1);
$cart->addProduct($combo2);$totalPrice = $cart->getTotalPrice();
echo "Total Price: $totalPrice";

说明在这里插入图片描述

在上面的购物车代码中,Product 抽象类或接口表示商品和商品组合的公共行为,Item 类表示单个商品,Combo 类表示商品组合,ShoppingCart 类表示购物车。因此,在这个示例中,Item 和 Combo 是叶子组件,Combo 是容器组件。

具体来说,Item 是叶子组件,因为它是商品组合树的最底层,没有子组件。它只包含单个商品,提供了获取商品价格和获取商品列表的方法。

而 Combo 是容器组件,它包含了一组商品对象,包括单个商品和其他商品组合。它提供了添加、删除商品和计算价格等方法。因此,它既可以是容器组件,也可以是叶子组件,具体取决于它是否包含其他商品或商品组合。

在购物车中,ShoppingCart 类是容器组件,它包含了购物车中的所有商品对象,包括单个商品和商品组合。它提供了添加、删除商品和计算总价等方法。因此,ShoppingCart 类既可以是容器组件,也可以是叶子组件,具体取决于它是否包含其他商品或商品组合。

综上,根据组合模式的定义,叶子组件表示树形结构中最底层的对象,容器组件表示树形结构中非最底层的对象,它们都实现了相同的接口或抽象类,从而使客户端可以一致地对待它们。在购物车中,商品对象和商品组合对象都实现了 Product 接口,因此它们可以在 ShoppingCart 中互相嵌套,从而形成了一棵树形结构。

相关内容

热门资讯

122.(leaflet篇)l... 听老人家说:多看美女会长寿 地图之家总目录(订阅之前建议先查看该博客) 文章末尾处提供保证可运行...
育碧GDC2018程序化大世界... 1.传统手动绘制森林的问题 采用手动绘制的方法的话,每次迭代地形都要手动再绘制森林。这...
育碧GDC2018程序化大世界... 1.传统手动绘制森林的问题 采用手动绘制的方法的话,每次迭代地形都要手动再绘制森林。这...
Vue使用pdf-lib为文件... 之前也写过两篇预览pdf的,但是没有加水印,这是链接:Vu...
PyQt5数据库开发1 4.1... 文章目录 前言 步骤/方法 1 使用windows身份登录 2 启用混合登录模式 3 允许远程连接服...
Android studio ... 解决 Android studio 出现“The emulator process for AVD ...
Linux基础命令大全(上) ♥️作者:小刘在C站 ♥️个人主页:小刘主页 ♥️每天分享云计算网络运维...
再谈解决“因为文件包含病毒或潜... 前面出了一篇博文专门来解决“因为文件包含病毒或潜在的垃圾软件”的问题,其中第二种方法有...
南京邮电大学通达学院2023c... 题目展示 一.问题描述 实验题目1 定义一个学生类,其中包括如下内容: (1)私有数据成员 ①年龄 ...
PageObject 六大原则 PageObject六大原则: 1.封装服务的方法 2.不要暴露页面的细节 3.通过r...
【Linux网络编程】01:S... Socket多进程 OVERVIEWSocket多进程1.Server2.Client3.bug&...
数据结构刷题(二十五):122... 1.122. 买卖股票的最佳时机 II思路:贪心。把利润分解为每天为单位的维度,然后收...
浏览器事件循环 事件循环 浏览器的进程模型 何为进程? 程序运行需要有它自己专属的内存空间࿰...
8个免费图片/照片压缩工具帮您... 继续查看一些最好的图像压缩工具,以提升用户体验和存储空间以及网站使用支持。 无数图像压...
计算机二级Python备考(2... 目录  一、选择题 1.在Python语言中: 2.知识点 二、基本操作题 1. j...
端电压 相电压 线电压 记得刚接触矢量控制的时候,拿到板子,就赶紧去测各种波形,结...
如何使用Python检测和识别... 车牌检测与识别技术用途广泛,可以用于道路系统、无票停车场、车辆门禁等。这项技术结合了计...
带环链表详解 目录 一、什么是环形链表 二、判断是否为环形链表 2.1 具体题目 2.2 具体思路 2.3 思路的...
【C语言进阶:刨根究底字符串函... 本节重点内容: 深入理解strcpy函数的使用学会strcpy函数的模拟实现⚡strc...
Django web开发(一)... 文章目录前端开发1.快速开发网站2.标签2.1 编码2.2 title2.3 标题2.4 div和s...