(Design patterns topic 2) Strategy Mode

What is the strategy pattern

Strategy Mode is a package of algorithms, and algorithms use is the responsibility of segmentation algorithm itself off, delegated to a different object management , and ultimately can be achieved to address multiple if judgment.

1. Environment (Context) role: to hold a reference to the Strategy.

2. Abstract Strategy (Strategy) Role: This is an abstract role, usually implemented by an interface or abstract class. This role gives specific strategies required for all class interface.

3. Specific strategies (ConcreteStrategy) role: packaging related algorithms or behavior.

Defined strategy interfaces -> implement a different strategy class -> Strategy calls using multi-state or otherwise

Why are we called to do policy mode

Each judge if that can be understood as a policy.

Strategy mode advantages and disadvantages

advantage

Algorithm can freely switch (high-level masking algorithms, free to switch roles)

Avoid using multiple conditional (if there will be a variety of algorithms much the same judgment, it is difficult to maintain)

Good scalability (cancellation algorithm can be freely added without affecting the overall function)

Shortcoming

An increase in the number of class strategy (a strategy for each class reusability is very small, if the need to increase the algorithm, it can only add class)

All policies need of external exposure class (who used must understand the use of strategies, the need to supplement other modes, such as factory mode, proxy mode)

Strategy mode scenario 

Polymerization payment platform

For example, to build a polymerization time payment platform, this time the need butt many third-party payment interface, such as Alipay, micro-channel pay, millet payments.

By tradition if the code judgment, maintenance of late is very poor!

S Pring framework strategy used in the model

ClassPathXmlApplicationContext Spring underlying Resource Interface using the strategy pattern

Spring for the Resource provides the following interface implementation class:

A UrlResource : implementation class access to network resources.

A ClassPathResource : access path in the class loader implementation class resources.

FileSystemResource : access to the file system implementation class resources.

ServletContextResource : access with respect to the ServletContext implement the classpath resources:

InputStreamResource : implementation class to access the input stream resources.

Prefer ByteArrayResource : implementation classes to access an array of bytes resources.

1new ClassPathXmlApplicationContext("");

2. Go to the constructor.

 

 

 3.

4.SpringBean initialization SimpleInstantiationStrategy

SimpleInstantiationStrategy simple initialization strategy

CglibSubclassingInstantiationStrategy CGLIB initialization strategy

策略模式架构

 

 

 

策略模式环境搭建

创建项目名称 springboot_ strategy

Maven依赖信息

 

 1 <parent>
 2     <groupId>org.springframework.boot</groupId>
 3     <artifactId>spring-boot-starter-parent</artifactId>
 4     <version>2.0.1.RELEASE</version>
 5 </parent>
 6 <dependencies>
 7     <!-- sprinboot web -->
 8     <dependency>
 9         <groupId>org.springframework.boot</groupId>
10         <artifactId>spring-boot-starter-web</artifactId>
11     </dependency>
12     <dependency>
13         <groupId>org.projectlombok</groupId>
14         <artifactId>lombok</artifactId>
15         <version>1.16.10</version>
16     </dependency>
17     <dependency>
18         <groupId>commons-lang</groupId>
19         <artifactId>commons-lang</artifactId>
20         <version>2.6</version>
21     </dependency>
22     <dependency>
23         <groupId>org.mybatis.spring.boot</groupId>
24         <artifactId>mybatis-spring-boot-starter</artifactId>
25         <version>1.1.1</version>
26     </dependency>
27     <!-- mysql 依赖 -->
28     <dependency>
29         <groupId>mysql</groupId>
30         <artifactId>mysql-connector-java</artifactId>
31     </dependency>
32 </dependencies>

PayStrategy(抽象角色)

1 public interface PayStrategy {
2 
3     /**
4      * 共同算法实现骨架
5      * @return
6      */
7      public String toPayHtml();
8 }

ConcreteStrategy (具体实现角色)

1 @Component
2 public class AliPayStrategy  implements PayStrategy {
3     public String toPayHtml() {
4         return "调用支付宝支付接口";
5     }
6 }
1 @Component
2 public class XiaoMiPayStrategy implements PayStrategy {
3     public String toPayHtml() {
4         return "调用小米支付接口";
5     }
6 }

PayContextService (上下文)

@RestController
public class PayContextService {

