zoukankan      html  css  js  c++  java
  • PHP设计模式—组合模式

    定义:

    组合模式(Composite):将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。当你发现需求中是体现部分与整体层次的结构时,以及你希望用户可以忽略组合对象与单个对象的不同,统一的使用组合结构中的所有对象时,就应该考虑用组合模式了。

     

    实现方式:

    1、透明方式:叶节点和枝节点对于外界没有什么区别,它们具备完全一致的行为接口,问题则是叶节点会有冗余方法。

    2、安全方式:叶节点中的冗余代码不实现,问题则是由于不够透明,所以叶节点和枝节点将不具有相同的接口,客户端的调用需要做相应的判断,带来了不便。

    代码实例:

    一、透明方式实现:

    // 1、抽象类Component.php
    /**
     * 包含叶节点和枝节点方法的抽象类
     * Class Component
     */
    abstract class Component
    {
        /**
         * @var
         */
        protected $name;
    
        /**
         * Component constructor.
         * @param $name
         */
        public function __construct($name)
        {
            $this->name = $name;
        }
    
    
        /**
         * 添加叶节点或枝节点
         * @param Component $component
         * @return mixed
         */
        abstract public function add(Component $component);
    
    
        /**
         * @param $depth
         * @return mixed
         */
        abstract public function display($depth);
    }
    
    
    // 2、枝节点Composite.php
    /**
     * 枝节点
     * Class Composite
     */
    class Composite extends Component
    {
        /**
         * @var array
         */
        protected $children = [];
    
        /**
         * @param Component $component
         * @return mixed|void
         */
        public function add(Component $component)
        {
            // TODO: Implement add() method.
            $this->children[] = $component;
        }
    
        public function display($depth)
        {
            // TODO: Implement display() method.
            $nameStr = str_repeat('-', $depth) . $this->name . '<br>';
            foreach ($this->children as $component) {
                $nameStr .= $component->display($depth + 2);
            }
            return $nameStr;
        }
    }
    
    
    // 3、叶节点Leaf.php
    /**
     * 叶节点
     * Class Leaf
     */
    class Leaf extends Component
    {
        /**
         * 叶节点不需要添加子节点,但为了保持叶节点和枝节点一致,代码冗余,透明方式
         * @param Component $component
         * @return mixed|string
         */
        public function add(Component $component)
        {
            // TODO: Implement add() method.
            return '叶节点不能添加子节点' . '<br>';
        }
    
        public function display($depth)
        {
            // TODO: Implement display() method.
            return str_repeat('-', $depth) . $this->name . '<br>';
        }
    }

    调用:

    // 生成树根root,根上长出两叶LeafA和LeafB
    $root = new Composite("root");
    $root->add(new Leaf("Leaf A"));
    $root->add(new Leaf("Leaf B"));
    
    // 根上长出分支 CompositeX,分支上也有两叶LeafXA和LeafXB
    $comp = new Composite("Composite X");
    $comp->add(new Leaf("Leaf XA"));
    $comp->add(new Leaf("Leaf XB"));
    $root->add($comp);
    
    // 在CompositeX分支上再长出分支CompositeXY,分支上也有两叶LeafXYA和LeafXYB
    $comp2 = new Composite("Composite XY");
    $comp2->add(new Leaf("Leaf XYA"));
    $comp2->add(new Leaf("Leaf XYB"));
    $comp->add($comp2);
    
    echo $root->display(2);

    结果:

    --root
    ----Leaf A
    ----Leaf B
    ----Composite X
    ------Leaf XA
    ------Leaf XB
    ------Composite XY
    --------Leaf XYA
    --------Leaf XYB

    二、安全方式实现:

    // 1、抽象类Component.php
    /**
     * 包含叶节点和枝节点方法的抽象类
     * Class Component
     */
    abstract class Component
    {
        /**
         * @var
         */
        protected $name;
    
        /**
         * Component constructor.
         * @param $name
         */
        public function __construct($name)
        {
            $this->name = $name;
        }
    
    
        /**
         * @param $depth
         * @return mixed
         */
        abstract public function display($depth);
    }
    
    
    // 2、枝节点Composite.php
    /**
     * 枝节点
     * Class Composite
     */
    class Composite extends Component
    {
        /**
         * @var array
         */
        protected $children = [];
    
        /**
         * @param Component $component
         * @return mixed|void
         */
        public function add(Component $component)
        {
            // TODO: Implement add() method.
            $this->children[] = $component;
        }
    
        public function display($depth)
        {
            // TODO: Implement display() method.
            $nameStr = str_repeat('-', $depth) . $this->name . '<br>';
            foreach ($this->children as $component) {
                $nameStr .= $component->display($depth + 2);
            }
            return $nameStr;
        }
    }
    
    
    // 3、叶节点Leaf.php
    /**
     * 叶节点
     * Class Leaf
     */
    class Leaf extends Component
    {
        public function display($depth)
        {
            // TODO: Implement display() method.
            return str_repeat('-', $depth) . $this->name . '<br>';
        }
    }

    调用:

    // 生成树根root,根上长出两叶LeafA和LeafB
    $root = new Composite("root");
    $root->add(new Leaf("Leaf A"));
    $root->add(new Leaf("Leaf B"));
    
    // 根上长出分支 CompositeX,分支上也有两叶LeafXA和LeafXB
    $comp = new Composite("Composite X");
    $comp->add(new Leaf("Leaf XA"));
    $comp->add(new Leaf("Leaf XB"));
    $root->add($comp);
    
    // 在CompositeX分支上再长出分支CompositeXY,分支上也有两叶LeafXYA和LeafXYB
    $comp2 = new Composite("Composite XY");
    $comp2->add(new Leaf("Leaf XYA"));
    $comp2->add(new Leaf("Leaf XYB"));
    $comp->add($comp2);
    
    echo $root->display(2);

    结果:

    --root
    ----Leaf A
    ----Leaf B
    ----Composite X
    ------Leaf XA
    ------Leaf XB
    ------Composite XY
    --------Leaf XYA
    --------Leaf XYB
  • 相关阅读:
    Android屏幕适配
    设计模式学习心得
    C语言中的作用域、链接属性与存储属性
    二级指针删除单向链表
    C++编程风格
    python中index、slice与slice assignment用法
    lua_pcall与lua_call之间的区别
    lua-C++ userdata使用
    lua中调用C++函数
    C++中为什么有时要使用extern "C"
  • 原文地址:https://www.cnblogs.com/woods1815/p/12822057.html
Copyright © 2011-2022 走看看