互聯網公司流行扁平化管理,也就是管理層級盡量少于或者不超過三層,作為一個底層的碼農,你的CEO和你的職級也就相差3層以內,但是很多傳統企業,則會有非常深的層級關系,從資料結構看,這種按職能進行分組的組織架構非常像一顆樹,而我們今天介紹的組合模式的作用就和這個企業組織架構層級的模式非常類似,
Gof類圖及解釋
GoF定義:將物件組合成樹形結構以表示“部分-整體”的層次結構,Composite使得用戶對單個物件和組合物件的使用具有一致性
GoF類圖

代碼實作
abstract class Component
{
protected $name;
public function __construct($name){
$this->name = $name;
}
abstract public function Operation(int $depth);
abstract public function Add(Component $component);
abstract public function Remove(Component $component);
}
抽象出來的組合節點宣告,在適當情況下實作所有類的公共介面的預設行為,是所有子節點的父類,
class Composite extends Component
{
private $componentList;
public function Operation($depth)
{
echo str_repeat('-', $depth) . $this->name . PHP_EOL;
foreach ($this->componentList as $component) {
$component->Operation($depth + 2);
}
}
public function Add(Component $component)
{
$this->componentList[] = $component;
}
public function Remove(Component $component)
{
$position = 0;
foreach ($this->componentList as $child) {
++$position;
if ($child == $component) {
array_splice($this->componentList, ($position), 1);
}
}
}
public function GetChild(int $i)
{
return $this->componentList[$i];
}
}
具體的節點實作類,保存下級節點的參考,定義實際的節點行為,
class Leaf extends Component
{
public function Add(Component $c)
{
echo 'Cannot add to a leaf' . PHP_EOL;
}
public function Remove(Component $c)
{
echo 'Cannot remove from a leaf' . PHP_EOL;
}
public function Operation(int $depth)
{
echo str_repeat('-', $depth) . $this->name . PHP_EOL;
}
}
葉子節點,沒有子節點的最終節點,
- 從來代碼來看,完全就是一顆樹的實作
- 所有的子節點和葉子節點都可以處理資料,但葉子節點為終點
- 你希望用戶可以忽略組合物件與單個物件的不同,統一地使用組合結構中的所有物件時,就應該考慮使用組合模式
- 用戶不用關心到底是處理一個葉節點還是處理一個組合組件 ,也就用不著為定義組合而寫一些選擇判斷陳述句了
- 組合模式可以讓客戶一致性地使用組合結構和單個物件
接著文章最開頭的例子來說,在我們的組織架構中,一項任務下達到最底的人員時,會經歷多個層級,我還是比較喜歡傳統一起的企業管理方式,通常是一名總監對應多個主管,一名主管對應多位經理,一位經理對應多位組長,一名組長對應多名員工,當一個通知下發時,每一層級的作業人員都要做出回應,并將通知繼續下發到下屬員工那里,同時從下屬哪里獲得反饋,這樣,我們就不知不覺地在實踐中完成了一次組合模式的應用,突然感覺自己棒棒噠,感覺人生已經到達了巔峰!!
完整代碼:https://github.com/zhangyue0503/designpatterns-php/blob/master/14.composite/source/composite.php
實體
短信短信,這個功能我們可以是翻來覆去的用了,這次也不例外,這一回我們的網站后臺的功能是要針對不同分站和不同來源的用戶進行短信的發送,在這里,我們依然只關注短信發送這件事兒,我們希望給你不同渠道角色但包含統一行為的用戶,你來進行發送就行了,這樣的功能似乎并不難吧!
短信發送類圖

完整原始碼:https://github.com/zhangyue0503/designpatterns-php/blob/master/14.composite/source/composite-msg.php
<?php
abstract class Role
{
protected $userRoleList;
protected $name;
public function __construct(String $name)
{
$this->name = $name;
}
abstract public function Add(Role $role);
abstract public function Remove(Role $role);
abstract public function SendMessage();
}
class RoleManger extends Role
{
public function Add(Role $role)
{
$this->userRoleList[] = $role;
}
public function Remove(Role $role)
{
$position = 0;
foreach ($this->userRoleList as $n) {
++$position;
if ($n == $role) {
array_splice($this->userRoleList, ($position), 1);
}
}
}
public function SendMessage()
{
echo "開始發送用戶角色:" . $this->name . '下的所有用戶短信', PHP_EOL;
foreach ($this->userRoleList as $role) {
$role->SendMessage();
}
}
}
class Team extends Role
{
public function Add(Role $role)
{
echo "小組用戶不能添加下級了!", PHP_EOL;
}
public function Remove(Role $role)
{
echo "小組用戶沒有下級可以洗掉!", PHP_EOL;
}
public function SendMessage()
{
echo "小組用戶角色:" . $this->name . '的短信已發送!', PHP_EOL;
}
}
// root用戶
$root = new RoleManger('網站用戶');
$root->add(new Team('主站用戶'));
$root->SendMessage();
// 社交版塊
$root2 = new RoleManger('社交版塊');
$managerA = new RoleManger('論壇用戶');
$managerA->add(new Team('北京論壇用戶'));
$managerA->add(new Team('上海論壇用戶'));
$managerB = new RoleManger('sns用戶');
$managerB->add(new Team('北京sns用戶'));
$managerB->add(new Team('上海sns用戶'));
$root2->add($managerA);
$root2->add($managerB);
$root2->SendMessage();
說明
- 當我要發送論壇版塊的用戶時,我可以自由地添加各地方站的葉子節點來控制發送物件
- 你可以把整個$root2的發送看作是一個整體,不同的版塊和地區看成是部分
- 這個組合可以一直向下延伸,直到深度的葉子節點結束,這個度當然是由自己來把控,很清晰明了
下期看點
組合模式最大的特點就是可以讓葉子節點或者子節點無限的組合和延伸,能夠形成各種不同的組合方式,但又能保證萬變不離其宗,讓整個遞回是在可控的范圍內進行,很牛X吧!!下一篇我們將學習到的是中介者模式,它和我們經常打交道的房產中介有什么區別呢?別急,下次再聊!
關注公眾號:【硬核專案經理】獲取最新文章
添加微信/QQ好友:【xiaoyuezigonggong/149844827】免費得PHP、專案管理學習資料
知乎、公眾號、抖音、頭條搜索【硬核專案經理】
B站ID:482780532
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/240346.html
標籤:PHP
下一篇:Python之猜拳游戲
