策略模式的介绍

策略模式是一种设计模式,它定义了一系列算法,并将每个算法封装起来,使它们可以相互替换。这种模式使得算法可以在不修改客户端代码的情况下独立变化。文章通过代码示例展示了如何创建抽象策略、具体策略和上下文类,并解释了其优点和缺点,如易于扩展、提高代码可读性,但需要额外的类和接口。最后,文章给出了一个优化if-else结构的审计策略应用实例。
摘要由CSDN通过智能技术生成

什么是策略模式

定义一系列算法,将每一个算法封装起来,并使它们可以相互替换。策略模式让算法可以独立于使用它的客户端而变化。

 

策略模式结构

1)抽象策略(Strategy)类:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有具体策略类所需的接口。

2)具体策略(Concrete Strategy)类:实现了抽象策略定义的接口,提供具体的算法实现或行为。

3)环境或上下文(Context)类:是使用算法的角色,持有一个策略类的引用,最终给客户端调用。

代码示例:

package main.java.cn.test.strategy.V1;

/**
 * @author ningzhaosheng
 * @date 2023/6/11 14:28:43
 * @description
 */
public interface Strategy {
    void algorithm();
}
package main.java.cn.test.strategy.V1;

import main.java.cn.test.strategy.V1.Strategy;

/**
 * @author ningzhaosheng
 * @date 2023/6/11 14:29:10
 * @description
 */
public class ConcreteStrategyA implements Strategy {
    @Override
    public void algorithm(){
        System.out.println("执行策略A");
    }
}
package main.java.cn.test.strategy.V1;

import main.java.cn.test.strategy.V1.Strategy;

/**
 * @author ningzhaosheng
 * @date 2023/6/11 14:29:49
 * @description
 */
public class ConcreteStrategyB implements Strategy {
    @Override
    public void algorithm() {
        System.out.println("执行策略B");
    }
}
package main.java.cn.test.strategy.V1;

import main.java.cn.test.strategy.V1.Strategy;

/**
 * @author ningzhaosheng
 * @date 2023/6/11 14:30:13
 * @description
 */
public class Context {
    private Strategy strategy;

    public Context(Strategy strategy){
        this.strategy = strategy;
    }
    // 调用策略类中的算法
    public void algorithm(){
        strategy.algorithm();
    }
}
package main.java.cn.test.strategy.V1;

import main.java.cn.test.strategy.V1.ConcreteStrategyA;
import main.java.cn.test.strategy.V1.Context;
import main.java.cn.test.strategy.V1.Strategy;

/**
 * @author ningzhaosheng
 * @date 2023/6/11 14:30:31
 * @description
 */
public class Client {
    public static void main(String [] args){
        Strategy strategyA = new ConcreteStrategyA();
        // 具体策略类,可以在运行时指定类型,通过配置文件+反射机制实现
        Context context = new Context(strategyA);
        context.algorithm();
    }
}

优点

1)易于扩展和维护。由于不同的算法被封装在不同的类中,所以我们可以很容易地添加新的算法或修改已有算法,而不需要修改客户端的代码。

2)提高代码的可读性。将不同的算法封装在不同的类中,使得代码更加模块化,易于理解和维护。

3)可以消除大量的条件语句。使用策略模式,我们可以将不同的算法替换成不同的类,从而消除大量的if-else语句,使得代码更加简洁和易于理解。

缺点

1)需要额外的类和接口。使用策略模式,我们需要为每个算法都创建一个独立的类,从而增加了代码的复杂度。

2)客户端需要知道所有的策略类。使用策略模式,客户端需要知道所有的策略类,以便在运行时选择合适的策略。这可能会增加代码的复杂度。

应用场景

1)需要根据不同的条件选择不同的算法时。例如,计算器程序需要根据用户输入的运算符选择相应的计算方法。

2)需要在运行时动态地选择算法时。例如,某个系统需要根据用户的配置或环境变量来选择合适的算法。

3)需要将算法的实现细节与客户端代码分离时。例如,某个系统需要根据不同的数据来源来解析数据,但是客户端并不关心数据的解析细节。

应用:策略模式优化if-else代码

package main.java.cn.test.strategy.V2;

/**
 * @author ningzhaosheng
 * @date 2023/6/11 14:34:56
 * @description 定义策略接口
 */
