首页 > 解决方案 > Java 抽象:抽象类委托抽象与具体类使用通用抽象

问题描述

假设我正在实现一个像 Animal 这样的简单接口。从广义上讲,有两种方法可以做到这一点:

  1. 在抽象类中实现接口的方法,并为所需的任何实现特定逻辑创建抽象方法。
  2. 在具体类中实现接口方法,在访问受保护的抽象类中移动通用逻辑。

我想了解如果——

public interface Animal {
    void makeSound();
}

public abstract class BaseAnimal implements Animal {
    @Override
    public void makeSound() {
        //do something which is common for all implementaions
        doSomeImplementaionSpecificStuff();
    }

    public abstract void doSomeImplementaionSpecificStuff();
}

public class Dog extends BaseAnimal implements Animal {
    public void doSomeImplementationSpecificStuff(){
       //do something specific to a dog
    }
}
public abstract class BaseAnimal implements Animal {
    public void doCommonStuff() {
        //any common logic that can be shared between concrete  implementation goes here
    }
}

public class Dog extends BaseAnimal implements Animal {
    @Override
    public void makeSound() {
       doCommonStuff();
       //do something specific to a dog
    }
}

标签: javaoopdesign-patterns

解决方案


这两种方式并不总是可以互换的。
您的第一个示例为子类设置了一个约束,该约束需要实现作为该方法一部分的特定makeSound()方法。
使用这种方式将子类的实现强耦合到父类之一。
此外,子类可能仍然是子类makeSound(),因为它不是final
所以我只会在非常具体的场景中使用这种方式:

  • 定义一个子类必须定义的工厂方法,因为父类依赖于它(抽象工厂)
  • 定义通用算法并让子类定义该算法的某些特定部分(模板方法)。

在一般情况下,您想使用第二个示例的代码,但也可以这样BaseAnimalAnimal

public abstract class BaseAnimal implements Animal {
    public void doCommonStuff() {
        //any common logic that can be shared between concrete  implementation goes here
    }
}

public class Dog extends BaseAnimal implements Animal {
    @Override
    public void makeSound() {
       doCommonStuff();
       //do something specific to a dog
    }
}

请注意,在 Java 8 中,默认接口依赖于您定义仅定义通用方法的抽象类:

public interface Animal {
    void makeSound();
    default void doCommonStuff() {
            //any common logic that can be shared between concrete  implementation goes here    
}

另请注意,doCommonStuff()在抽象类的 API 中公开不一定很好。客户端应该可以调用它吗?如果这是一个实现细节,您可以将其提取到支持类 ( ) 中,并通过将 an 组合到子类中AnimalDelegate来支持组合而不是继承。 AnimalDelegateAnimal


推荐阅读