【設計模式】組合模式

ajiang02發表於2020-01-13

組合模式用來解決整體和部分可以一致對待的問題

比如說 資料夾 和其下的 檔案;
可以複製檔案也可以複製整個資料夾;

組合模式是將物件組合成樹形結構以表示整體和部分的層次結構;

可以方便的增加節點;

說明

運用tp5框架進行測試;
這裡選用的層次結構是:唐朝的三省六部制
【設計模式】組合模式

程式碼

1、CentralSystem.php檔案(抽象類)
<?php
namespace app\composite\controller;

/**
 * Class CentralSystem  中央官制抽象類,其子類必須實現抽象方法
 */
abstract  class CentralSystem
{
    // 當前類名字
    protected $name;

    // 建構函式,初始化$name
    public function __construct($name)
    {
        $this->name = $name;
    }

    // 獲得類名字
    public function getName()
    {
        return $this->name;
    }

    // 新增子節點
    abstract public function add(CentralSystem $centralSystem);

    // 移除子節點
    abstract public function remove(CentralSystem $centralSystem);

    // 迴圈當前節點的子節點
    abstract public function show($deep);
}
2、Emperor.php檔案 與 Province.php檔案 一樣 (皇帝類和三省類)

可以只寫一個Emperor檔案,不用同我一樣,我就是糾結症犯了

<?php
namespace app\composite\controller;
use think\Exception;

/**
 * Class Emperor 皇帝類,相當於樹的根節點root
 */
class Emperor extends CentralSystem
{
    // 存放其子節點
    protected $office = [];

    /**
     * @param CentralSystem $centralSystem  新增子節點,將子節點放在陣列
     * @throws Exception
     */
    public function add(CentralSystem $centralSystem)
    {
        // 獲取新節點的名字
        $office_name = $centralSystem->getName();

        if (in_array($office_name, $this->office)) {
            throw new Exception($office_name . '節點已經存在');
        } else {
            $this->office[$office_name] = $centralSystem;
        }
    }

    /**
     * @param CentralSystem $centralSystem 移除子節點,將子節點從陣列中移除
     * @throws Exception
     */
    public function remove(CentralSystem $centralSystem)
    {
        // 獲取新節點的名字
        $office_name = $centralSystem->getName();

        if (in_array($office_name, $this->office)) {
            unset($this->office[$office_name]);
        } else {
            throw new Exception($office_name . '節點不存在');
        }
    }

    /**
     * @param int $deep 重複字元'-'的次數
     */
    public function show($deep = 0)
    {
        echo str_repeat('-', $deep) . $this->name;
        echo "</br>";
        // 迴圈子節點的 節點陣列$office
        foreach ($this->office as $item) {
            $item->show($deep + 4);
        }
    }
}
3、Ministries.php檔案 (六部類)
<?php
namespace app\composite\controller;

class Ministries extends CentralSystem
{
    /**
     * @param CentralSystem $centralSystem  葉子節點,沒有子節點
     */
    public function add(CentralSystem $centralSystem)
    {
        echo "葉子節點不能新增子節點";
    }

    public function remove(CentralSystem $centralSystem)
    {
        echo "葉子節點不能移除子節點";
    }

    /**
     * @param int $deep 字元'-'重複的次數
     */
    public function show($deep = 0)
    {
        echo str_repeat('-', $deep) . $this->name. "</br>";
    }
}
4、CompositeTest.php 測試檔案
<?php
namespace app\composite\controller;

/**
 * Class CompositeTest  組合模式測試----唐朝三省六部制
 * 結果:
 * 唐太宗
 * ----門下省
 * ----中書省
 * ----尚書省
 * --------吏部
 * --------戶部
 * --------禮部
 * --------兵部
 * --------刑部
 * --------工部
 */
class CompositeTest
{
    public function test()
    {
        // 唐太宗相當於根節點root
        $emperor = new Emperor('唐太宗');
        // 唐太宗下的三個子節點:門下省、尚書省、中書省
        $emperor->add(new Province('門下省'));
        $emperor->add(new Province('中書省'));
        $shangshu = new Province('尚書省');     // 這裡單獨賦值是因為“尚書省”要另外新增子節點
        $emperor->add($shangshu);

        // 尚書省新增六部
        $shangshu->add(new Ministries('吏部'));
        $shangshu->add(new Ministries('戶部'));
        $shangshu->add(new Ministries('禮部'));
        $shangshu->add(new Ministries('兵部'));
        $shangshu->add(new Ministries('刑部'));
        $shangshu->add(new Ministries('工部'));

        // 迴圈唐太宗的子節點陣列,其子節點又有自己的子節點。
        $emperor->show();
    }
}

【設計模式】組合模式

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章