• 策略模式与模板方法模式


    1.  策略模式

    策略模式是一种行为设计模式,它能让你定义一系列算法,并将每种算法分别放入独立的类中,以使算法的对象能够相互替换。

    当你有许多仅在执行某些行为时略有不同的相似类时,可使用策略模式。使用该模式能将类的业务逻辑与其算法实现细节隔离开来。

    说白了,其实还是解耦

    策略模式的结构如上图所示,主要包含三个角色:

    • 抽象角色:通常是一个接口
    • 具体角色:接口的具体实现
    • 环境角色:调用接口的上下文环境,通常是一段业务逻辑方法

    举个常见的例子:支付

    先定义一个接口 PayStrategy.java

    package com.example.service;
    
    import com.example.domain.dto.PayDTO;
    import com.example.domain.dto.PayDetailDTO;
    
    /**
     * @author ChengJianSheng
     * @date 2021/1/11
     */
    public interface PayStrategy {
    
        /**
         * 下单
         */
        PayDTO prepay();
    
        /**
         * 查询
         */
        PayDetailDTO query();
    
        /**
         * 撤销
         */
        void cancel();
    
        /**
         * 退款
         */
        void refund();
    
    } 

    然后是具体实现

    AlipayStrategy.java 

    package com.example.service.impl;
    
    import com.alipay.api.AlipayClient;
    import com.alipay.api.request.AlipayTradePrecreateRequest;
    import com.alipay.api.response.AlipayTradeCancelResponse;
    import com.example.domain.dto.PayDTO;
    import com.example.domain.dto.PayDetailDTO;
    import com.example.service.PayStrategy;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    /**
     * https://opendocs.alipay.com/open/common/abilitymap
     * https://opendocs.alipay.com/open/194/106078
     * 扫码支付
     */
    @Component
    public class AlipayStrategy implements PayStrategy {
    
        @Autowired
        private AlipayClient alipayClient;
    
        @Override
        public PayDTO prepay() {
            AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
            AlipayTradeCancelResponse response = alipayClient.execute(request);
            return null;
        }
    
        @Override
        public PayDetailDTO query() {
            return null;
        }
    
        @Override
        public void cancel() {
    
        }
    
        @Override
        public void refund() {
    
        }
    
        public void payNotify(String data) {
    
        }
    
        public void refundNotify() {
    
        }
    }
    

    WeixinPayStrategy.java

    package com.example.service.impl;
    
    import com.example.domain.dto.PayDTO;
    import com.example.domain.dto.PayDetailDTO;
    import com.example.service.PayStrategy;
    import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
    import com.github.binarywang.wxpay.bean.request.WxPayOrderQueryRequest;
    import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
    import com.github.binarywang.wxpay.service.WxPayService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    /**
     * https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pages/index.shtml
     * https://github.com/Wechat-Group/WxJava/wiki/%E5%BE%AE%E4%BF%A1%E6%94%AF%E4%BB%98
     * @author ChengJianSheng
     * @date 2021/1/11
     */
    @Component
    public class WeixinPayStrategy implements PayStrategy {
    
        @Autowired
        private WxPayService wxPayService;
    
        @Override
        public PayDTO prepay() {
            WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
            wxPayService.createOrder(request);
            return null;
        }
    
        @Override
        public PayDetailDTO query() {
            WxPayOrderQueryRequest request = new WxPayOrderQueryRequest();
            wxPayService.queryOrder(request);
            return null;
        }
    
        @Override
        public void cancel() {
    
        }
    
        @Override
        public void refund() {
    
        }
    
        public void payNotify(String data) {
            WxPayOrderNotifyResult result = wxPayService.parseOrderNotifyResult(data);
        }
    
        public void refundNotify(String data) {
            WxPayOrderNotifyResult result = wxPayService.parseRefundNotifyResult(data);
        }
    } 

    上下文

    package com.example.service.impl;
    
    import com.example.domain.dto.PayDTO;
    import com.example.service.PayService;
    import com.example.service.PayStrategy;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    /**
     * @author ChengJianSheng
     * @date 2021/1/11
     */
    @Service
    public class PayServiceImpl implements PayService {
        @Autowired
        private AlipayStrategy alipayStrategy;
        @Autowired
        private WeixinPayStrategy weixinPayStrategy;
    
        @Override
        public void prePay(PayDTO payDTO) {
            //  创建支付订单
            //  组装参数
            PayStrategy payStrategy = null;
            if (payDTO.getChannel() == 1) {
                payStrategy = alipayStrategy;
            } else {
                payStrategy = weixinPayStrategy;
            }
    
            payStrategy.prepay();
    
        }
    } 

    这样就将算法的细节与业务逻辑隔离开,开发始终要遵循的原则是:高内聚,低耦合

    其余部分代码补充如下:

    pom.xml

    <dependency>
        <groupId>com.alipay.sdk</groupId>
        <artifactId>alipay-sdk-java</artifactId>
        <version>4.11.8.ALL</version>
    </dependency>
    <dependency>
        <groupId>com.github.binarywang</groupId>
        <artifactId>weixin-java-pay</artifactId>
        <version>4.0.0</version>
    </dependency>
    

     AlipayConfig.java

    package com.example.config;
    
    import com.alipay.api.AlipayClient;
    import com.alipay.api.DefaultAlipayClient;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    /**
     * 扫码支付
     * https://opendocs.alipay.com/open/194/106078
     * https://opendocs.alipay.com/open/common/abilitymap
     *
     * @author ChengJianSheng
     * @date 2021/1/11
     */
    @Configuration
    public class AlipayConfig {
        @Value("${alipay.appId}")
        private String appId;
        @Value("${alipay.privateKey}")
        private String privateKey;
        @Value("${alipay.publicKey}")
        private String publicKey;
    
        @Bean
        public AlipayClient alipayClient() {
            AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", appId, privateKey, "json", "UTF-8", publicKey, "RSA2");
            return alipayClient;
        }
    }
    

    WeixinPayConfig.java 

    package com.example.config;
    
    import com.github.binarywang.wxpay.config.WxPayConfig;
    import com.github.binarywang.wxpay.service.WxPayService;
    import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    /**
     * https://pay.weixin.qq.com/wiki/doc/apiv3/index.shtml
     * https://github.com/Wechat-Group/WxJava/wiki/%E5%BE%AE%E4%BF%A1%E6%94%AF%E4%BB%98
     * @author ChengJianSheng
     * @date 2021/1/11
     */
    @Configuration
    public class WeixinPayConfig {
        /**
         * 公众号appid
         */
        @Value("${weixin.pay.appId}")
        private String appId;
        /**
         * 商户号.
         */
        @Value("${weixin.pay.mchId}")
        private String mchId;
        /**
         * 商户密钥.
         */
        @Value("${weixin.pay.mchKey}")
        private String mchKey;
    
        @Value("${weixin.pay.notifyUrl}")
        private String notifyUrl;
    
        @Bean
        public WxPayService wxPayService() {
            WxPayConfig payConfig = new WxPayConfig();
            payConfig.setAppId(appId);
            payConfig.setMchId(mchId);
            payConfig.setMchKey(mchKey);
            payConfig.setNotifyUrl(notifyUrl);
    
            WxPayService wxPayService = new WxPayServiceImpl();
            wxPayService.setConfig(payConfig);
            return wxPayService;
        }
    }
    

    2.  模板方法模式

    模板方法模式是一种行为设计模式,它在超类中定义了一个算法的框架,允许子类在不修改结构的情况下重写算法的特定步骤。 

    当多个类的算法除一些细微不同之外几乎完全一样时,可使用该模式。

    这里,“算法”应理解为一个功能,或者一段业务逻辑 

    模板方法模式的结构如上图所示,主要实现方式是

    1. 将一些公共的逻辑抽象出来,将功能实现分解为多个步骤
    2. 定义抽象类,将有差异的步骤声明为抽象方法
    3. 子类继承抽象基类,实现其中的抽象方法 

    模板方法减少了重复代码,将公共代码提到基类中,子类只需关注各自差异化的逻辑 

    上面的支付,也可以用模板方法模式来实现。

    个人觉得,策略模式、工厂方法模式、模板方法模式,这三个都比较像。能用模板方法模式的地方,通常也可以用策略模式。

    只是它们的侧重点不一样,策略模式的侧重点在于可以动态切换算法,即同样的参数,用不同的策略执行,可以得到不同的结果。

    而模板方法模式的侧重点在于算法结构不变,中间的某些步骤的具体实现可以不同。

    如果我们把策略模式中的上下文看成一个算法的话,那策略模式中的具体实现就是特定的步骤,这么一想,感觉二者太像了。

    模板方法模式有一个活生生的例子是java.io.InputStream。InputStream中定义了一个抽象的read()方法,从流中读取数据的方法时一样的,只是从什么流中读取的问题,可以从文件流中读,也可以从网络流中读。

    最后,不要为了用设计模式而用设计模式

    https://refactoringguru.cn/design-patterns

  • 相关阅读:
    PyQt(Python+Qt)学习随笔:窗口的布局设置及访问
    PyQt(Python+Qt)学习随笔:QAbstractItemView的showDropIndicator属性
    PyQt学习随笔:QStandardItemModel使用注意事项
    Windows 2008 R2 防火墙允许Serv-U通过的方法
    实例化php类的时候如何传参
    密码强度检测
    php和c++socket通讯(基于字节流,二进制)
    PHP 魔术方法__set() __get() 方法详解
    type='button'和'submit'的区别
    jQuery实现CheckBox全选、全不选
  • 原文地址:https://www.cnblogs.com/cjsblog/p/14272184.html
Copyright © 2020-2023  润新知