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);
}
}
您可以将 Map
与 java.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
。
我有这个 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);
}
}
您可以将 Map
与 java.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
。