1. 将对象组合成树形结构以表示“部分-整体”的层次结构,composite使得用户对单个对象和组合对象的使用具有一致性,<br />说白了就是用对象组成一个树形结构,用户在操作的时候不用在意对象是单一的,还是多个对象,只用一个操作就可以,剩余的交给组合模式的属性结构来解决<br />定义一个数组,每次添加一个对象,对象分为叶子节点,跟节点,节点可以有子节点,可以操作子节点,<br />将A B C 三个对象添加到X对象中,X Y对象再添加到1对象中,这就是树形结构<br />角色:<br />component:组合中的对象接口声明,在适当的情况加实现所有类拥有的默认行为,<br />leaf:在组合中表示叶子节点,没有子节点,<br />composite:定义有子节点的行为,储存子节点,并在接口中实现与子类有关的操作(增加删除)<br />client:最终调用组合部件的对象<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/22438777/1635387380129-28048b1f-9f51-4f9f-95c8-5d530f45c2b7.png#clientId=u873a798d-b96e-4&from=paste&height=486&id=uc2c28b33&margin=%5Bobject%20Object%5D&name=image.png&originHeight=486&originWidth=1091&originalType=binary&ratio=1&size=65766&status=done&style=none&taskId=u55ef2972-07f6-4677-8073-22876a234d7&width=1091)
    <?php
    
     //组合接口类
    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) {
                if ($child == $component) {
                    array_splice($this->componentList, ($position), 1);
                }
                ++$position;
            }
        }
    
        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;
        }
    }
    
    $root =new Composite('root');
    
    $root->add(new Leaf('航母'));
    $root->add(new Leaf('潜艇'));
    
    
    $comp1=new Composite('坦克');
    $comp1->add(new Leaf('冲锋车'));
    $comp1->add(new Leaf('装甲车'));
    
    $root->add($comp1);
    
    $comp1->add(new Leaf('重坦'));
    
    $root->add(new Composite('飞机'));
    var_dump($root);
    
    $root->Remove(new Leaf('潜艇'));
    
    //var_dump($root->GetChild(0));
    $root->Operation(1);
    // var_dump($root);
    
    
    class Composite#1 (2) {
      private $componentList =>
      array(4) {
        [0] =>
        class Leaf#2 (1) {
          protected $name =>
          string(6) "航母"
        }
        [1] =>
        class Leaf#3 (1) {
          protected $name =>
          string(6) "潜艇"
        }
        [2] =>
        class Composite#4 (2) {
          private $componentList =>
          array(3) {
            ...
          }
          protected $name =>
          string(6) "坦克"
        }
        [3] =>
        class Composite#8 (2) {
          private $componentList =>
          NULL
          protected $name =>
          string(6) "飞机"
        }
      }
      protected $name =>
      string(4) "root"
    }
    
    实例 比如说发送短信,定义很多组,需要给固定的组,以及组员发送短信,就可以用组合模式,定义好关系,发送短息,只用一个组长,发送,组员(子节点)也会发送<br />组合模式有两种实现方式,透明式的组合模式,安全式的组合模式<br />上面的就是透明式的,一个组合接口定义所有用到的方法,但是叶子节点不用操作子类,也没有子类,有的方法就没有用了,万一调用可能会报错,(实现为空,不操作没事),所以提出了安全式<br />安全式就是定义一个组合接口,里之定义叶子节点的方法,然后节点自己再继承顶一个一个节点接口,自己使用,相当于定义了两个接口,子节点跟叶子节点,