Android - 动态方法调用 (java)

Android - Dynamic method call (java)

我有这个 class,它包含四个私有方法,每个都有相同的两个参数,还有一个 public 方法可以在它们之间进行选择。 可能的方法存储在 Map 中,并且可以添加更多。 我想动态调用正确的方法,删除 switch..case。 有没有一种礼貌的方式来做到这一点,即没有 getMethod/invoke?

public class PlayerClass {

    private MediaSource customPlayFunction1(Channel chn, OtherParam other) {
        
    }
    
    private MediaSource customPlayFunction2(Channel chn, OtherParam other) {
        
    }
    
    private MediaSource customPlayFunction3(Channel chn, OtherParam other) {
        
    }
    
    private MediaSource defauPlayFunction(Channel chn, OtherParam other) {
        
    }
    
    
    public void playChannel(Activity activity, Channel chn) {

        //do something 

        switch (chn.customFunction) {
            case ("CustomPlayFunction1"): {
                videoSource = customPlayFunction1(chn,other);
                break;
            }
            case ("CustomPlayFunction2"): {
                videoSource = customPlayFunction2(chn,other);
                break;
            }
            case ("CustomPlayFunction3"): {
                videoSource = customPlayFunction3(chn,other);
                break;
            }
            default: {
                videoSource = defaultPlayFunction(chn,other);
                break;
            }
        }
        //do something else
    
    }
}

那么你可以使用 Enums 如果这些是有限的并且可以使用(取决于上下文,但目前你还没有提供任何信息):

public enum Channel{
  CUSTOM_1 {
    @Override
    public abstract MediaSource perform(Other other){
      // customPlayFunction1
    }
  }, 
  CUSTOM_2{
    @Override
    public abstract MediaSource perform(Other other){
      // customPlayFunction2
    }
  }, 
  CUSTOM_3{
    @Override
    public abstract MediaSource perform(Other other){
      // customPlayFunction3
    }
  }, 
  DEFAULT{
    @Override
    public abstract MediaSource perform(Other other){
      // defaultPlayFunction
    }
  };
  public abstract MediaSource perform(Other other);
}

否则你必须把责任分给Strategy:

public interface PlayStrategy{
  public MediaSource perform(Channel chn, Other other);
}
public class Custom1Strategy implements PlayStrategy{
  public MediaSource perform(Channel chn, Other other){
     // customPlayFunction1
  }
}
// same fore 2, 3  and default

并且在 Channel 中,您可以存储一个 PlayStrategy 对象,该对象将被传递给 PlayerClass,它会执行如下操作:

chn.getPlay().perform(chn, other);

最后但最不推荐的方法是使用这样的 Map<String, BiFunction<Channel, Other, MediaSource>>

public class PlayerClass {
    private BiFunction<Channel, Other, MediaSource>> map = new HashMap<>();
    public PlayerClass(){
        map.put("CustomPlayFunction1", this::customPlayFunction1)
        map.put("CustomPlayFunction2", this::customPlayFunction2)
        map.put("CustomPlayFunction3", this::customPlayFunction3)
    }
    private MediaSource customPlayFunction1(Channel chn, OtherParam other) {}
    private MediaSource customPlayFunction2(Channel chn, OtherParam other) {}
    private MediaSource customPlayFunction3(Channel chn, OtherParam other) {}
    private MediaSource defauPlayFunction(Channel chn, OtherParam other) {}
    public void playChannel(Activity activity, Channel chn) {
        map.getOrDefault(chn.customFunction, this::defauPlayFunction).apply(chn, other);
    }
}

您可以将 Mapjava.util.function 中的 BiFunction<Channel, OtherParam, MediaSource> 结合起来。您需要做的就是根据字符串键填充您的地图:

private Map<String, BiFunction<Channel, OtherParam, MediaSource>> myMap;

public void setup() {
    myMap = new HashMap<>();
    myMap.put("CustomPlayFunction1", this::customPlayFunction1);
    myMap.put("CustomPlayFunction2", this::customPlayFunction2);
    myMap.put("CustomPlayFunction3", this::customPlayFunction3);
}

public void playChannel(Activity activity, Channel chn) {
    videoSource = myMap.getOrDefault(chn.customFunction, this::defaultPlayFunction).apply(chn, other);
}

apply 将使用适当的参数调用接收到的函数。

getOrDefault 会捕捉任何在地图中找不到键的情况,并自动调用 defaultPlayFunction