PHP设计模式---组合模式(Composite Pattern)

定义

允许将对象组合成树形结构来表现整体部分的参差结构,组合能让客户以一致的方式处理个别对象以及对象的组合

原理

定义一个接口,所有类都继承这个接口(这为客户能一直处理枝叶对象提供了可能,因为每个类都要实现这里的每一个抽象方法)

abstract classc MenuComponent {
    //获得类名称
    public $name;
    //添加类别
    public abstract function getName();
    //删除类别
    public abstract function add(MenuComponent $menu);
    //获得子类别
    public abstract function remove(MenuComponent $menu);
    //显示类别名称
    public abstract function getChild($i);
    public abstract function show();
}

叶子类它内部没有别的类,是最底层的类,继承接口的时候就添加跟删除返回一个假
树干类它有一个属性用来以数组的形式存储叶子类对象,对应的就应该在添加跟删除中实现添加跟删除叶子类的实现
这两种类还有3个方法需要实现,分别是getname 用来返回这个类的名字 getchild 获得类的子类 show 如果是树干类就进行遍历如果不是
就不遍历,这个方法有种递归的意思,当数组中的元素还是个树干就在遍历;这样才能显示出树形菜单的效果

代码示例

所有树状菜单都继承的接口
abstract class MenuComponent
{
        //获得类名称
        public $name;
        //添加类别
        public abstract function getName();
        //删除类别
        public abstract function add(MenuComponent $menu);
        //获得子类别
        public abstract function remove(MenuComponent $menu);
        //显示类别名称
        public abstract function getChild($i);
        public abstract function show();
}
枝叶(最底层类)类
class MenuItem extends MenuComponent
{
    public function __construct($name)
    {
        $this->name = $name;
    }
    public function getName(){
        return $this->name;
    }
    public function add(MenuComponent $menu){
        return false;
    }
    public function remove(MenuComponent $menu){
        return false;
    }
    public function getChild($i){
        return null;
    }
    public function show(){
        echo " |-".$this->getName()."<br />";
    }
}
树干(一级类别)类
class Menu extends MenuComponent
{
    public $menuComponents = array();
    public function __construct($name)
    {
        $this->name = $name;
    }
        public function getName()
    {
        return $this->name;
    }
    public function add(MenuComponent $menu)
    {
        $this->menuComponents[] = $menu;
    }
    public function remove(MenuComponent $menu)
    {
        $key = array_search($menu, $this->menuComponents);
        if($key !== false) unset($this->menuComponents[$key]);
    }
    public function getChild($i)
    {
        if(isset($this->menuComponents[$i])) return $this->menuComponents[$i];
        return null;
    }
    public function show()
    {
        echo ":" . $this->getName() . "<br />";
        foreach($this->menuComponents as $v){
        $v->show();
        }
    }
}
测试代码
class testDriver
{
    public function run()
    {
        $menu1 = new Menu('文学');//根分类
        $menuitem1 = new MenuItem('绘画');//第一个子类
        $menuitem2 = new MenuItem('书法');//第二个子类
        $menuitem3 = new MenuItem('小说');//第三个子类
        $menuitem4 = new Menu('雕刻');//第四个子类
        $menu1->add($menuitem1);
        $menu1->add($menuitem2);
        $menu1->add($menuitem3);
        $menuitem5=new MenuItem('核雕');//第四个子类的第一个子类
        $menuitem6=new MenuItem('石雕');//第四个子类的第二个子类
        $menuitem4->add($menuitem5);
        $menuitem4->add($menuitem6);
        $menu1->add($menuitem4);
        //$menu1->add($menuitem4);
        $menu1->show();//显示类别
    }
}

//测试代码:
$test = new testDriver();
$test->run();