我是靠谱客的博主 文艺硬币,最近开发中收集的这篇文章主要介绍实战设计模式之策略模式一、定义二、特点三、结构四、实现五、总结,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

一、定义

策略(Strategy)模式的定义:该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。

二、特点

策略模式的主要优点如下。

  1. 多重条件语句不易维护,而使用策略模式可以避免使用多重条件语句,如 if…else 语句、switch…case 语句。
  2. 策略模式提供了一系列的可供重用的算法族,恰当使用继承可以把算法族的公共代码转移到父类里面,从而避免重复的代码。
  3. 策略模式可以提供相同行为的不同实现,客户可以根据不同时间或空间要求选择不同的。
  4. 策略模式提供了对开闭原则的完美支持,可以在不修改原代码的情况下,灵活增加新算法。
  5. 策略模式把算法的使用放到环境类中,而算法的实现移到具体策略类中,实现了二者的分离。

其主要缺点如下。

  1. 客户端必须理解所有策略算法的区别,以便适时选择恰当的算法类。
  2. 策略模式造成很多的策略类,增加维护难度。

三、结构

策略模式的主要角色如下。

  1. 抽象策略(Strategy)类:定义了一个公共接口,各种不同的算法以不同的方式实现这个接口,环境角色使用这个接口调用不同的算法,一般使用接口或抽象类实现。
  2. 具体策略(Concrete Strategy)类:实现了抽象策略定义的接口,提供具体的算法实现。
  3. 环境(Context)类:持有一个策略类的引用,最终给客户端调用。

四、实现

以基于 Spring Boot 的电商系统的支付方式为例,在购物支付时可以选择支付宝支付、微信支付、银联支付,此时可以应用我们的策略模式。

4.1 抽象策略类

package com.example.demo.designpattern.strategy.service;

import com.example.demo.designpattern.strategy.model.PayVO;
import com.example.demo.designpattern.strategy.model.Result;

/**
 * 支付抽象策略
 */
public interface PayStrategy {
    /**
     * 支付
     *
     * @param vo 参数
     * @return 结果
     */
    Result<Object> pay(PayVO vo);
}

4.2 具体策略类

4.2.1 支付宝支付

package com.example.demo.designpattern.strategy.service.concrete;

import com.example.demo.designpattern.strategy.model.AliPayInfo;
import com.example.demo.designpattern.strategy.model.PayModeEnum;
import com.example.demo.designpattern.strategy.model.PayVO;
import com.example.demo.designpattern.strategy.model.Result;
import com.example.demo.designpattern.strategy.service.PayStrategy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class AliPayStrategy implements PayStrategy {
    @Override
    public Result<Object> pay(PayVO vo) {
        log.info("{},{}", vo.getOrderId(), PayModeEnum.ALI_PAY.description());
        AliPayInfo payInfo = AliPayInfo.builder().outTradeNo("70501111111S001111119").tradeNo("2014112400001000340011111118").build();
        return Result.builder().code(0).data(payInfo).build();
    }
}

4.2.2 微信支付

package com.example.demo.designpattern.strategy.service.concrete;

import com.example.demo.designpattern.strategy.model.PayModeEnum;
import com.example.demo.designpattern.strategy.model.PayVO;
import com.example.demo.designpattern.strategy.model.Result;
import com.example.demo.designpattern.strategy.model.WechatPayInfo;
import com.example.demo.designpattern.strategy.service.PayStrategy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class WechatPayStrategy implements PayStrategy {
    @Override
    public Result<Object> pay(PayVO vo) {
        log.info("{},{}", vo.getOrderId(), PayModeEnum.WECHAT_PAY.description());
        WechatPayInfo payInfo = WechatPayInfo.builder().prepayId("123").tradeType("JSAPI").build();
        return Result.builder().code(0).data(payInfo).build();
    }
}

4.2.3 银联支付

package com.example.demo.designpattern.strategy.service.concrete;

