Java:具体空实例方法的继承

时间:2018-03-15 16:57:14

标签: java oop

该问题被视为一般的面向对象设计问题,目前与任何具体案例无关。

我们说我有一个有抽象类的测试库:

public abstract class AbstractTest<E extends Event> {

    private ProcessingService service = new ProcessingService();

    protected static abstract void buildTestData();

    public void testSomething(Event event) {
        beforeScenario(event);

        service.process(event);

        // ... asserts and other actions

        afterScenario(event);
    }

    protected void beforeScenario(E event) {
        // override if needed
    }

    protected void afterScenario(E event) {
        // override if needed
    }
}

AbstractTest派生的每个类都被迫提供buildTestData()实现,并且可以选择提供自己的beforeScenarioafterScenario

从我的观点来看,拥有这些空洞的方法有其自身的优点和缺点。对于@Override可选方法而不是抽象方法,您不能创建派生类。如果派生类重写它们并使用抽象类中的testSomething,您还要确保调用场景的正确顺序:

public class SpecificTest extends AbstractTest<SomeEvent> {

    protected static void buildTestData() {
        // build test data
    }

    // override only scenarious and do not touch testSomething()
    protected void beforeScenario(E event) {
        // construct
    }

    protected void afterScenario(E event) {
        // destroy
    }
}

另一方面,这些空的具体方法在父类中看起来很奇怪。派生类可以@Override testSomething像:

public class SpecificTest extends AbstractTest<SomeEvent> {

    protected static void buildTestData() {
        // build test data
    }

    // assuming that you don't have these methods in parent classes
    public void testSomething(Event event) {
        beforeScenario(event);

        super.testSomething(event);

        afterScenario(event);
    }


    private void beforeScenario(E event) {
        // construct
    }

    private void afterScenario(E event) {
        // destroy
    }
}

从OOD的角度来看哪种方法更合适?

将这些空方法保留在父类中是否有意义?

1 个答案:

答案 0 :(得分:1)

你的方法没有错。您的代码结构类似于Template Pattern

模板模式实现看起来像(取自Head First Design Patterns)

abstract class AbstractClass {
    final void templateMethod() {
       primitiveOperation1();
       primitiveOperation2();
       concreteOperation();
       hook();
    }
    abstract void primitiveOperation1();
    abstract void primitiveOperation2();

    final void concreteOperation() {
      //implementation 
    }
    void hook() { }
}

primitiveOperations是抽象的,必须被子类覆盖,而concreteOperation标记为final,不能被覆盖。 我们还有一个名为hook的具体方法,默认情况下不执行任何操作。子类可以选择覆盖它或决定不覆盖它。这些方法称为钩子。

因此,在将您的代码与此

进行比较时
  • buildTestDataprimitiveOperation
  • testSomethingconcreteOperation
  • beforeScenarioafterScenariohooks