我有一个问题,我已经工作了很长一段时间。我正在构建一个包含两个主要类Template.php
和Tag.php
的模板引擎,以及一些扩展类,如Img.php
和String.php
。
该计划的工作方式如下:
Template对象创建Tag对象。每个标记对象确定要实现的扩展类(img,string等)。
标记类的目的是为每个扩展类提供帮助函数,例如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();
我需要的一件事是创建自定义标签的通用界面,即我可以实例化Img(...)然后实例化String(...),我需要使用Tag实例化每个扩展。
编辑:另外只是为了澄清:Tag类具有所有扩展类共有的功能,Tag类中不应该有任何需要在扩展类中实现的方法。 Tag类仅提供辅助函数。
我知道这个问题有点模糊,我希望你们中的一些人过去曾经处理过这个问题,并且可以预见选择每种设计模式时会遇到一些问题。如果您有任何其他建议,我很乐意听到。
谢谢! 马特穆勒
答案 0 :(得分:2)
继承比在单个Tag
类中封装不同标记的所有功能更有意义。关注点分离很重要,因此最好采用基于继承的方法。否则,你最终会在一个类中拥有一堆不同的特定于标签的逻辑,这很糟糕。这是一场维护噩梦!
如果您有Img
特定的逻辑,请将其放在自己的类中。您可以将所有常用方法放在Tag
类中。如果这是Java,我会将Tag
作为抽象类甚至是接口,并使不同的实现(Img
,Div
等)扩展(在摘要的情况下) class)或实现(在接口的情况下)。
更好的方法是拥有一个Tag
接口,然后是一个实现所有通用逻辑的AbstractTag
抽象类。然后,您的特定代码可以实现Tag
界面并扩展AbstractTag
。但是,我不知道这在PHP中是否完全可行,但你可以尝试做类似的事情。
答案 1 :(得分:1)
new Tag('img')
和Tag::create('img')
都不能令我信服。我认为,决定使用哪个标签是在错误的地方 - 在Tag类中 - 虽然它明显属于模板。标签及其后代应该无法控制它们的使用方式。
我建议如下:创建标签的层次结构
abstract class Tag { ...common methods.... }
class ImgTag extends Tag { ...image specific methods... }
class SpanTag extends Tag { ...image specific methods... }
并且在模板中只需在需要时使用新的WhateverTag
class Template...
function insertImage
$tag = new ImgTag($atts);
$tag->render();
如果标签是在多个地方创建的,那么最好有一个工厂方法,但它仍然属于模板
class Template...
function createImage
return new ImgTag($atts);
function insertOneImage
$tag = $this->createImage
$tag->render();
function insertAnotherImage
$tag = $this->createImage
$tag->render();
作为一般建议,不惜任何代价避免使用静态方法。静态只是全局函数的花哨别名,没有任何面向对象的。