A recent discussion thread on the Design Patterns LinkedIn group got me thinking that a blog on how to create a factory for strategies in Java would be useful. The method below removes the need for if or switch statements.
I will start with the code and then go on to look at the details.
The Strategy interface:
package com.tomasmalmsten.examples.strategy;
public interface Strategy {
void execute();
}
The Factory class:
package com.tomasmalmsten.examples.strategy;
import java.util.HashMap;
import java.util.Map;
public class StrategyFactory {
public static final String DEFAULT_STRATEGY_KEY = "default";
public static final String SPECIFIC_STRATEGY_KEY = "specific";
private static StrategyFactory instance = new StrategyFactory();
private Map<String, Strategy> strategies = new HashMap<String, Strategy>(2);
private StrategyFactory() {
strategies.put(DEFAULT_STRATEGY_KEY, new DefaultStrategy());
strategies.put(SPECIFIC_STRATEGY_KEY, new SpecificStrategy());
}
public Strategy findStrategyForKey(String key) {
return strategies.get(key);
}
public static StrategyFactory getInstance() {
return instance;
}
}
A strategy implementation:
package com.tomasmalmsten.examples.strategy;
public class DefaultStrategy implements Strategy {
DefaultStrategy() {}
public void execute() {
System.out.println("Default Strategy!");
}
}
Another strategy implementation:
package com.tomasmalmsten.examples.strategy;
public class SpecificStrategy implements Strategy {
SpecificStrategy() {}
public void execute() {
System.out.println("Specific Strategy!");
}
}
The example code is fairly simple. The complexity lies in how to create the factory and what responsibility it should have compared to the strategies. According to the single responsibility principle a class should only have one responsibility. Therefore the strategy should not do anything else then execute. The factories responsibility is to provide strategies to the client. Therefore it’s singleton instance does just that.
The client only need to know the key of the strategy it needs. This can be derived by class name, key word or something else and is stored as the key in the map that finds the correct strategy instance. To make the client logic simpler I have used Enum types to maintain keys in the past. The enum will then be able to create a valid key based on whatever is logical for the specific client.
Also note the access modifiers used for constructors. All creation logic is isolated to the package. This makes it easy to maintain since we know that nothing outside of the package can create new instances and instead has to use the factory to get an instance of the strategy.
The same recipe works well for creating other similar factories as well, for example Command factories.
A recent discussion thread on the Design Patterns LinkedIn group got me thinking that a blog on how to create a factory for strategies in Java would be useful. The method below removes the need for if or switch statements.
I will start with the code and then go on to look at the details.
The Strategy interface:
[java]
package com.tomasmalmsten.examples.strategy;
public interface Strategy {
void execute();
}
[/java]
The Factory class:
[java]
package com.tomasmalmsten.examples.strategy;
import java.util.HashMap;
import java.util.Map;
public class StrategyFactory {
public static final String DEFAULT_STRATEGY_KEY = "default";
public static final String SPECIFIC_STRATEGY_KEY = "specific";
private static StrategyFactory instance = new StrategyFactory();
private Map<String, Strategy> strategies = new HashMap<String, Strategy>(2);
private StrategyFactory() {
strategies.put(DEFAULT_STRATEGY_KEY, new DefaultStrategy());
strategies.put(SPECIFIC_STRATEGY_KEY, new SpecificStrategy());
}
public Strategy findStrategyForKey(String key) {
return strategies.get(key);
}
public static StrategyFactory getInstance() {
return instance;
}
}
[/java]
A strategy implementation:
[java]
package com.tomasmalmsten.examples.strategy;
public class DefaultStrategy implements Strategy {
DefaultStrategy() {}
public void execute() {
System.out.println("Default Strategy!");
}
}
[/java]
Another strategy implementation:
[java]
package com.tomasmalmsten.examples.strategy;
public class SpecificStrategy implements Strategy {
SpecificStrategy() {}
public void execute() {
System.out.println("Specific Strategy!");
}
}
[/java]
The example code is fairly simple. The complexity lies in how to create the factory and what responsibility it should have compared to the strategies. According to the single responsibility principle a class should only have one responsibility. Therefore the strategy should not do anything else then execute. The factories responsibility is to provide strategies to the client. Therefore it's singleton instance does just that.
The client only need to know the key of the strategy it needs. This can be derived by class name, key word or something else and is stored as the key in the map that finds the correct strategy instance. To make the client logic simpler I have used Enum types to maintain keys in the past. The enum will then be able to create a valid key based on whatever is logical for the specific client.
Also note the access modifiers used for constructors. All creation logic is isolated to the package. This makes it easy to maintain since we know that nothing outside of the package can create new instances and instead has to use the factory to get an instance of the strategy.
The same recipe works well for creating other similar factories as well, for example Command factories.