如何重写此代码以避免切换/强制转换



给你一个简单的例子,希望它是清楚的。
我已经为Service类添加了继承,以避免现在出现的切换

class Config {}
class ConfigA extends Config {}
class ConfigB extends Config {}
// service class - different implementation for configA and ConfigB
// normally it would look like
class ServiceA {
public String run(ConfigA configA) {}
}

所以接下来我需要像

这样的东西
class ServiceRunner {
public String run(Config config) {
// if or switch doesn't matter now
if (config  instanceof ConfigA) {
return serviceA.run((ConfigA)config);
}
}
}
// main
Config config =  configFactory.create(...) // returns ConfigA or ConfigB
String result = serviceRunner.run(config);

有没有更好的方法来编码它,我的意思是没有强制转换?我能想到的唯一解决办法是:

interface Service { String run(); }
@RequestScope
class ServiceA implements Service {
private ConfigA  config;
public ServiceA(ConfigA configA) {this.configA = configA}
public String run() {
...
}
}

,但我不相信这是一个好主意实现服务bean作为状态bean,我使用CDI(实际上quarkus)的DI,它似乎不支持辅助注入通过构造函数

为什么不在服务本身中隐藏关于给定服务处理哪些配置的细节呢?通过这样做,您可以得到如下内容:

interface Service { 
boolean handlesConfig(Config config)
String run(Config config); 
}
class ServiceRunner {

private List<Service> services;
public String run(Config config) {
for (service : services) {
if (service.handles(config)) {
return service.run(config);
}
}
}
}

似乎这是桥模式的情况。你有平行的服务和配置层次结构。所以如果明天有一个ServiceC,那么就应该有一个ConfigC。可能存在一个在服务和配置中都很常见的抽象。试着找到它,并把它抽象出来。然后服务将使用该抽象。ConfigA, ConfigB将是该抽象的简化。

或者,正如上面提到的应答器,服务应该被编程为抽象配置而不是简单配置。

配置是否有不同类型的接口,不能提取成一个公共接口?在这种情况下,它违反了Liskov替换原则,该原则要求所有子类都应该是可互换的。例如,Shape <- Rectangle <- Square的层次结构是错误的,因为Square不是矩形的一种类型(当然是程序化的)——因为Rectangle有2个维度,即长度和宽度,而Square只有一个维度的长度。建立这种层次结构会破坏抽象。类似地,Config的层次结构可能根本不是层次结构。

最新更新