public interface AuditStrategy {
    // 判断条件是否匹配
    public boolean isSupport(LeaveForm leaveForm);

    // 审核业务逻辑
    public void audit(LeaveForm leaveForm);

    // 规则冲突优先级
    public int getPriority();

    // 规则名称
    public String getName();
}
package main.java.cn.test.strategy.V2;

/**
 * @author ningzhaosheng
 * @date 2023/6/11 14:35:56
 * @description 策略实现1
 */
public class AuditStrategyImpl_1 implements AuditStrategy{
    @Override
    public boolean isSupport(LeaveForm leaveForm) {
        return leaveForm.getDays() <= 3 && leaveForm.getType() == 1;
    }
    @Override
    public void audit(LeaveForm leaveForm) {
        System.out.println(leaveForm);
        System.out.println("三天以下婚丧假 无需审批自动通过!");
    }
    @Override
    public int getPriority() {
        return 0;
    }
    @Override
    public String getName() {
        return "三天以下婚假审批规则";
    }
}
package main.java.cn.test.strategy.V2;

/**
 * @author ningzhaosheng
 * @date 2023/6/11 14:36:32
 * @description 策略实现2
 */
public class AuditStrategyImpl_2 implements AuditStrategy{
    @Override
    public boolean isSupport(LeaveForm leaveForm) {
        return leaveForm.getDays() > 3 && leaveForm.getType() == 1;
    }
    @Override
    public void audit(LeaveForm leaveForm) {
        System.out.println(leaveForm);
        System.out.println("三天以上婚丧假 进入上级审批流程!");
    }
    @Override
    public int getPriority() {
        return 0;
    }
    @Override
    public String getName() {
        return "三天以上婚丧假审批规则";
    }
}
package main.java.cn.test.strategy.V2;

/**
 * @author ningzhaosheng
 * @date 2023/6/11 14:36:59
 * @description 策略实现3
 */
public class AuditStrategyImpl_3 implements AuditStrategy{
    @Override
    public boolean isSupport(LeaveForm leaveForm) {
        //级别9 总经理
        return leaveForm.getEmployee().getLevle().equals(9);
    }
    @Override
    public void audit(LeaveForm leaveForm) {
        System.out.println(leaveForm);
        System.out.println("总经理请假无需审批自动通过!");
    }
    @Override
    public int getPriority() {
        return 999;
    }
    @Override
    public String getName() {
        return "总经理请假审批规则";
    }
}
package main.java.cn.test.strategy.V2;

/**
 * @author ningzhaosheng
 * @date 2023/6/11 14:48:27
 * @description 策略实现4
 */
public class AuditStrategyImpl_4  implements AuditStrategy{
    @Override
    public boolean isSupport(LeaveForm leaveForm) {
        return leaveForm.getDays() > 3 && leaveForm.getType() == 0;
    }
    @Override
    public void audit(LeaveForm leaveForm) {
        System.out.println(leaveForm);
        System.out.println("三天以上病假 进入上级审批流程!");
    }
    @Override
    public int getPriority() {
        return 0;
    }
    @Override
    public String getName() {
        return "三天以上病假审批规则";
    }
}
package main.java.cn.test.strategy.V2;

/**
 * @author ningzhaosheng
 * @date 2023/6/11 14:49:19
 * @description 策略实现5
 */
public class AuditStrategyImpl_5 implements AuditStrategy{
    @Override
    public boolean isSupport(LeaveForm leaveForm) {
        return leaveForm.getDays() <= 3 && leaveForm.getType() == 0;
    }
    @Override
    public void audit(LeaveForm leaveForm) {
        System.out.println(leaveForm);
        System.out.println("三天以下病假 无需审批自动通过!");
    }
    @Override
    public int getPriority() {
        return 0;
    }
    @Override
    public String getName() {
        return "三天以下病假假审批规则";
    }
}
package main.java.cn.test.strategy.V2;

import java.util.ArrayList;
import java.util.List;

/**
 * @author ningzhaosheng
 * @date 2023/6/11 14:39:21
 * @description 策略工厂
 */
