组合模式
组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。
这种模式创建了一个包含自己对象组的类。该类提供了修改相同对象组的方式。
示例 - 导航菜单
每个菜单都有自己的属性(包含:icon、名称、链接、子菜单)
设计一个菜单类
<?php
namespace App\Console\Test\Menu;
/**
* 菜单
*/
class Menu
{
//菜单名称
public string $name;
//菜单icon
public string $icon;
//点击链接
public string $url;
//子菜单
public array $items = [];
public function __construct(string $name)
{
$this->setName($name);
}
public function addMenu(Menu $menu)
{
array_push($this->items,$menu);
}
public function setName(string $name)
{
$this->name = $name;
}
public function display()
{
dd($this);
}
//菜单转数组
public function toArray() : array
{
$data = [
'name' => $this->getName()
];
if(!empty($this->url))
$data['url'] = $this->getUrl();
if(!empty($this->icon))
$data['icon']= $this->getIcon();
if(!empty($this->items))
{
$data['menus'] = [];
foreach($this->items as $item)
{
array_push($data['menus'],$item->toArray());
}
}
return $data;
}
/**
* @return string
*/
public function getIcon(): string
{
return $this->icon;
}
/**
* @param string $icon
*/
public function setIcon(string $icon): void
{
$this->icon = $icon;
}
/**
* @return string
*/
public function getUrl(): string
{
return $this->url;
}
/**
* @param string $url
*/
public function setUrl(string $url): void
{
$this->url = $url;
}
/**
* @return array
*/
public function getItems(): array
{
return $this->items;
}
/**
* @param array $items
*/
public function setItems(array $items): void
{
$this->items = $items;
}
public function getName() : string
{
return $this->name;
}
}
接下来我们开始组装菜单。在组装前我们先定义一个菜单配置,声明菜单与菜单之间的关系
//菜单配置
public function getMenuData()
{
return [
'name' => '菜单',
'menus' => [
[
'name' => '系统设置',
'icon' => 'aaa',
'menus' => [
[
'name' => '文件上传配置',
'url' => '1',
'icon' => '123'
],
[
'name' => '系统设置',
'url' => '2',
'icon' => '123'
],
[
'name' => '支付设置',
'url' => '3',
'icon' => '123'
],
[
'name' => '网站设置',
'url' => '4',
'icon' => '123'
]
]
],
[
'name' => "用户管理",
'icon' => 'bbb',
'menus' => [
[
'name' => '粉丝管理',
'url' => '5'
],
[
'name' => '商户管理',
'url' => '6'
]
]
],
[
'name' => '应用管理',
'icon' => 'ccc',
'menus' => [
[
'name' => '秒杀',
'url' => '7'
],
[
'name' => '砍价',
'url' => '8'
],
]
]
]
];
}
组装菜单
//组装菜单方法
public function structMenu(array &$menuConfig) : Menu
{
if(!isset($menuConfig['name']))
throw new \Exception("not get name",101);
$menu = new Menu($menuConfig['name']);
//属性
if(isset($menuConfig['url']))
$menu->setUrl($menuConfig['url']);
//属性
if(isset($menuConfig['icon']))
$menu->setIcon($menuConfig['icon']);
//子菜单
if(isset($menuConfig['menus']) && !empty($menuConfig['menus']))
{
foreach($menuConfig['menus'] as $childrenMenuConfig)
{
$menu->addMenu($this->structMenu($childrenMenuConfig));
}
}
return $menu;
}
public function index16()
{
//获取菜单配置
$menuConfig = $this->getMenuData();
//根据菜单配置组装菜单
$menu = $this->structMenu($menuConfig);
//打印菜单
dd($menu->toArray());
}