是不是坏模式:确定接口实现的class
Is it a bad pattern: determine class of interface implementation
我有接口
interface Car {
enum Type { MITSUBISHI, FORD }
Car.Type getType();
还有两个 类 实现接口
class Mitsubishi implements Car {
@Override
Car.Type getType() { return Car.Type.MITSUBISHI; }
}
class Ford implements Car {
@Override
Car.Type getType() { return Car.Type.FORD; }
}
并像
一样使用它
List<Car> cars = this.cars;
List<Mitsubishi> mitsubishiCars = cars.stream().filter(c -> c.getType().equals(Car.Type.MITSUBISHI)).collect(Collectors.toList());
问题,这是不是一个坏模式?如果是,那为什么?
一般来说,这似乎是一个糟糕的模式,因为接口 Car
不应该知道谁实现了它,而包含这个 enum Type
会自动获取其潜在实现的知识。
这就是说,这完全取决于您如何使用Car.Type
。
您很可能希望使用枚举值来确定要执行的指定操作。例如:
//park the car depending on the type
switch (type) {
case MITSUBISHI:
//park in a certain way
case FORD:
//park in some other way
//...
}
如果是这样的话,除了知道其实现的接口之外,我至少看到了 2 个其他问题:
- 每次您有一个新的
Car
实现时,您都需要丰富接口 Car
中的枚举 Type
。这可能很烦人
- 当
Type
的值变多时,无论什么流结构(switch
、if
块等)都将变得庞大且难以维护。
如果是这样的话,我宁愿在界面中创建根据汽车类型处理动作的方法。例如:
interface Car {
void park();
}
class Mitsubishi implements Car {
@Override
public void park() {
//way to park a Mitsubishi
}
}
如果你只是想使用枚举值在某个时候打印汽车的类型(比如在日志中),那么只需在接口中添加一个 String getType()
方法,return 正确的品牌:
interface Car {
String getType();
}
class Mitsubishi implements Car {
@Override
public String getType() {
return "Mitsubishi";
}
}
但总的来说,我不会建议这种方法,除非您没有想到 Car.Type
的用途,但您没有分享(尽管我真的不知道您还可以如何使用除了我上面列出的 2 种情况外,我想使用枚举。
Post-编辑
看到您想如何使用枚举后:
List<Car> cars = this.cars;
List<Mitsubishi> mitsubishiCars = cars.stream()
.filter(c -> c.getType().equals(Car.Type.MITSUBISHI))
.collect(Collectors.toList());
我认为你可以在接口外定义枚举,然后在接口中创建一个 Type getType()
方法,然后像这样使用它:
cars.stream()
.filter(c -> c.getType() == Type.MITSUBISHI)
.collect(Collectors.toList());
(当然假设 Mitsubishi
实施将 return Type.MITSUBISHI
Type getType()
)。
我有接口
interface Car {
enum Type { MITSUBISHI, FORD }
Car.Type getType();
还有两个 类 实现接口
class Mitsubishi implements Car {
@Override
Car.Type getType() { return Car.Type.MITSUBISHI; }
}
class Ford implements Car {
@Override
Car.Type getType() { return Car.Type.FORD; }
}
并像
一样使用它List<Car> cars = this.cars;
List<Mitsubishi> mitsubishiCars = cars.stream().filter(c -> c.getType().equals(Car.Type.MITSUBISHI)).collect(Collectors.toList());
问题,这是不是一个坏模式?如果是,那为什么?
一般来说,这似乎是一个糟糕的模式,因为接口 Car
不应该知道谁实现了它,而包含这个 enum Type
会自动获取其潜在实现的知识。
这就是说,这完全取决于您如何使用Car.Type
。
您很可能希望使用枚举值来确定要执行的指定操作。例如:
//park the car depending on the type
switch (type) {
case MITSUBISHI:
//park in a certain way
case FORD:
//park in some other way
//...
}
如果是这样的话,除了知道其实现的接口之外,我至少看到了 2 个其他问题:
- 每次您有一个新的
Car
实现时,您都需要丰富接口Car
中的枚举Type
。这可能很烦人 - 当
Type
的值变多时,无论什么流结构(switch
、if
块等)都将变得庞大且难以维护。
如果是这样的话,我宁愿在界面中创建根据汽车类型处理动作的方法。例如:
interface Car {
void park();
}
class Mitsubishi implements Car {
@Override
public void park() {
//way to park a Mitsubishi
}
}
如果你只是想使用枚举值在某个时候打印汽车的类型(比如在日志中),那么只需在接口中添加一个 String getType()
方法,return 正确的品牌:
interface Car {
String getType();
}
class Mitsubishi implements Car {
@Override
public String getType() {
return "Mitsubishi";
}
}
但总的来说,我不会建议这种方法,除非您没有想到 Car.Type
的用途,但您没有分享(尽管我真的不知道您还可以如何使用除了我上面列出的 2 种情况外,我想使用枚举。
Post-编辑
看到您想如何使用枚举后:
List<Car> cars = this.cars;
List<Mitsubishi> mitsubishiCars = cars.stream()
.filter(c -> c.getType().equals(Car.Type.MITSUBISHI))
.collect(Collectors.toList());
我认为你可以在接口外定义枚举,然后在接口中创建一个 Type getType()
方法,然后像这样使用它:
cars.stream()
.filter(c -> c.getType() == Type.MITSUBISHI)
.collect(Collectors.toList());
(当然假设 Mitsubishi
实施将 return Type.MITSUBISHI
Type getType()
)。