PHP設計模式之組合模式

互聯網公司流行扁平化管理,也就是管理層級儘可能少於或者不超過三層,做爲一個底層的碼農,你的CEO和你的職級也就相差3層之內。可是不少傳統企業,則會有很是深的層級關係,從數據結構看,這種按職能進行分組的組織架構很是像一顆樹。而咱們今天介紹的組合模式的做用就和這個企業組織架構層級的模式很是相似。php

Gof類圖及解釋

GoF定義:將對象組合成樹形結構以表示「部分-總體」的層次結構。Composite使得用戶對單個對象和組合對象的使用具備一致性git

GoF類圖github

組合模式

代碼實現微信

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.phpthis

實例

短信短信,這個功能咱們能夠是翻來覆去的用了。此次也不例外。這一回咱們的網站後臺的功能是要針對不一樣分站和不一樣來源的用戶進行短信的發送。在這裏,咱們依然只關注短信發送這件事兒,咱們但願給你不一樣渠道角色但包含統一行爲的用戶,你來進行發送就好了,這樣的功能彷佛並不難吧!3d

短信發送類圖

短信發送組合模式版

完整源碼: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

相關文章
相關標籤/搜索