Policy mode and using Spring to implement Policy mode + Factory mode

Keywords: Spring

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

185 original articles published, 418 praised, 90,000 visits+
Private letter follow

Posted by kane007 on Thu, 30 Jan 2020 18:01:44 -0800