我有一个问题困扰了我很长时间。我正在构建一个包含两个主要类的模板引擎 Template.php
和Tag.php
,有一堆扩展类,如 Img.php
和String.php
.
程序的工作原理如下:
Template 对象创建 Tag 对象。每个标签对象决定要实现哪个扩展类(img、string等)。
Tag 类的要点是为每个扩展类提供辅助函数,例如 wrap('div'),
addClass('slideshow')
等
每个Img 或 String 类都用于渲染特定于所需内容的代码,因此 $Img->render()
会给出类似 <img src='blah.jpg' />
的内容
我的问题是:
我应该像这样封装 Tag 对象中的所有扩展功能吗:
Tag.php
function __construct($namespace, $args) {
// Sort out namespace to determine which extension to call
$this->extension = new $namespace($this); // Pass in Tag object so it can be used within extension
return $this; // Tag object
}
function render() {
return $this->extension->render();
}
Img.php
function __construct(Tag $T) {
$args = $T->getArgs();
$T->addClass('img');
}
function render() {
return '<img src="blah.jpg" />';
}
用法:
$T = new Tag("img", array(...);
$T->render();
...或者我应该创建更多的继承结构,因为“Img是一个标签”
Tag.php
public static create($namespace, $args) {
// Sort out namespace to determine which extension to call
return new $namespace($args);
}
Img.php
class Img extends Tag {
function __construct($args) {
// Determine namespace then call create tag
$T = parent::__construct($namespace, $args);
}
function render() {
return '<img src="blah.jpg" />';
}
}
用法:
$Img = Tag::create('img', array(...));
$Img->render();
我确实需要一个用于创建自定义标签的通用接口(interface),即我可以实例化 Img(...) 然后实例化 String(...),我确实需要使用 Tag 实例化每个扩展。
编辑:另外只是为了澄清:Tag 类具有所有扩展类共有的功能,Tag 类中不应该有任何需要在扩展类中实现的方法。标签类仅提供辅助函数。
我知道这个问题有点模糊,我希望你们中的一些人过去处理过这个问题,并且能够预见到选择每种设计模式时的某些问题。如果您有任何其他建议,我很乐意听到。
谢谢! 马特·穆勒
最佳答案
继承比将不同标签的所有功能封装在单个 Tag
类中更有意义。关注点分离很重要,因此最好在这里采用基于继承的方法。否则,您最终会在一个类中拥有一堆不同的特定于标签的逻辑,这很糟糕。这是维护的噩梦!
如果您有特定于 Img
的逻辑,请将其放在自己的类中。您可以将所有常用方法放在 Tag
类中。如果这是 Java,我会将 Tag
设为抽象类甚至接口(interface),并具有不同的实现(Img
、Div
等)。 ) 扩展(对于抽象类)或实现(对于接口(interface))。
更好的方法是拥有一个 Tag
接口(interface),然后是一个实现所有通用逻辑的 AbstractTag
抽象类。然后您的特定标签可以实现 Tag
接口(interface)并扩展 AbstractTag
。不过,我不知道这在 PHP 中是否完全可能,但你可以尝试做类似的事情。
关于php - 设计模式问题: encapsulation or inheritance,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2786041/