设计模式 | 组合模式
时间:2022-07-22
本文章向大家介绍设计模式 | 组合模式,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
说明
模式定义: 组合模式(Composite Pattern)有时候又叫做部分-整体模式,用于将对象组合成树形结构以表示“部分-整体”的层次关系。组合模式使得用户对单个对象和组合对象的使用具有一致性。
常见使用场景:如树形菜单、文件夹菜单、部门组织架构图等。
说到树形就需要先说说树的基本构成:
- 根节点
是树的一个组成部分,也叫树根。它是同一棵树中除本身外所有结点的祖先,没有父结点。
- 叶子结点
一棵树当中没有子结点(即度为0)的结点。 叶子是指度为0的结点,又称为终端结点。
- 子树
子树就是树的其中一个节点以及其下面的所有的节点所构成的树
组合模式结构说明
在组合模式中有三个角色, Component
、Leaf
、Composite
, 我们分别看一下
- Component
这是组合模式中对象声明的接口, 在适当情况下, 实现所有类共有的接口默认行为, 用于访问和管理Component
部件, Component
可以是抽象类或者接口。
- Leaf
在组合中表示叶子结点, 叶子结点没有子节点
- Composite
非叶子结点, 用于存储子部件, 在Component
接口中实现子部件的相关操作, 比如增加
示例
编写程序展示一个学校的院系结构,需求: 要在一个页面中展示出学校的院系组成,一个学校有多个学院,一个学院有多个系
<?php
/**
* Created by 憧憬.
*/
abstract class OrganizationComponent {
private $name;
private $des;
/**
* OrganizationComponent constructor.
* @param $name
* @param $des
*/
public function __construct($name, $des)
{
$this->name = $name;
$this->des = $des;
}
/**
* @return mixed
*/
public function getName()
{
return $this->name;
}
/**
* @param mixed $name
*/
public function setName($name): void
{
$this->name = $name;
}
/**
* @return mixed
*/
public function getDes()
{
return $this->des;
}
/**
* @param mixed $des
*/
public function setDes($des): void
{
$this->des = $des;
}
/**
* 添加
* @param OrganizationComponent $organizationComponent
* @throws Exception
* @author: 憧憬
*/
public function add(OrganizationComponent $organizationComponent)
{
throw new Exception('没有add');
}
/**
* 删除
* @param OrganizationComponent $organizationComponent
* @throws Exception
* @author: 憧憬
*/
public function remove(OrganizationComponent $organizationComponent)
{
throw new Exception('没有remove');
}
/**
* 输出
* @return mixed
* @author: 憧憬
*/
abstract public function iprint();
}
/**
* 大学
* 是Composite角色, 可以管理College
* Class University
*/
class University extends OrganizationComponent {
public $organizationComponents;
/**
* University constructor.
* @param $name
* @param $des
*/
public function __construct($name, $des)
{
parent::__construct($name, $des);
$this->organizationComponents = [];
}
public function add(OrganizationComponent $organizationComponent)
{
$this->organizationComponents[] = $organizationComponent;
}
public function remove(OrganizationComponent $organizationComponent)
{
foreach ($this->organizationComponents as $k => $component) {
if ($component == $organizationComponent) {
unset($this->organizationComponents[$k]);
}
}
}
public function getName()
{
return parent::getName(); // TODO: Change the autogenerated stub
}
public function getDes()
{
return parent::getDes(); // TODO: Change the autogenerated stub
}
/**
* 输出University 包含的学院
* @return mixed|void
* @author: 憧憬
*/
public function iprint()
{
echo '---------------'. $this->getName() .'--------学校' . PHP_EOL;
foreach ($this->organizationComponents as $component) {
$component->iprint();
}
}
}
/**
* 学院
* Class College
*/
class College extends OrganizationComponent {
// 包含的college
public $organizationComponents;
/**
* University constructor.
* @param $name
* @param $des
*/
public function __construct($name, $des)
{
parent::__construct($name, $des);
$this->organizationComponents = [];
}
public function add(OrganizationComponent $organizationComponent)
{
$this->organizationComponents[] = $organizationComponent;
}
public function remove(OrganizationComponent $organizationComponent)
{
foreach ($this->organizationComponents as $k => $component) {
if ($component == $organizationComponent) {
unset($this->organizationComponents[$k]);
}
}
}
public function getName()
{
return parent::getName(); // TODO: Change the autogenerated stub
}
public function getDes()
{
return parent::getDes(); // TODO: Change the autogenerated stub
}
/**
* 输出University 包含的系
* @return mixed|void
* @author: 憧憬
*/
public function iprint()
{
echo '---------------'. $this->getName() .'-------学院' . PHP_EOL;
foreach ($this->organizationComponents as $component) {
$component->iprint();
}
}
}
/**
* 系 属于叶子结点 所以不需要重写add和remove
* Class Department
*/
class Department extends OrganizationComponent {
public function __construct($name, $des)
{
parent::__construct($name, $des);
$this->organizationComponents = [];
}
public function iprint()
{
// TODO: Implement iprint() method.
echo '-------------'.$this->getName(). '--------系'.PHP_EOL;
}
}
// 创建学校
$university = new University('清华大学', '中国顶级大学');
// 创建学院
$computerCollege = new College('计算机学院', '计算机学院');
$infoEngineerCollege = new College('信息工程学院', '信息工程学院');
// 创建学院下的个个系
$computerCollege->add(new Department('软件工程', '软件工程ok'));
$computerCollege->add(new Department('网络工程', '网络工程ok'));
$computerCollege->add(new Department('计算机科学与技术', '计算机科学与技术ok'));
$infoEngineerCollege->add(new Department('通信工程', '通信工程不ok'));
$infoEngineerCollege->add(new Department('信息工程', '信息工程不ok'));
// 将学院加入学校
$university->add($computerCollege);
$university->add($infoEngineerCollege);
// 输出整个大学下面的子节点
$university->iprint();
echo PHP_EOL;
// 输出计算机学院下面的子节点
$computerCollege->iprint();
// 如果再要强化级别 只需要接着实现 组合进来就可以 比较方便
- JS原型,a和b是不是失散多年的兄弟?
- Linux shell 程序设计1——安装及入门
- 偶遇--《坑新人--前端专用面试题》
- 简单的说下,(function(){...})() 与 (function(){...}()) 有什么区别?
- ASP.NET Process Model之二:ASP.NET Http Runtime Pipeline[上篇]
- Shell常用命令小结
- 插入法排序
- ASP.NET Process Model之二:ASP.NET Http Runtime Pipeline - Part II
- 震惊了!这样的js面试题让所有人-男默女泪
- 前端知识学了却不会用,都是没走心
- var a="xx";a=a+"ss";a的值变了,但"xx"字符串并没有变
- 先行者计划--1109微课总结 | 《通过二个demo初识webPack》
- 先行者计划--1107微课 《什么是Vuex?》| 文字简版
- 脱离前端菜鸟层次的二个关键点
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法