我正在使用复合模式来拥有可重用的元素来构建页面。为此,我有一个简单的界面来驱动模式
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'";
}
}
The problem is that all the objects of the composite must implement the interface, some of them must extend only the first class ( can_have_children ) but not the second ( this is because they are higher level abstraction that configure another renderable object to do the job ), some of them the second but not the first and some of them both classes.
Have i done somthing wrong while designing my classes?How do i come out of it? The most obvious way is to make a class duplicating some code
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;
}
}
this would work, but it's a smell that something is not right, as i would need to duplicate code if i add something to Can_Have_Children. What should i do?
P.S. No traits, i support 5.2