如何避免重复的 if 语句

Log*_*gan 5 java design-patterns

我有多个服务使用一种方法实现接口 - execute(). 每个服务都使用此方法根据字符串值执行一些操作,在原始代码中,该值是枚举,因此这些值是常量。

interface Service{
   public void execute();
}

class Service1 implements Service{
   //constructors
   public void execute(JSONObject payload, String payloadType){
      if(payloadType.equals("type1")){
       doSomething(payload);
      }
   }
}

class Service2 implements Service{
   //constructors
   public void execute(JSONObject payload, String payloadType){
      if(payloadType.equals("type1")){
       doSomething1(payload);
      }
      if(payloadType.equals("type2")){
       doSomething2(payload);
      }
   }
}
Run Code Online (Sandbox Code Playgroud)

我想避免每次创建新服务时都编写相同的 if 语句。问题是,每个服务不必根据每个字符串类型执行操作。所以Service1在type等于"type1"时执行action,而Service2根据"type1"和"type2"执行action。

我尝试了以下解决方案:

class Main {
  public static void main(String[] args) {
    exec(new B(), "type2");
  }

  private static void exec(Service service, JSONObject payload, String payloadType){
      if(payloadType.equals("type1")){
       Init i = (Init)service;
       i.init(payload);
      }
      if(payloadType.equals("type2")){
       Action a = (Action)service;
       a.action(payload);
      }
  }
}

interface Service{

}

interface Init{
  public void init(JSONObject payload);
}

interface Action{
  public void action(JSONObject payload);
}

class A implements Service, Init{
  @Override
  public void init(JSONObject payload){
    doSomething(payload);
  }
}

class B implements Service, Init, Action{

  @Override
  public void init(JSONObject payload){
    doSomething1(payload);
  }

 @Override
   public void action(JSONObject payload){
    doSomething2(payload);
  }
}
Run Code Online (Sandbox Code Playgroud)

上面的代码有效,但我不喜欢使用强制转换。我认为这不是一个好习惯,也很不安全。你能建议我在这里使用什么设计模式或其他解决方案吗?我试过访问者,但我无法弄清楚这个案例的正确实现。

更新

感谢所有的答案,他们非常有帮助。我设法实现了我想要的。这是最终有效的代码。

public class Main {

    public static B b = new B();
    public static A a = new A();

    public static void main(String[] args) {
        exec(b, "init");
    }

    private static void exec(Service service, String type){
        if(type.equals("init") && service instanceof Init){
            service.fillCarrier(new InitCarrier());
        }
        if(type.equals("action") && service instanceof Action){
            service.fillCarrier(new ActionCarrier());
        }
    }
}

interface Carrier<T>{
    public void set(T t);
}

class InitCarrier implements Carrier<Init>{
    public void set(Init init){
        init.init();
    }
}

class ActionCarrier implements Carrier<Action>{
    public void set(Action action){
        action.action();
    }
}

abstract class Service{
    public void fillCarrier(Carrier carrier){
        carrier.set(this);
    }
}

interface Init{
    public void init();
}

interface Action {
    public void action();
}

class A extends Service implements Init{
    
    @Override
    public void init(){
        System.out.println("init a");
    }
}

class B extends Service implements Init, Action{

    @Override
    public void init() {
        System.out.println("init b");
    }

    @Override
    public void action(){
        System.out.println("action");
    }
}

Run Code Online (Sandbox Code Playgroud)

Mor*_*S42 0

棘手的问题,我可能有一个可行的解决方案。

那将是存储类型,以及类型以 HashMap 形式执行的代码。

HashMap<String, Function<Void, Void>> types = new HashMap<String, Function<Void, Void>>();
Run Code Online (Sandbox Code Playgroud)

然后在主函数中,您将使用类型名称及其运行的函数填充 HashMap。

types.put("Type1",()->{
    /*Do something*/
});
types.put("Type2",()->{
    /*Do something*/
});
types.put("Type3",()->{
    /*Do something*/
});
Run Code Online (Sandbox Code Playgroud)

然后在服务中,您将有一个字符串数组来表示它使用的类型。例如:

String[] serviceTypes = {"Type1", "Type2"};
Run Code Online (Sandbox Code Playgroud)

最后,在服务的执行函数中,您将对字符串运行相应的 lambda。

public void execute(String type){
    if((new ArrayList<>(Arrays.asList(serviceTypes))).contains(type)) {
        Main.types.get(type);
    }
}
Run Code Online (Sandbox Code Playgroud)