我有类似的类层次结构
interface ISomething
{
public function foo();
...
}
abstract class TopAbstract implements ISomething
{
...
}
abstract class HighAbstract extends TopAbstract
{
public function foo()
{
...
}
}
and 46(!) classes that inherit from HighAbstract
class One extends HighAbstract
{
}
...
class FortySix extends HighAbstract
{
}
现在我必须添加functionnality,并且需要备用HighAbstract :: foo()(以及其他内容)。 实现这一目标的最佳方式是什么?
我可以修改HighAbstract,但我想将新功能分开(关注点分离)
我可以在HighAbstract中添加一个子类,但是我必须编辑46个子类来更改它们的父类。
我可以为HighAbstract添加一个特性,但仍然意味着修改它(HighAbstract)并使用分支并使用HighAbstract中的特征:: foo()
还有其他想法吗?
我认为在HighAbstract中使用具有最少编辑的特征可能是最不好的解决方案,因此代码在某种程度上是分开的,如果新功能被删除,则可以通过最小的更改来完成。
您怎么看?
由于
答案 0 :(得分:0)
你的问题恰恰反映了继承的陷阱,这是最强耦合的关系。您看,当您的46个子类继承HighAbstract
类时,他们将使用在foo
方法中实现的{strong>固定和具体实现HighAbstract
课程。无法在运行时更改此选项,您唯一的选择是修改源代码:更改46个子类以继承另一个父级,或更改当前父级的源代码。
关于解决方案,我建议两个可能的解决方案:
1)如果您使用的是良好的IDE,那么您可以使用重构功能,因此您无需手动更改46个子类的父级。
2)如果您预计将来可能会发生这种变化,那么您必须接受修改46个子类的源代码,但只需要一次性,更喜欢聚合而不是继承,比如这样:
class FlexibleAbstract extends TopAbstract {
private $origin;
public function __construct($origin) {
$this->origin = $origin;
}
public function foo() {
$this->origin->foo();
}
}
class One extends FlexibleAbstract {
...
}
function somewhere() {
$oneA = new One(new HighAbstract());
$oneB = new One(new AlternativeHighAbstract());
$oneC = new One(new AnotherAlternativeHighAbstract());
}
当然,这个解决方案有点烦恼:每次创建One
对象时,都必须创建一个TopAbstract
对象。如果你讨厌这个,你可能需要考虑工厂模式。