1. Strategic Model
A policy pattern defines a set of algorithms that encapsulate each one and make them interchangeable
1. Primary Role of Policy Patterns
The main roles are as follows:
- Encapsulation role (Context): Also known as context role, it acts as a connecting link between encapsulation and encapsulation, blocking direct access to strategies and algorithms by high-level modules, encapsulating possible changes
- Abstract Policy Role: The abstraction of a policy family, usually an interface, that defines the methods and properties that each policy or algorithm must have
- ConcreteStrategy: Implements operations in abstract policies that contain specific algorithms
2. Implementation Strategy Mode
//Abstract Policy Role public interface Strategy { //Operational Rules for Strategic Modes void doSomething(); }
//Specific Strategy Roles public class ConcreteStrategy1 implements Strategy { @Override public void doSomething() { System.out.println("Operational Rules for Specific Strategy 1..."); } }
//Specific Strategy Roles public class ConcreteStrategy2 implements Strategy { @Override public void doSomething() { System.out.println("Operational Rules for Specific Strategy 2..."); } }
//Encapsulate roles public class Context { //Abstract Policy private Strategy strategy; //Constructor Settings Specific Policies public Context(Strategy strategy) { this.strategy = strategy; } //Encapsulated Strategy Methods public void doAnything() { this.strategy.doSomething(); } }
public class Client { public static void main(String[] args) { //Declare a specific policy Strategy strategy = new ConcreteStrategy1(); //Declare Context Object Context context = new Context(strategy); //Execute post-encapsulation methods context.doAnything(); } }
The results are as follows:
Rule of operation for specific strategy 1...
2. Using Spring to Implement Strategy Mode + Factory Mode
1. Implementation Policy Class
public interface Strategy { //Operational Rules for Strategic Modes void doSomething(); }
@Component public class ConcreteStrategy1 implements Strategy { @Override public void doSomething() { System.out.println("Operational Rules for Specific Strategy 1..."); } @Override public String toString() { return "Specific Strategy 1"; } }
@Component public class ConcreteStrategy2 implements Strategy { @Override public void doSomething() { System.out.println("Operational Rules for Specific Strategy 2..."); } @Override public String toString() { return "Specific Strategy 2"; } }
@Component public class DefaultStrategy implements Strategy { @Override public void doSomething() { System.out.println("Operational Rules for Default Policies..."); } @Override public String toString() { return "Default Policy"; } }
2. Implement factory class
@Component public class StrategyFactory { //Spring automatically injects the implementation class of the Strategy interface into this Map, with key as the bean id and value as the corresponding policy implementation class @Autowired private Map<String, Strategy> strategyMap; public Strategy getBy(String strategyName) { return strategyMap.get(strategyName); } }
Spring automatically injects the implementation class of the Strategy interface into this Map (provided that the implementation class is managed by the Spring container), which has a key of bean id and can be set in @Component(value = "xxx"), or lowercase by default.Value value is the corresponding policy implementation class
Test class:
@SpringBootTest class SpringbootDemoApplicationTests { @Autowired private ApplicationContext context; @Test public void test() { context.getBean(StrategyFactory.class).getBy("concreteStrategy1").doSomething(); context.getBean(StrategyFactory.class).getBy("concreteStrategy2").doSomething(); } }
The results are as follows:
Rule of operation for specific strategy 1... Rule of operation for specific strategy 2...
3. Alias Conversion
Using the bean id used by the above test class call, the actual business should be to escape the incoming code to the bean id of the corresponding policy class
@Component @PropertySource("classpath:application.properties") @ConfigurationProperties(prefix = "strategy") public class StrategyAliasConfig { private HashMap<String, String> aliasMap; public static final String DEFAULT_STATEGY_NAME = "defaultStrategy"; public HashMap<String, String> getAliasMap() { return aliasMap; } public void setAliasMap(HashMap<String, String> aliasMap) { this.aliasMap = aliasMap; } public String of(String entNum) { return aliasMap.get(entNum); } }
Configuration file application.properties
strategy.aliasMap.strategy1=concreteStrategy1 strategy.aliasMap.strategy2=concreteStrategy2
@Component public class StrategyFactory { @Autowired private StrategyAliasConfig strategyAliasConfig; //Spring automatically injects the implementation class of the Strategy interface into this Map, with key as the bean id and value as the corresponding policy implementation class @Autowired private Map<String, Strategy> strategyMap; //No corresponding policy class was found, using the default public Strategy getBy(String strategyName) { String name = strategyAliasConfig.of(strategyName); if (name == null) { return strategyMap.get(StrategyAliasConfig.DEFAULT_STATEGY_NAME); } Strategy strategy = strategyMap.get(name); if (strategy == null) { return strategyMap.get(StrategyAliasConfig.DEFAULT_STATEGY_NAME); } return strategy; } }
Test class:
@SpringBootTest class SpringbootDemoApplicationTests { @Autowired private ApplicationContext context; @Test public void test() { context.getBean(StrategyFactory.class).getBy("strategy1").doSomething(); context.getBean(StrategyFactory.class).getBy("strategy2").doSomething(); } }
The results are as follows:
Rule of operation for specific strategy 1... Rule of operation for specific strategy 2...
Reference resources:
Zen in Design Mode
https://mp.weixin.qq.com/s/cc4Slm0Ta22PShYuKpO2mQ