principlejavaModerate
Strategy pattern instances based on enums
Viewed 0 times
instancesbasedstrategyenumspattern
Problem
I have a
Based on some enum, I know which
Obviously, this is simplified. In my actual code I have 25 of those
Is there a better way to do this
Usage in views:
```
class MyOnItemSelectedListener implements OnItemSelectedListener
view which takes a DataPresenterStrategy instance to retrieve the proper text out of some data:public interface DataPresenterStrategy {
String getDisplayString(Data data);
String getUnit();
}
public class DistanceStrategy implements DataPresenterStrategy {
@Override
public String getDisplayString(Data data) {
return data.getDistance();
}
@Override
public String getUnit() {
return "m";
}
}
public class PowerStrategy implements DataPresenterStrategy {
@Override
public String getDisplayString(Data data) {
return data.getPower();
}
@Override
public String getUnit() {
return "W";
}
}Based on some enum, I know which
DataPresenterStrategy to create:enum DataPresenterStrategyType { DISTANCE, POWER }
DataPresenterStrategy toStrategy(StrategyType type) {
switch(type) {
case DISTANCE:
return new DistanceStrategy();
case POWER:
return new PowerStrategy();
}
}Obviously, this is simplified. In my actual code I have 25 of those
Strategy classes.Is there a better way to do this
DataPresenterStrategy instance creation?Usage in views:
public interface DataPresenter {
void setDataPresenterStrategy(DataPresenterStrategy strategy);
}
public class DataView implements DataPresenter {
private DataPresenterStrategy mDataPresenterStrategy;
@Override
public void setDataPresenterStrategy(DataPresenterStrategy strategy) {
mDataPresenterStrategy = strategy;
}
}
public class MyApplication {
private DataPresenter[] mDataPresenters;
public void setDataPresenterStrategy(int dataPresenterIndex, DataPresenterStrategyType type) {
switch (type)
/* (...) */
}
}setDataPresenterStrategy(int, DataPresenterStrategyType) is called when a user selects an item from a spinner:```
class MyOnItemSelectedListener implements OnItemSelectedListener
Solution
Another way to do the instance creation would be to give each type a constructor reference for the strategy it corresponds to.
The main advantages I see for this way are the compile time safety that each type has a
If not all of the constructors of your strategies take the same arguments you can replace the constructor reference with a lambda.
If you don't have access to Java 8, you can accomplish the same thing more verbosely with an anonymous class instead of the constructor reference, or you could make
enum DataPresenterStrategyType {
DISTANCE(DistanceStrategy::new), POWER(PowerStrategy::new);
private final Supplier constructor;
DataPresenterStrategyType(Supplier constructor){
this.constructor = constructor;
}
DataPresenterStrategy newStrategy() {
return constructor.get();
}
}The main advantages I see for this way are the compile time safety that each type has a
Supplier and that you don't need to look for all the switch statements in your project to add cases if you add a new strategy type.If not all of the constructors of your strategies take the same arguments you can replace the constructor reference with a lambda.
If you don't have access to Java 8, you can accomplish the same thing more verbosely with an anonymous class instead of the constructor reference, or you could make
newStrategy() an abstract method and implement it in each type.Code Snippets
enum DataPresenterStrategyType {
DISTANCE(DistanceStrategy::new), POWER(PowerStrategy::new);
private final Supplier<DataPresenterStrategy> constructor;
DataPresenterStrategyType(Supplier<DataPresenterStrategy> constructor){
this.constructor = constructor;
}
DataPresenterStrategy newStrategy() {
return constructor.get();
}
}Context
StackExchange Code Review Q#58489, answer score: 10
Revisions (0)
No revisions yet.