Java 策略模式与模板方法模式相关总结

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()方法,从流中读取数据的方法时一样的,只是从什么流中读取的问题,可以从文件流中读,也可以从网络流中读。

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

以上就是Java 策略模式与模板方法模式相关总结的详细内容,更多关于Java 策略模式与模板方法模式的资料请关注我们其它相关文章!

(0)

相关推荐

  • Java设计模式之策略模式原理与用法实例详解

    本文实例讲述了Java设计模式之策略模式原理与用法.分享给大家供大家参考,具体如下: 策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式让算法独立于使用它的客户而独立变化.其中JDK里面的TreeSet类和TreeMap类就用到了策略模式.这两个类是带排序的集合类,其中排序的规则就相当于策略模式里定义的一系列算法,而集合类就相当于是策略模式里的环境类,供用户使用,用只知道TreeSet和TreeMap是带排序的,至于怎么排序的,是由排序的算法决定的. 策略模式

  • Java经典设计模式之策略模式原理与用法详解

    本文实例讲述了Java经典设计模式之策略模式.分享给大家供大家参考,具体如下: 策略模式指:策略模式指将程序中可变部分抽象分离成一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式让算法独立于使用它的客户而独立变化. 策略模式一般由下面三部分组成: 1. 抽象策略角色: 策略类,通常由一个接口或者抽象类实现. 2. 具体策略角色:包装了相关的算法和行为. 3. 环境角色:持有某一个策略类的引用,客户端调用. 策略模式设计原则: 1. 把程序中需要变化的部分抽离出来,独立于不变

  • Java如何利用策略模式替代if/else语句

    平时在开发中避免不了使用大量的if else语句,但过多层的if else对于性能有很大的开销,类似如下代码 public class MainStart { public static void main(String[] args) { String msgid = "MS066"; if(message.equals("MS066")){ System.out.println("MS066"); }else if (message.equa

  • Java利用策略模式优化过多if else代码

    前言 不出意外,这应该是年前最后一次分享,本次来一点实际开发中会用到的小技巧. 比如平时大家是否都会写类似这样的代码: if(a){ //dosomething }else if(b){ //doshomething }else if(c){ //doshomething } else{ ////doshomething } 条件少还好,一旦 else if 过多这里的逻辑将会比较混乱,并很容易出错. 比如这样: 摘自cim中的一个客户端命令的判断条件. 刚开始条件较少,也就没管那么多直接写的:

  • java 使用策略模式操作JDBC数据库

    java 使用策略模式操作JDBC数据库 1:构造一个操作数据库的工具类,可以获得连接和释放连接 public class DBUtil { private static Connection conn = null; static { //静态初始块 try { Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/tes

  • Java策略模式实现简单购物车功能

    策略模式是一种行为模式.用于某一个具体的项目有多个可供选择的算法策略,客户端在其运行时根据不同需求决定使用某一具体算法策略. 策略模式也被称作政策模式.实现过程为,首先定义不同的算法策略,然后客户端把算法策略作为它的一个参数.使用这种模式最好的例子是Collection.sort()方法了,它使用Comparator对象作为参数.根据Comparator接口不同实现,对象会被不同的方法排序. 本文例子是,完成一个简单地购物车,两种付款策略可供选择,一为信用卡,另外一种为Paypal. 首先创建策

  • Java使用策略模式解决商场促销商品问题示例

    本文实例讲述了Java使用策略模式解决商场促销商品问题.分享给大家供大家参考,具体如下: 一 模式定义 策略模式:定义一系列的算法,将每一种算法封装起来并可以相互替换使用,策略模式让算法独立于使用它的客户应用而独立变化. 二 模式举例 1 模式分析 我们借用商场促销商品来说明这一模式. 2 策略模式静态类图 3 代码示例 3.1 创建策略接口一IStrategy package com.demo.strategy; /** * 策略接口 * * @author * */ public inter

  • Java设计模式之策略模式定义与用法详解

    本文实例讲述了Java策略模式定义与用法.分享给大家供大家参考,具体如下: 一. 定义: 定义一系列算法,把他们一个一个封装起来,并且使他们可以相互替换. 二. 优点: (1)上下文(Context)和具体策略(ConcreteStrategy)是松耦合关系,因此上下文只需要知道他要使用某一个实现  Strategy接口类的实例,但不需要知道是哪个类. (2)策略模式满足开闭原则,当增加新的具体类时,不需要修改上下文类的代码,上下文即可以引用新的具体策略的实例. 三. 实例: 下面就通过一个问题

  • 23种设计模式(11)java策略模式

    23种设计模式的学习视频已为大家备好,需要的可以在公众号内回复"设计模式"获取下载链接. 定义:定义一组算法,将每个算法都封装起来,并且使他们之间可以互换. 类型:行为类模式 类图: 策略模式是对算法的封装,把一系列的算法分别封装到对应的类中,并且这些类实现相同的接口,相互之间可以替换.在前面说过的行为类模式中,有一种模式也是关注对算法的封装--模版方法模式.         对照类图可以看到,策略模式与模版方法模式的区别仅仅是多了一个单独的封装类Context,它与模版方法模式的区别

  • java设计模式学习之策略模式

    策略模式:策略模式是一种定义一系列算法的方法,算法完成的工作都是相同的工作,但是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合. Java实现一个策略模式: 需求:商场收银系统,收银方式为正常收费,打八折,满300返100,这三种收费方式. 1:创建一个超类.即收费的抽象方法. public abstract class CashSuper { public abstract double acceptCash(double money); } 2:创建实现此

随机推荐