在我的应用程序中,我有许多不同的元素。我创建了一个扩展的抽象类。
abstract class Element {
protected $_value = null;
public function __construct($value) {
$this->_value = $value;
}
// ...
public abstract function render();
}
元素的示例可能是包含在段落标记中的某些文本。
class TextElement extends Element {
public function render() {
return "<p>{$this->_value}</p>\n";
}
}
我在创建具有多个值的元素时遇到问题。例如,图像元素可能会呈现图像标记并包含多个属性。这是一个问题,因为抽象类中的构造函数只接受一个参数。我看到了这个问题的两种可能解决方案。我可以将包含不同属性的数组传递给Element构造函数(解决方案1),或者我可以覆盖子类中的构造函数(解决方案2)。我的问题是,这些解决方案中哪一个是更好的设计还是存在更好的解决方案?我应该使用界面吗?
解决方案1
class ImageElement extends Element {
public function render() {
return "<img src=\"{$this->_value['src']}\" alt=\"{$this->_value['alt']}\" />";
}
}
$imageElement = new ImageElement(array('src' => '/image.png', 'alt' => 'image'));
解决方案2
class ImageElement extends Element {
protected $_alt;
public function __construct($src, $alt) {
$this->_value = $src;
$this->_alt = $alt;
}
// ...
public function render() {
return "<img src=\"{$this->_value}\" alt=\"{$this->_alt}\" />";
}
}
答案 0 :(得分:1)
使用第一个解决方案,如果有人在哪里查看您的代码,他们需要检查渲染函数以找出可用的参数。
使用第二个解决方案,如果您的IDE支持自动完成,或者您从源代码生成文档,您将获得一个参数列表,您可以更快地完成一天。
$ value并没有真正告诉我它用于什么以及如果遇到没有任何参数的元素怎么办?即BR元素或其他东西。
我认为解决方案2更“正确”,但只有“渲染”功能的界面才是最佳解决方案。
答案 1 :(得分:1)
两种解决方案都是合理的,但在您的情况下,我会选择您的第一个解决方案。您在这里处理HTML元素,这可能意味着您将支持大量属性,其中许多属性是可选的。这看起来没问题:
class ImageElement extends Element {
public function __construct($src, alt) {...}
}
$img = new ImageElement('/img/src.png', 'alt text');
这不太好
class ImageElement extends Element {
public function __construct($src, $alt, $id = null, $class = null, $width = null, $height = null, $style = null, $title = null) {...}
}
$img = new ImageElement('/img/src.png', 'alt text', null, 'img-class', null, null, null, 'Image title');
每当需要传递多个参数时,其中许多参数都是可选的,最好将对象或数组传递给构造函数。这看起来更好:
$img = new ImageElement(array(
'src' => '/img/src.png',
'alt' => 'alt text',
'class' => 'img-class',
'title' => 'Image title',
));
答案 2 :(得分:0)
重载!不幸的是,PHP没有做过载,所以假装:
public function __construct($VAL){
if(is_array($VAL)){
foreach($VAL as $k=>$v){
$this->$k=$v;
}
}else{
$this->_value=$VAL;
}
}