Reputation: 57
I have this class that contains four private methods, with same two arguments each, and a public method which chooses between them. The possible methods are stored in a Map and more may be added. I would like to dynamically call the proper method, removing the switch..case. Is there a polite way to do it, i.e. without 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
}
}
Upvotes: 1
Views: 455
Reputation: 12899
Well you can use Enums
if those are finite and makes sense to be used (depends on the context, but for the moment you have not provided any informations):
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);
}
Otherwise you have to separate the responsibility to a 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
and inside Channel
you can store a PlayStrategy
object that will be passed to the PlayerClass
that will do something like:
chn.getPlay().perform(chn, other);
The last but least suggested way, is using a Map<String, BiFunction<Channel, Other, MediaSource>>
like this:
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);
}
}
Upvotes: 1
Reputation: 4536
You could combine a Map
with a BiFunction<Channel, OtherParam, MediaSource>
from java.util.function
. All you need to do is fill your map depending on string key:
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
will call the received function with the appropriate parameters.
The getOrDefault
will catch any cases, where a key is not found in your map and automatically calls the defaultPlayFunction
.
Upvotes: 1