    @Autowired
    private PaymentChannelMapper paymentChannelMapper;
    @Autowired
    private  SpringUtils springUtils;
@RequestMapping(
"/toPayHtml") public String toPayHtml(String payCode){ // 1.验证参数 if(StringUtils.isEmpty(payCode)){ return "payCode不能为空!"; } // 2.使用PayCode查询 PaymentChannelEntity paymentChannel = paymentChannelMapper.getPaymentChannel(payCode); if(paymentChannel==null){ return "该渠道为空..."; } // 3.获取策略执行的beanid String strategyBeanId = paymentChannel.getStrategyBeanId(); // 4.使用strategyBeanId获取对应spring容器bean信息 PayStrategy payStrategy = springUtils.getBean(strategyBeanId, PayStrategy.class); // 5.执行具体策略算法 return payStrategy.toPayHtml(); } }

SpringUtils(工具类)

 1 @Component
 2 public class SpringUtils implements ApplicationContextAware {
 3 
 4     private static ApplicationContext applicationContext;
 5 
 6     @Override
 7     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
 8         this.applicationContext = applicationContext;
 9     }
10 
11     //获取applicationContext
12     public static ApplicationContext getApplicationContext() {
13         return applicationContext;
14     }
15 
16     //通过name获取 Bean.
17     public static Object getBean(String name){
18         return getApplicationContext().getBean(name);
19     }
20 
21     //通过class获取Bean.
22     public static <T> T getBean(Class<T> clazz){
23         return getApplicationContext().getBean(clazz);
24     }
25 
26     //通过name,以及Clazz返回指定的Bean
27     public static <T> T getBean(String name,Class<T> clazz){
28         return getApplicationContext().getBean(name, clazz);
29     }
30 
31 }

枚举类

 1 public enum PayEnumStrategy {
 2 
 3     /**
 4      *  支付宝支付
 5      */
 6     ALI_PAY("com.mayikt.strategy.impl.AliPayStrategy"),
 7     /**
 8      *  银联支付
 9      */
10     UNION_PAY("com.mayikt.strategy.impl.UnionPayStrategy");
11     PayEnumStrategy(String className) {
12         this.setClassName(className);
13     }
14 
15     public String getClassName() {
16         return className;
17     }
18 
19     public void setClassName(String className) {
20         this.className = className;
21     }
22 
23     /**
24      * class完整地址
25      */
26     private String className;
27 
28 }

StrategyFactory

 1 public class StrategyFactory {
 2     public static PayStrategy getPayStrategy(String strategyType) {
 3         try {
 4             // 1.获取枚举中className
 5             String className = PayEnumStrategy.valueOf(strategyType).getClassName();
 6             // 2.使用java反射技术初始化类
 7             return (PayStrategy) Class.forName(className).newInstance();
 8         } catch (Exception e) {
 9             return null;
10         }
11     }
12 }

数据库访问层

相关SQL语句:

 1 DROP TABLE IF EXISTS `payment_channel`;
 2 CREATE TABLE `payment_channel` (
 3   `ID` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
 4   `CHANNEL_NAME` varchar(32) NOT NULL COMMENT '渠道名称',
 5   `CHANNEL_ID` varchar(32) NOT NULL COMMENT '渠道ID',
 6   `strategy_bean_id` varchar(255) DEFAULT NULL COMMENT '策略执行beanid',
 7   PRIMARY KEY (`ID`,`CHANNEL_ID`)
 8 ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COMMENT='支付渠道 ';
 9 
10 -- ----------------------------
11 -- Records of payment_channel
12 -- ----------------------------
13 INSERT INTO `payment_channel` VALUES ('4', '支付宝渠道', 'ali_pay', 'aliPayStrategy');
14 INSERT INTO `payment_channel` VALUES ('5', '小米支付渠道', 'xiaomi_pay', 'xiaoMiPayStrategy');

实体类

 1 @Data
 2 public class PaymentChannelEntity {
 3    /** ID */
 4    private Integer id;
 5    /** 渠道名称 */
 6    private String channelName;
 7    /** 渠道ID */
 8    private String channelId;
 9    /**
10     * 策略执行beanId
11     */
12    private String strategyBeanId;
13 
14 }

数据库访问层

1 public interface PaymentChannelMapper {
2      @Select("\n" +
3              "SELECT  id as id ,CHANNEL_NAME as CHANNELNAME ,CHANNEL_ID as CHANNELID,strategy_bean_id AS strategybeanid\n" +
4              "FROM payment_channel where CHANNEL_ID=#{payCode}")
5      public PaymentChannelEntity getPaymentChannel(String payCode);
6 }

 

 

优点:策略模式最终帮助我们解决在实际开发中多重if判断问题、提高扩展性、维护性增强、提高代码可读性。

缺点:后期维护不同策略类是非常多、定义类比较多、代码量增大。

优点大于缺点。

Guess you like

Origin www.cnblogs.com/lmyupupblogs/p/12088237.html