在PHP Composite模式,如何设计类的解决需要延长两班(Composite pattern

2019-09-21 03:06发布

我使用的复合模式具有可重复使用的元素来构建一个页面。 此我有一个简单的接口,其驱动模式

interface Ai1ec_Renderable {
    /**
     * This is the main function, it just renders the method for the element,
     * taking care of childrens ( if any )
     */
    public function render();
}

由于只有一些元素将被允许有孩子,我已经创建了一个抽象类,增加了该行为

abstract class Ai1ec_Can_Have_Children {
    /**
     *
     * @var array
     */
    protected $renderables = array();
    /**
     * Adds a renderable child to the element
     * 
     * @param Ai1ec_Renderable $renderable
     */
    public function add_renderable_children( Ai1ec_Renderable $renderable ) {
        $this->renderables[] = $renderable;
    }
}

因此,如果该对象可以有孩子它扩展了抽象类。 出现这个问题,因为我有HTML元素的第二个抽象类

abstract class Ai1ec_Html_Element {
    /**
     *
     * @var string
     */
    protected $id;
    /**
     *
     * @var array
     */
    protected $classes = array();
    /**
     *
     * @param $id string        
     */
    public function set_id( $id ) {
        $this->id = $id;
    }

    public function add_class( $class ) {
        $this->classes[] = $class;
    }
    protected function create_class_markup() {
        if (empty( $this->classes )) {
            return '';
        }
        $classes = implode( ' ', $this->classes );
        return "class='$classes'";
    }
    protected function create_attribute_markup( 
        $attribute_name, 
        $attribute_value
    ) {
        if (empty( $attribute_value )) {
            return '';
        }
        return "$attribute_name='$attribute_value'";
    }
}

问题是,复合材料的所有对象必须实现的接口,其中一些必须扩展只有第一类(can_have_children),而不是第二个(这是因为他们是更高层次的抽象,配置另一个渲染对象做的工作) ,他们中的一些第二,但不是第一个,其中一些两类。

我做了错误的财产以后在设计我的课?我怎么出来的呢? 最明显的方法是使一类重复一些代码

abstract class Ai1ec_Can_Have_Children extends Ai1ec_Html_Element {
    /**
     *
     * @var array
     */
    protected $renderables = array();
    /**
     * Adds a renderable child to the element
     * 
     * @param Ai1ec_Renderable $renderable
     */
    public function add_renderable_children( Ai1ec_Renderable $renderable ) {
        $this->renderables[] = $renderable;
    }
}

这会工作,但它是一个气味的东西是不正确的,因为我需要,如果我添加了一些Can_Have_Children复制代码。 我该怎么办?

PS没有的特质,我支持5.2

Answer 1:

看来这里有两个主要责任:渲染和生儿育女。 所以,我有两个独立的接口开始:

interface Renderable {
  public function render();
}

interface Container {
  public function addChild(Renderable $renderable);
}

然后有一个具体的实施Container (不是抽象的):

class BasicContainer implements Container, Renderable {
  /* similar to your Ai1ec_Can_Have_Children class */
}

然后,您可以定义HTML元素类,如下所示,使用组成,而不是继承添加容器功能:

abstract class HtmlElement implements Renderable {
  /* similar to your Ai1ec_Html_Element class */
}

abstract class ContainerHtmlElement extends HtmlElement implements Container {
  private $container = new BasicContainer();

  public function addChild(Renderable $renderable) {
    $this->container->addChild($renderable);
  }

  public function render() {
    parent::render();
    $this->container->render();
  }
}


Answer 2:

两个重要的设计模式的原则可以在这里找到:

  1. 程序的接口,而不是实现
  2. 有利于对继承对象组合物

如果你看一下在GoF的书原来的类图,你会看到组件接口有两种实现方式:叶和复合材料。 叶参与者只实现了操作(),并没有其他人。 例如,考虑以下因素:

    <?php
class Leaf implements IComponent
{
    private $sName;
    public function __construct($sNodeName)

    {
        $this->sName=$sNodeName;
    }

    /* None of this batch of methods are used by Leaf */
    /* However in order to correctly implement the interface */
    /* you need some kind of implementation */
    public function add(IComponent $comOn){}
    public function remove(IComponent $comGone){}
    public function getChild($someInt){}

    /* Some userful content is required for the operation */
    public function operation()
    {
        echo $this->sName . "<br />";
    }
}

?> 

因此,虽然在图案叶参与者仅实现操作()方法,它具有的其他接口方法虚设实现。 你可以找到更多的细节:

http://www.php5dp.com/the-composite-design-pattern-in-php-part-i-from-conceptual-to-practical/

http://www.php5dp.com/category/design-patterns/composite/

综合是少数,你会发现这样的“一翼”实现的一个。



文章来源: Composite pattern in PHP, how to design classes to work around the need to extend two classes