zoukankan      html  css  js  c++  java
  • php设计模式七 ---组合模式

    1.介绍

    组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。

    这种模式创建了一个包含自己对象组的类。该类提供了修改相同对象组的方式。

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

    主要解决:它在我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以向处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。

    何时使用: 1、您想表示对象的部分-整体层次结构(树形结构)。 2、您希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。

    如何解决:树枝和叶子实现统一接口,树枝内部组合该接口。

    优点: 1、高层模块调用简单。 2、节点自由增加。

    缺点:在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则。

    2.案例

    1、抽象角色(MenuComponent),给参加组合的对象规定一系列接口。接口中包括管理节点的方法

       在本例中如add及remove方法。MenuComponent中可以定义一些接口的默认动作。

    2、树叶组件(Leaf)角色:在组合中表示叶节点对象,叶节点没有子节点。在组合中定义图元对象的行为。

       在本例中为MenuItem,为菜单的具体项,不可以有子项。

    3、树枝组件(Composite)角色:存储子部件。定义有子部件的那些部件的行为。在Component接口中实现与子部件有关的操作。

       在本例中为Menu,为菜单项,菜单项包含了一个menuComponents数组来储存MenuItem。

    // 1.抽象角色
    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();
    }
    
    // 2 叶子组件
    class MenuItem extends MenuComponent{
        public function __construct( $name ){
            $this->name = $name;
        }
    
        public function getName(){
            return $this->name;
        }
    
        public function add( MenuComponent $menu ){
            return ;
        }
    
        public function remove( MenuComponent $menu ){
            return ;
        }
    
        public function getChild($i){
            return ;
        }
    
        public function show(){
            echo '&nbsp;|-'.$this->getName()."<br/>";
        }
    }
    
    // 3树枝组合
    class Menu extends MenuComponent{
        public $menuComponents = [];
    
        public function __construct( $name ){
            $this->name = $name;
        }
    
        public function getName(){
            return $this->name;
        }
    
        public function add( MenuComponent $menu ){
            if (in_array($menu, $this->menuComponents,true)){
                return ;
            }
            $this->menuComponents[] = $menu;
        }
    
        public function remove( MenuComponent $menu ){
            if($key = array_search($menu, $this->menuComponents)){
                unset($this->menuComponents[$key]);
            }
        }
    
        public function getChild($i){
            if( isset($this->menuComponents[$i]) ){
                return $this->menuComponents[$i];
            }
            return ;
        }
    
        public function show(){
            echo ":".$this->getName()."<br/>";
            foreach($this->menuComponents as $val ){
                $val->show();
            }
        }
    }
    
    $menu = new Menu('china');
    $menu->add( new MenuItem('shanghai'));
    $menu->add( new MenuItem('beijing'));
    
    $menu->show();

    总结:1.部分中,必须实现抽象类的方法,导致了部分肥胖,违背了接口隔离原则;如果不适应抽象,有违背了依赖倒置原则;

    参考资料:http://www.cnblogs.com/colorstory/p/2662308.html

  • 相关阅读:
    Spark学习笔记1
    Scala学习笔记
    Scala实现网站流量实时分析
    使用Docker搭建Spark集群(用于实现网站流量实时分析模块)
    使用Docker搭建Hadoop集群(伪分布式与完全分布式)
    Docker配置阿里云镜像源
    从centos7镜像到搭建kubernetes集群(kubeadm方式安装)
    来做一个简单的成绩查询!(输入输出)
    String类的知识点(不断更新)
    人机猜拳游戏Java
  • 原文地址:https://www.cnblogs.com/myvic/p/8074106.html
Copyright © 2011-2022 走看看