在PHP中添加抽象子类而不修改所有继承子类

时间:2017-01-24 23:23:42

标签: php inheritance design-patterns

我有类似的类层次结构

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中使用具有最少编辑的特征可能是最不好的解决方案,因此代码在某种程度上是分开的,如果新功能被删除,则可以通过最小的更改来完成。

您怎么看?

由于

1 个答案:

答案 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对象。如果你讨厌这个,你可能需要考虑工厂模式。