public class AuditStrategyFactory {
    //私有静态全局唯一 工厂对象
    private final static AuditStrategyFactory factory = new AuditStrategyFactory();
    //使用集合存储策略信息
    private List<AuditStrategy> auditStrategyList = new ArrayList<>();
    //私有构造,用于注册规则
    private AuditStrategyFactory(){
        auditStrategyList.add(new AuditStrategyImpl_1());
        auditStrategyList.add(new AuditStrategyImpl_2());
        auditStrategyList.add(new AuditStrategyImpl_3());
        auditStrategyList.add(new AuditStrategyImpl_4());
        auditStrategyList.add(new AuditStrategyImpl_5());
    }
    //全局访问点 获取单例对象
    public static AuditStrategyFactory getInstance(){
        return factory;
    }
    //获取匹配的策略
    public AuditStrategy getAuditStrategy(LeaveForm leaveForm){
        AuditStrategy auditStrategy = null;
        for (AuditStrategy strategy : auditStrategyList) {
            //找到匹配的规则
            if(strategy.isSupport(leaveForm)){
                if(auditStrategy == null){
                    auditStrategy = strategy;
                }else{
                    //优先级高的规则 替换现有的规则
                    //例如: 总经理请病假10,总经理优先级999,普通员工0

                    if(strategy.getPriority() > auditStrategy.getPriority()){
                        auditStrategy = strategy;
                    }
                }
            }
        }
        if(auditStrategy == null){
            throw new RuntimeException("没有匹配到请假审核规则");
        }else{
            return auditStrategy;
        }
    }
}
package main.java.cn.test.strategy.V2;

/**
 * @author ningzhaosheng
 * @date 2023/6/11 14:40:03
 * @description 策略工厂上下文
 */
public class LeaveServiceNew {
    public void audit(LeaveForm leaveForm){
        AuditStrategyFactory factory = AuditStrategyFactory.getInstance();
        //返回符合条件的策略
        AuditStrategy strategy = factory.getAuditStrategy(leaveForm);
        //通过策略类进行审核
        strategy.audit(leaveForm);
    }
}
package main.java.cn.test.strategy.V2;

/**
 * @author ningzhaosheng
 * @date 2023/6/11 14:33:53
 * @description 员工类
 */
public class Employee {


    private String name; // 姓名
    private Integer levle; // 级别

    public Employee(String name,Integer levle){
        this.name = name;
        this.levle = levle;
    }
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getLevle() {
        return levle;
    }

    public void setLevle(Integer levle) {
        this.levle = levle;
    }
}
package main.java.cn.test.strategy.V2;

/**
 * @author ningzhaosheng
 * @date 2023/6/11 14:34:29
 * @description 请假实体
 */
public class LeaveForm {
    private Employee employee;//员工对象
    private String reason;//请假原因
    private int days;//天数
    private int type; //类型 0-病假 1-婚丧假 2-年假

    public LeaveForm(Employee employee,String reason,int days,int type){
       this.employee = employee;
       this.reason = reason;
       this.days = days;
       this.type = type;
    }
    public Employee getEmployee() {
        return employee;
    }

    public void setEmployee(Employee employee) {
        this.employee = employee;
    }

    public String getReason() {
        return reason;
    }

    public void setReason(String reason) {
        this.reason = reason;
    }

    public int getDays() {
        return days;
    }

    public void setDays(int days) {
        this.days = days;
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }
}
package main.java.cn.test.strategy.V2;

/**
 * @author ningzhaosheng
 * @date 2023/6/11 14:40:26
 * @description 测试类
 */
public class Client {
    public static void main(String[] args) {
        LeaveServiceNew leaveServiceNew = new LeaveServiceNew();
        LeaveForm form1 = new LeaveForm(new Employee("李总经理", 9), "甲流发烧", 10, 0);
        leaveServiceNew.audit(form1);
        LeaveForm form2 = new LeaveForm(new Employee("打工人1", 2), "甲流发烧", 2, 0);
        leaveServiceNew.audit(form2);
        LeaveForm form3 = new LeaveForm(new Employee("打工人2", 3), "结婚", 2, 1);
        leaveServiceNew.audit(form3);
        LeaveForm form4 = new LeaveForm(new Employee("打工人3", 4), "请年假,休息休息", 5, 2);
        leaveServiceNew.audit(form4);
    }
}

执行结果:

 经过上面的改造,我们已经消除了if-else的结构,每当新来了一种请假规则,只需要添加新的规则处理策略,并修改Factory中的集合。如果要使得程序符合开闭原则,则需要调整Factory中处理策略的获取方式,通过反射的方式,获取指定包下的所有Strategy实现类,然后放到字典集合中去.

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值