从父类调用子类方法不是最佳实践?

4
我正在处理一个项目,其中有一个抽象类(BaseConverter),其中有一个抽象方法(convert())和一些具体方法。其中一个重要的具体方法是invokeConverter(),它基本上会调用子类中实现的convert()方法。
在我们的代码被其他人审核时,他告诉我们,不应该从超类调用子类方法,并且他说这不是最佳实践。以下是我们的类结构。请问是否这种做法不正确?
@Named
public abstract class BaseConverter{ 

     @Inject
     private ConversionDriver conversionDriver;//this class is responsible to return the correct subclass object based on the type

     protected abstract String convert(Object toConvert); 

     public String invokeConverter(ConverterType type, Object toConvert){
       conversionDriver.getConverter(type).convert(toConvert);//getConverter() return the subclass object based on the type
     } 
    ....
    ....
}

2
你没有调用子类方法,而是调用了超类的重写方法。这也是首先拥有抽象方法的原因之一。我不知道这会是什么不好的做法。 - Codebender
@Codebender,谢谢..是的,我已经用同样的答案进行了合理化解释,但那个人并不相信,并要求我们改变结构。 - whoami
1
问那个人……让他解释,因为他很了解你的代码。 - Garry
2
我认为问题可能在于invokeConverter似乎执行的是静态方法而不是实例方法,因为它检索一些对象来执行转换。这基本上意味着必须创建一个子类实例,然后根据类型创建另一个实例。模板方法应该直接使用当前实例,假设它是“正确的实例”,而静态方法应该选择正确的子类。 - RealSkeptic
1
@RealSkeptic,这是我在阅读模板模式后所做的确切更改。我将private ConversionDriver conversionDriver;移动到调用类中,这样convert()将被正确实例调用。非常感谢。 - whoami
显示剩余3条评论
1个回答

4
这实际上是GoF提出的一个名为“模板方法”的设计模式。但你不应该过度使用它,因为它偏向于继承而不是组合。
引用块中描述了在操作中定义算法的骨架,并将一些步骤推迟到子类中。模板方法使得子类可以在不改变算法结构的情况下重新定义算法的某些步骤。
你会发现这种模式在许多已知的框架和插件中都有实现。但在某些情况下,你应该考虑不同的模式,比如策略或装饰者模式。
例如,策略模式使用委托来变化整个算法,而模板方法使用被诟病的继承来变化算法的特定部分。策略还会在运行时修改单个对象的逻辑,而模板方法通过子类化在编译时修改整个类的逻辑。
关于“最佳实践” - 这是一个有争议的术语。当代码库增长并需要重构以获得更好的复杂性时,我认为应该用更好的设计模式替换模板方法。
但有时它是满足你需求的最佳解决方案。例如,你可能有一个doExecute()方法,并希望其他程序员扩展你的类(而不修改它),因此你让他们挂接到你的代码提供beforeExecute()方法的部分。成熟的系统可能会包括各种对象的事件分发器功能。

2
这有一定的道理;但在 OP 的例子中,他们实际上正在执行一些不同的操作 - 他们正在对一个单独的实例调用模板方法。这并不是真正的“模板方法”设计模式,有点令人困惑。我必须同意评论者的观点。 - Dawood ibn Kareem
1
同意@DavidWallace,我将私有的ConversionDriver conversionDriver;移到调用类中,以便对当前实例调用convert()。非常感谢。 - whoami
2
好观点@DavidWallace。我大多数时候都与这个问题的标题相关。Praki,你的重构很棒,会正确地实现这个模式。 - TechWisdom
2
@DavidArno:“许多GoF模式,例如Singleton、Service Locator和Template,现在都被广泛认为是反模式。” 顺便说一下,Service Locator不是GoF设计模式。 - Géry Ogam
1
@Maggyero,哦,你说得对。我没意识到它的起源是J2EE,而不是C++缺失的功能解决方法。感谢你纠正我。 - David Arno
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接