import com.example.demo.designpattern.strategy.model.PayModeEnum;
import com.example.demo.designpattern.strategy.model.PayVO;
import com.example.demo.designpattern.strategy.model.Result;
import com.example.demo.designpattern.strategy.model.UnionPayInfo;
import com.example.demo.designpattern.strategy.service.PayStrategy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class UnionPayStrategy implements PayStrategy {
    @Override
    public Result<Object> pay(PayVO vo) {
        log.info("{},{}", vo.getOrderId(), PayModeEnum.UNION_PAY.description());
        UnionPayInfo payInfo = UnionPayInfo.builder().id("ch_L8qn10mLmr1GS8e5OODmHaL4").orderNo("123456789").build();
        return Result.builder().code(0).data(payInfo).build();
    }
}

4.3 环境类

package com.example.demo.designpattern.strategy.context;

import com.example.demo.designpattern.strategy.model.PayModeEnum;
import com.example.demo.designpattern.strategy.model.PayVO;
import com.example.demo.designpattern.strategy.service.PayStrategy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.Map;

@Service
public class PayContext {
    @Autowired
    private Map<String, PayStrategy> payStrategyMap;

    public Object pay(PayVO vo) {
        PayModeEnum payModeEnum = PayModeEnum.getEnum(vo.getPayMode());
        Assert.notNull(payModeEnum, "暂不支持该支付方式:" + vo.getPayMode());
        PayStrategy payStrategy = payStrategyMap.get(payModeEnum.strategy());
        Assert.notNull(payStrategy, "暂不支持该支付策略:" + payModeEnum.strategy());
        return payStrategy.pay(vo);
    }
}

说明:payStrategyMap 是借助于 Spring 自动注入方式得到所有具体策略,key默认为类名(首字母小写),value为对应实例。

4.4 接口调用

package com.example.demo.designpattern.strategy.controller;

import com.example.demo.designpattern.strategy.context.PayContext;
import com.example.demo.designpattern.strategy.model.PayVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/cashier")
public class CashierController {
    @Autowired
    private PayContext payContext;

    @PostMapping("/pay")
    public Object pay(@RequestBody PayVO vo) {
        return payContext.pay(vo);
    }
}

4.5 支付方式与策略对应关系枚举

package com.example.demo.designpattern.strategy.model;

import java.util.Arrays;

/**
 * 支付方式枚举
 */
public enum PayModeEnum {
    /**
     * 支付宝支付
     */
    ALI_PAY("aliPayStrategy", "支付宝支付策略"),
    /**
     * 微信支付
     */
    WECHAT_PAY("wechatPayStrategy", "微信支付策略"),
    /**
     * 银联支付
     */
    UNION_PAY("unionPayStrategy", "银联支付策略");

    private final String strategy;
    private final String description;

    public String strategy() {
        return strategy;
    }

    public String description() {
        return description;
    }

    PayModeEnum(String strategy, String description) {
        this.strategy = strategy;
        this.description = description;
    }

    public static PayModeEnum getEnum(String name) {
        return Arrays.stream(PayModeEnum.values()).filter(value -> value.name().equals(name)).findAny().orElse(null);
    }
}

4.6 其它关联类

package com.example.demo.designpattern.strategy.model;

import lombok.Builder;
import lombok.Data;

import java.io.Serializable;

@Data
@Builder
public class PayVO implements Serializable {
    private String payMode;
    private String orderId;
}
package com.example.demo.designpattern.strategy.model;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Result<T> implements Serializable {
    private Integer code;
    private T data;
    private String message;
}
package com.example.demo.designpattern.strategy.model;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class AliPayInfo implements Serializable {
    private String outTradeNo;
    private String tradeNo;
}
package com.example.demo.designpattern.strategy.model;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class WechatPayInfo implements Serializable {
    private String tradeType;
    private String prepayId;
}
package com.example.demo.designpattern.strategy.model;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UnionPayInfo implements Serializable {
    private String id;
    private String orderNo;
}

4.5 运行结果

选择支付宝支付
选择微信支付
选择银联支付

五、总结

策略模式避免了if…else、switch…case等操作,业务职责更清晰,符合开闭原则。

最后

以上就是文艺硬币为你收集整理的实战设计模式之策略模式一、定义二、特点三、结构四、实现五、总结的全部内容,希望文章能够帮你解决实战设计模式之策略模式一、定义二、特点三、结构四、实现五、总结所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(44)

评论列表共有 0 条评论

立即
投稿
返回
顶部