【发布时间】:2016-03-12 02:19:45
【问题描述】:
我有一些处理程序(“控制器”)类,它们可以以某种方式处理项目:
interface IHandler
{
public function execute(Item $item);
}
class FirstHandler implements IHandler
{
public function execute(Item $item) { echo $item->getTitle(); }
}
class SecondHandler implements IHandler
{
public function execute(Item $item) { echo $item->getId() . $item->getTitle(); }
}
class Item
{
public function getId() { return rand(); }
public function getTitle() { return 'title at ' . time(); }
}
但是我需要在子 Item 类中添加一些新功能:
class NewItem extends Item
{
public function getAuthor() { return 'author ' . rand(); }
}
并在 SecondHandler 中使用它
class SecondHandler implements IHandler
{
public function execute(Item $item) { printf('%d %s, author %s', $item->getId(), $item->getTitle(), $item->getAuthor()); }
}
但是Item 类实际上没有getAuthor 方法。而且,如果我尝试在SecondHandler 类中更改接受方法的签名,我将捕获E_STRICT 关于声明兼容性的错误。当然,这有点违反 LSP。
我该如何解决这个问题?我是否需要两个接口,例如INewHandler 和IHandler,具有不同的execute 方法签名?但这是某种代码重复。
另外,我不能在处理程序中使用__constructor(Item $item) 和__construct(NewItem $item)(以及不带参数的execute 方法),这将被视为更好的解决方案:它们必须是不可变的,并且应用程序中允许的每个策略只有一个实例生命周期。
【问题讨论】:
-
我相信在示例中使用较少通用的名称将有助于我们更好地识别和解决问题。
-
有什么想法吗?你有“处理程序”类和简单的“DTO”类(Doctrine 实体、Yii ActiveRecord 等)
-
如果Strategy is not a reference 到design pattern,请不要在我们面前放红鲱鱼。这看起来很像策略。
-
这些项目之间的关系究竟如何?继承真的有必要吗?为什么不作曲?如果给出更具描述性的名称(暗示更具体的场景),我们可以做出更好的判断。
-
已编辑。项目实际上是相关的,因为我使用 Doctrine 的类表继承,并且它们具有共享方法(getId、getTitle 等)
标签: php oop inheritance architecture liskov-substitution-principle