场景
策略模式(Strategy Pattern)
是指定义了算法家族并分别封装起来,让它们之间可以互相替换,
此模式使得算法的变化不会影响使用算法的用户。
策略模式的应用场景
1、系统中有很多类,而它们的区别仅仅在于行为不同。
2、一个系统需要动态地在几种算法中选择一种。
注:
博客:
霸道流氓气质的博客_CSDN博客-C#,架构之路,SpringBoot领域博主
关注公众号
霸道的程序猿
获取编程相关电子书、教程推送与免费下载。
业务举例-物流策略选择
在某物流管理系统中,车辆有人车、料车、皮卡车辆类型,三种车型分别有不同的物流规则。
调度员需要根据不同的货物制定不同的物流方案。
新建物流规则接口LogisticRules
package com.ruoyi.demo.designPattern.strategyPattern;
/**
* 物流规则类
*/
public interface LogisticsRules {
//执行物流
void doLogistics();
}
然后分别新建人车、料车、皮卡物流规则类
人车物流规则类
package com.ruoyi.demo.designPattern.strategyPattern;
public class PersonCarLogisticsRules implements LogisticsRules{
@Override
public void doLogistics() {
System.out.println("人车执行物流规则");
}
}
料车物流规则类
package com.ruoyi.demo.designPattern.strategyPattern;
public class SkipCatLogisticsRules implements LogisticsRules{
@Override
public void doLogistics() {
System.out.println("料车执行物流规则");
}
}
皮卡车物流规则类
package com.ruoyi.demo.designPattern.strategyPattern;
public class PickupCarLogisticsRules implements LogisticsRules{
@Override
public void doLogistics() {
System.out.println("皮卡车执行物流规则");
}
}
创建物流方案类
package com.ruoyi.demo.designPattern.strategyPattern;
/**
* 物流方案类
*/
public class LogisticsPlan {
private LogisticsRules logisticsRules;
public LogisticsPlan(LogisticsRules logisticsRules){
this.logisticsRules = logisticsRules;
}
public void execute(){
logisticsRules.doLogistics();
}
}
编写客户端测试类
package com.ruoyi.demo.designPattern.strategyPattern;
import org.apache.commons.lang.StringUtils;
public class logicticsTest {
public static void main(String[] args) {
//游客物流计划
LogisticsPlan visitorPlan = new LogisticsPlan(new PersonCarLogisticsRules());
//快递物流计划
LogisticsPlan expressPlan = new LogisticsPlan(new SkipCatLogisticsRules());
visitorPlan.execute();
expressPlan.execute();
}
}
在实际业务中,往往会根据不同的需求对物流规则进行动态选择,代码通常如下
//实际业务中会根据不同的需求对物流规则进行动态选择
LogisticsPlan logisticsPlan = null;
String logisticsKey = "EXPRESS";
if(StringUtils.equals(logisticsKey,"EXPRESS")){
logisticsPlan = new LogisticsPlan(new SkipCatLogisticsRules());
}else if(StringUtils.equals(logisticsKey,"VISITOR")){
logisticsPlan = new LogisticsPlan(new PersonCarLogisticsRules());
}
logisticsPlan.execute();
这样改造之后,如果经过业务积累,物流规则越来越多,每次上新规则都要改代码、重复测试。
所以可以结合单例模式和工厂模式进行优化。
设计模式-简单工厂模式、工厂模式、抽象工厂模式在Java中的使用示例:
设计模式-简单工厂模式、工厂模式、抽象工厂模式在Java中的使用示例_霸道流氓气质的博客-CSDN博客
设计模式-单例模式-饿汉式单例模式、懒汉式单例模式、静态内部类在Java中的使用示例:
设计模式-单例模式-饿汉式单例模式、懒汉式单例模式、静态内部类在Java中的使用示例_霸道流氓气质的博客-CSDN博客
创建LogisticsRulesFactory
package com.ruoyi.demo.designPattern.strategyPattern;
import java.util.HashMap;
import java.util.Map;
public class LogisticsRulesFactory {
private static Map<String,LogisticsRules> LOGISTICS_RULES_MAP = new HashMap<>();
static {
LOGISTICS_RULES_MAP.put(LogisticsKey.EXPRESS,new SkipCatLogisticsRules());
LOGISTICS_RULES_MAP.put(LogisticsKey.VISTOR,new PersonCarLogisticsRules());
}
//默认规则是皮卡车规则-既能拉人、又能拉货
private static final LogisticsRules DEFAULT_RULES = new PickupCarLogisticsRules();
private LogisticsRulesFactory(){}
public static LogisticsRules getLogsiticsRules(String logisticsKey){
LogisticsRules logisticsRules = LOGISTICS_RULES_MAP.get(logisticsKey);
return logisticsRules == null?DEFAULT_RULES:logisticsRules;
}
private interface LogisticsKey{
String VISTOR = "VISTOR";
String EXPRESS = "EXPRESS";
}
}
这时候客户端代码可以这样写
package com.ruoyi.demo.designPattern.strategyPattern;
public class logisticsBetterTest {
public static void main(String[] args) {
String logisticsKey = "EXPRESS";
LogisticsPlan logisticsPlan = new LogisticsPlan(LogisticsRulesFactory.getLogsiticsRules(logisticsKey));
logisticsPlan.execute();
}
}
业务示例-支付方式选择
支付时会选择支付方式,如果未选择,也会用默认的支付方式进行结算。
创建Payment抽象类,定义支付规范和支付逻辑
package com.ruoyi.demo.designPattern.strategyPattern;
public abstract class Payment {
//支付类型(名称)
public abstract String getName();
//查询余额
protected abstract double queryBalance(String uid);
//扣款支付
public PayState pay(String uid,double amount){
if(queryBalance(uid)<amount){
return new PayState(500,"支付失败","余额不足");
}
return new PayState(200,"支付成功","支付金额:"+amount);
}
}
分别创建具体的支付方式。
支付宝支付方式
package com.ruoyi.demo.designPattern.strategyPattern;
public class AliPay extends Payment{
@Override
public String getName() {
return "支付宝";
}
@Override
protected double queryBalance(String uid) {
return 900;
}
}
微信支付类
package com.ruoyi.demo.designPattern.strategyPattern;
public class WechatPay extends Payment{
@Override
public String getName() {
return "微信支付";
}
@Override
protected double queryBalance(String uid) {
return 600;
}
}
银联支付类
package com.ruoyi.demo.designPattern.strategyPattern;
public class UnionPay extends Payment{
@Override
public String getName() {
return "银联支付";
}
@Override
protected double queryBalance(String uid) {
return 1000;
}
}
创建支付状态的包装类
package com.ruoyi.demo.designPattern.strategyPattern;
public class PayState {
private int code;
private Object data;
private String msg;
public PayState(int code, Object data, String msg) {
this.code = code;
this.data = data;
this.msg = msg;
}
public String toString(){
return ("支付状态:["+code+"],"+msg+",交易详情:"+data);
}
}
创建支付策略管理类
package com.ruoyi.demo.designPattern.strategyPattern;
import java.util.HashMap;
import java.util.Map;
/**
* 支付策略管理类
*/
public class PayStrategy {
public static final String ALI_PAY = "ALI_PAY";
public static final String WECHAT_PAY = "WECHAT_PAY";
public static final String UNION_PAY = "UNION_PAY";
public static final String DEFAULT_PAY = "UNION_PAY";
private static Map<String,Payment> payStrategy = new HashMap<>();
static {
payStrategy.put(ALI_PAY,new AliPay());
payStrategy.put(WECHAT_PAY,new WechatPay());
payStrategy.put(UNION_PAY,new UnionPay());
}
public static Payment get(String payKey){
if(!payStrategy.containsKey(payKey)){
return payStrategy.get(DEFAULT_PAY);
}
return payStrategy.get(payKey);
}
}
创建订单类
package com.ruoyi.demo.designPattern.strategyPattern;
public class Order {
private String uid;
private String orderId;
private double amount;
public Order(String uid, String orderId, double amount) {
this.uid = uid;
this.orderId = orderId;
this.amount = amount;
}
public PayState pay(String payKey){
Payment payment = PayStrategy.get(payKey);
System.out.println("欢迎使用"+payment.getName());
System.out.println("本次交易金额为:"+amount+",开始扣款。。。");
return payment.pay(uid,amount);
}
}
测试代码如下
package com.ruoyi.demo.designPattern.strategyPattern;
public class PayStrategyTest {
public static void main(String[] args) {
Order order = new Order("001","2022103119105523",288.33);
//开始支付,选择支付方式,每个渠道的具体算法是不一样的,基本算法是固定的
//在支付的时候才决定这个值用哪个
System.out.println(order.pay(PayStrategy.ALI_PAY));
}
}
策略模式的优缺点
优点:
1、策略模式符合开闭原则。
2、策略模式可避免使用多重条件语句,如if…else语句、switch语句。
3、使用策略模式可以提高算法的保密性和安全性。
缺点:
1、客户端必须知道所有的策略,并且决定使用哪一个策略类。
2、代码中会产生非常多的策略类,增加了代码的维护难度。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/135879.html