标记接口与枚举
Marker Interface vs Enums
我正在尝试为动物园建模。
假设我对动物园中的区域有以下结构(省略了一些细节)
public abstract class AnimalHabitat{
private ArrayList<Animal> animals = new ArrayList<>();
public void setAnimal(Animal animal) {
animals.add(animal)
}
}
public class Enclosure extends AnimalHabitat{}
public class Aquarium extends AnimalHabitat{}
public class Cage extends AnimalHabitat{}
那么我有下面的动物结构
public abstract class Animal{}
public class Lion extends Animal{}
public class Zebra extends Animal{}
public class Shark extends Animal{}
public class Starfish extends Animal{}
public class Parrot extends Animal{}
public class Eagle extends Animal{}
我想将一种动物添加到其相应的适当栖息地。为了简化代码,我正在考虑使用标记界面,例如
public interface TerrestrialAnimal{}
public class Lion extends Animal implements TerrestrialAnimal{}
public class Zebra extends Animal implements TerrestrialAnimal{}
然后我就能做到
public class Zoo{
public boolean addAnimal(AnimalHabitat habitat, Animal animal) {
if (animal instanceOf TerrestrialAnimal && habitat instanceOf Enclosure) {
habitat.set(animal);
return true;
}
if (animal instanceOf AquaticAnimal && habitat instance of Aquarium) {
habitat.set(animal);
return true;
}
// So for aerial
}
}
但是另一种方法是使用枚举。例如假设我有
public enum AnimalType{
Terrestrial, Aquatic, Aerial;
//getter
}
然后在Animal摘要中class我可以定义
public abstract class Animal{
private AnimalType type;
// Initialise in the constructor depending on the animal instance
}
我将在 Zoo 的 addAnimal() 方法中执行相同的操作。
每种方法的优缺点是什么?谢谢!
我会使用枚举。您不需要所有这些 if 语句。
只要在Animal
和AnimalHabitat
中都有属性type
,然后比较它们。
if (animal.getType() == habital.getType()) { // can add to habitat
如果要向特定于动物类型的接口添加一些方法,请切换到接口。
枚举
优点:
- 易于扩展:您可以轻松增加价值
- 更准确:您有一个文件来定义所有 AnimalType
- 更具可读性:绝对可读
- 更灵活:您可以在枚举上定义方法,您可以使用枚举值打印 AnimalType
- Comparable:你可以做简单的比较而不是使用 instanceof
使用枚举方法我没有发现任何缺点。
界面
优点
- 方法:可以定义常用方法签名
- 同一个Animal可以使用2个接口(一个动物可以有更多的栖息地?还是更多的种类?)
- 您可以在 collections/class 变量中使用接口作为超类型
缺点
- 贵:肯定贵,一种接口一个
在您的示例中,我更喜欢枚举,因为您使用接口来定义动物类型,并且可以使用枚举轻松完成。如果您需要定义通用方法签名或希望将接口用作超类型,请使用接口,如下所示:
List<TerrestrialAnimal> terrestrialAnimal = new ArrayList<>();
它可以包含所有陆生动物。
我正在尝试为动物园建模。
假设我对动物园中的区域有以下结构(省略了一些细节)
public abstract class AnimalHabitat{
private ArrayList<Animal> animals = new ArrayList<>();
public void setAnimal(Animal animal) {
animals.add(animal)
}
}
public class Enclosure extends AnimalHabitat{}
public class Aquarium extends AnimalHabitat{}
public class Cage extends AnimalHabitat{}
那么我有下面的动物结构
public abstract class Animal{}
public class Lion extends Animal{}
public class Zebra extends Animal{}
public class Shark extends Animal{}
public class Starfish extends Animal{}
public class Parrot extends Animal{}
public class Eagle extends Animal{}
我想将一种动物添加到其相应的适当栖息地。为了简化代码,我正在考虑使用标记界面,例如
public interface TerrestrialAnimal{}
public class Lion extends Animal implements TerrestrialAnimal{}
public class Zebra extends Animal implements TerrestrialAnimal{}
然后我就能做到
public class Zoo{
public boolean addAnimal(AnimalHabitat habitat, Animal animal) {
if (animal instanceOf TerrestrialAnimal && habitat instanceOf Enclosure) {
habitat.set(animal);
return true;
}
if (animal instanceOf AquaticAnimal && habitat instance of Aquarium) {
habitat.set(animal);
return true;
}
// So for aerial
}
}
但是另一种方法是使用枚举。例如假设我有
public enum AnimalType{
Terrestrial, Aquatic, Aerial;
//getter
}
然后在Animal摘要中class我可以定义
public abstract class Animal{
private AnimalType type;
// Initialise in the constructor depending on the animal instance
}
我将在 Zoo 的 addAnimal() 方法中执行相同的操作。
每种方法的优缺点是什么?谢谢!
我会使用枚举。您不需要所有这些 if 语句。
只要在Animal
和AnimalHabitat
中都有属性type
,然后比较它们。
if (animal.getType() == habital.getType()) { // can add to habitat
如果要向特定于动物类型的接口添加一些方法,请切换到接口。
枚举
优点:
- 易于扩展:您可以轻松增加价值
- 更准确:您有一个文件来定义所有 AnimalType
- 更具可读性:绝对可读
- 更灵活:您可以在枚举上定义方法,您可以使用枚举值打印 AnimalType
- Comparable:你可以做简单的比较而不是使用 instanceof
使用枚举方法我没有发现任何缺点。
界面
优点
- 方法:可以定义常用方法签名
- 同一个Animal可以使用2个接口(一个动物可以有更多的栖息地?还是更多的种类?)
- 您可以在 collections/class 变量中使用接口作为超类型
缺点
- 贵:肯定贵,一种接口一个
在您的示例中,我更喜欢枚举,因为您使用接口来定义动物类型,并且可以使用枚举轻松完成。如果您需要定义通用方法签名或希望将接口用作超类型,请使用接口,如下所示:
List<TerrestrialAnimal> terrestrialAnimal = new ArrayList<>();
它可以包含所有陆生动物。