首页 > 编程语言 >设计模式-策略模式在Java中的使用示例

设计模式-策略模式在Java中的使用示例

时间:2022-10-31 20:12:50浏览次数:75  
标签:Java String 示例 com package new 设计模式 strategyPattern public

场景

策略模式(Strategy Pattern)

是指定义了算法家族并分别封装起来,让它们之间可以互相替换,

此模式使得算法的变化不会影响使用算法的用户。

策略模式的应用场景

1、系统中有很多类,而它们的区别仅仅在于行为不同。

2、一个系统需要动态地在几种算法中选择一种。

注:

博客:
https://blog.csdn.net/badao_liumang_qizhi
关注公众号
霸道的程序猿
获取编程相关电子书、教程推送与免费下载。

业务举例-物流策略选择

在某物流管理系统中,车辆有人车、料车、皮卡车辆类型,三种车型分别有不同的物流规则。

调度员需要根据不同的货物制定不同的物流方案。

新建物流规则接口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中的使用示例:

https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/127539695

设计模式-单例模式-饿汉式单例模式、懒汉式单例模式、静态内部类在Java中的使用示例:

https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/127555096

创建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、代码中会产生非常多的策略类,增加了代码的维护难度。

 

标签:Java,String,示例,com,package,new,设计模式,strategyPattern,public
From: https://www.cnblogs.com/badaoliumangqizhi/p/16845578.html

相关文章

  • Java 从入门到放弃12 - 《网络编程基础》
    网络编程基础为了把计算机接入互联网,就必须要使用TCP/IP协议。TCP/IP协议泛指互联网协议,其中最重要的两个就是TCP和IP协议,而使用其他网络协议都是无法接入互联网的IP地......
  • Java学习笔记day1——注释
    /*java包含以下三种注释方法:1.单行注释2.多行注释*单行多行注释对所写程序进行注释说明,增强可读性,方便自己方便别人。*还可以调试所写的代码,注释内容均不参与编译......
  • Java学习笔记day1——变量
    /*1.关键字(keyword)和保留字*所有关键字都是小写的;*保留字:现有的Java版本尚未使用,但是以后的版本可能会用:goto,const。2.标识符--identifier*凡是可以自己起......
  • Java学习笔记day1——String类型变量
    /*String(字符串)类型变量的使用*1.String属于引用数据类型;*2.String用双引号""进行定义;*/classStringTest{publicstaticvoidmain(String[]ag......
  • java构造器
    后期使用反射的时候,如果自己重写了一个构造器,那么系统不会默认添加无参构造器,建议在写类时,如果要添加有参构造方法,一定要将无参构造方法也加上classStudent{//构......
  • Qt on Android 开发之 C++与Java 交互
    目录​​简述​​​​Qt引入Android模块​​​​Java示例​​​​Cpp与java交互​​简述我做了一个小例子,来实现了C++与Java之间的交互。该示例是以整形和字符型举例说明,......
  • java中将word转换为html导入到kindeditor编辑器中(解决图片问题,样式,非常完美)
    ​ 项目需求可发布文章需求涉及到富文本编辑器经过查阅我选择了较为简便不需要后端支持可独立完成的tinymce框架官方文档也是相当完整虽然都是全英文但是有强大的......
  • 完美解决 java: 无效的目标发行版: 11
    1、问题描述经过研究才发现,这是因为作者使用了jdk8进行编译,而试图使用jdk11的功能,这就必然会导致版本问题,因为jdk8支持1-8这个区间的功能,如何解决这个问题呢? image-2......
  • 设计模式十(备忘录模式,观察者模式,状态模式)
    备忘录模式(MementoPattern)保存一个对象的某个状态,以便在适当的时候恢复对象。备忘录模式属于行为型模式。介绍意图:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该......
  • javascript日期处理函数的一些问题
    问题1:newDate(字符串)产生的日期对象,在某些情形下,可能会自动增加1天。猜测是和时区有关,浏览器没有默认当前时区?这是一个坑。问题2:setDate()设置日期后不准确的问题。比如......