• 设计模式


    参考:http://terrylee.cnblogs.com/archive/2006/03/11/347919.html

    简介

    树状结构中,对于枝节点和叶节点,接口不同,客户端需要判断处理的节点类型。

    场景

    对于规模比较大的公司,其组织架构一般是:总公司,下面有分公司和直属部门(总公司的人事、财务、行政),分公司下面又有直属部门(分公司的人事、财务、行政)和支公司,支公司下面是各个部门。

    在客户端程序中,需要判断返回对象的具体类型到底是公司还是部门。如果是公司,则需要递归处理。

    这增加了客户端程序与复杂元素内部结构之间的依赖。组合模式可以解决这种问题。

    模式定义

    组合模式:将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。

    组合模式模糊了树型结构问题中简单元素和复杂元素的概念,客户程序可以跟处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。

    模式特点

    组合模式包含四个角色:

    • Component:对象声明接口,声明所有类共有的默认行为
    • Composite:有子节点的节点,存储子节点并实现 Component 接口有关操作
    • Leaf:叶节点,没有子节点,用于定义对象的基本行为
    • Client:客户类

    组合模式
    组合模式可以不提供父对象的管理方法,但必须提供子对象的管理方法(add、remove 等)。

    根据所实现接口的区别,组合模式包括两种:

    • 透明组合模式:叶节点和枝节点接口统一。在 Component 中声明所有用来管理子对象的方法(Add、Remove 等)。这样实现 Component 接口的所有子类都具备了管理子对象的方法。问题很明显,因为 Leaf 类本身不具备管理子对象的功能,所以实现的部分方法没有意义。
    • 安全组合模式:叶节点和枝节点接口不统一。不在 Component 中声明用来管理子对象的方法,而是在 Composite 声明所有用来管理子类对象的方法。问题也很明显,叶节点和枝节点将不具有相同的接口,客户端需要进行判断。

    优点

    • 将客户代码与复杂的对象容器结构解耦,客户代码只和抽象接口发生依赖关系
    • 透明组合模式的叶节点和枝节点有完全一致的行为接口

    缺点

    • 透明组合模式的叶节点中,部分接口是没有意义的
    • 安全组合模式的叶节点和枝节点具有不同的接口,客户端调用需要做相应的判断

    PHP 代码示例

    
    <?php
    
    abstract class Component {
        protected $name;
    
        public function __construct($name) {
            $this->name = $name;
        }
    
        public abstract function Add(Component $c);
        public abstract function Remove(Component $c);
        public abstract function Display(int $depth);
    }
    
    class Composite extends Component {
        private $children = array();
    
        public function Add(Component $c) {
            array_push($this->children, $c);
        }
    
        public function Remove(Component $c) {
            array_pop($this->children);
        }
    
        public function Display(int $depth) {
            echo '-' . $depth . '  ' . $this->name . "<br/>";
    
            foreach ($this->children as $component) {
                $component->Display($depth + 2);
            }
        }
    }
    
    class Leaf extends Component {
        public function Add(Component $c) {
            echo "Cannot add to a leaf" . "<br/>";
        }
    
        public function Remove(Component $c) {
            echo "Cannot remove from a leaf" . "<br/>";
        }
    
        public function Display(int $depth) {
            echo '-' . depth . $this->name . "<br/>";
        }
    }
    
    echo '<pre>';
    
    $root = new Composite("root");
    $root->Add(new Leaf("Leaf A"));
    $root->Add(new Leaf("Leaf B"));
    
    $comp = new Composite("Composite X");
    $comp->Add(new Leaf("Leaf XA"));
    $comp->Add(new Leaf("Leaf XB"));
    
    $root->Add($comp);
    
    $comp2 = new Composite("Composite XY");
    $comp2->Add(new Leaf("Leaf XYA"));
    $comp2->Add(new Leaf("Leaf XYB"));
    
    $comp->Add($comp2);
    
    $root->Add(new Leaf("Leaf C"));
    
    print_r($root);
    
    $leaf = new Leaf("Leaf D");
    $root->Add($leaf);
    $root->Remove($leaf);
    
    $root->Display(1);

    输出:

    Composite Object
    (
        [children:Composite:private] => Array
            (
                [0] => Leaf Object
                    (
                        [name:protected] => Leaf A
                    )
    
                [1] => Leaf Object
                    (
                        [name:protected] => Leaf B
                    )
    
                [2] => Composite Object
                    (
                        [children:Composite:private] => Array
                            (
                                [0] => Leaf Object
                                    (
                                        [name:protected] => Leaf XA
                                    )
    
                                [1] => Leaf Object
                                    (
                                        [name:protected] => Leaf XB
                                    )
    
                                [2] => Composite Object
                                    (
                                        [children:Composite:private] => Array
                                            (
                                                [0] => Leaf Object
                                                    (
                                                        [name:protected] => Leaf XYA
                                                    )
    
                                                [1] => Leaf Object
                                                    (
                                                        [name:protected] => Leaf XYB
                                                    )
    
                                            )
    
                                        [name:protected] => Composite XY
                                    )
    
                            )
    
                        [name:protected] => Composite X
                    )
    
                [3] => Leaf Object
                    (
                        [name:protected] => Leaf C
                    )
    
            )
    
        [name:protected] => root
    )
    -1  root
    -depthLeaf A
    -depthLeaf B
    -3  Composite X
    -depthLeaf XA
    -depthLeaf XB
    -5  Composite XY
    -depthLeaf XYA
    -depthLeaf XYB
    -depthLeaf C
  • 相关阅读:
    学习SpringMVC——从HelloWorld开始
    线性队列
    线性表之链表
    线性表之顺序表
    nextSibling 属性与 nextElementSibling 属性的异同
    JavaScript数组增删方法总结
    class关键字
    JS三座大山_单线程&EventLoop
    JS三座大山_闭包
    JS三座大山_原型与原型链
  • 原文地址:https://www.cnblogs.com/kika/p/10851560.html
Copyright © 2020-2023  润新知