Java设计模式之“策略模式”

今天学习多线程的时候,了解到多线程的Thread和Runnable中都有策略模式的提现,所以特意学了一下策略模式。

策略模式的三个组成部分分别为:抽象策略角色、具体策略角色、环境角色(策略类的实例作为环境角色的成员变量)

翻译成我们容易理解的对应关系就是

抽象策略角色:接口

具体策略角色:接口实现类

环境角色:调用接口的类(里面必须有一个类型为抽象策略角色的成员变量)

概念:策略模式就是事先准备好一系列算法,这些算法之间可以相互代替,且算法与调用的客户端相互独立。


话不多说,直接上代码,至于策略模式的优缺点,先读完下面的代码再谈更容易理解

代码模拟场景:计算每月工资和奖金需要纳税的总金额

/**
 * 抽象策略角色
 * @Date: 2019/4/16 14:44
 */
public interface TaxCount {

    double count(double salary,double bouns);

}
/**
 * 具体策略角色(策略类)
 * @Date: 2019/4/16 14:51
 */
public class SimpleTaxCount implements TaxCount{

    //工资纳税1%
    private static final double SALARY_RATE = 0.1;
    //奖金纳税1.5%
    private static final double BOUNS_RATE = 0.15;

    @Override
    public double count(double salary, double bouns) {
        //计算
        return salary * SALARY_RATE + bouns * BOUNS_RATE;
    }
}
/**
 * 环境角色(包含策略类的成员变量)
 * @Date: 2019/4/16 15:53
 */
public class TaxCountDo {

    private final double salary;

    private final double bouns;

    private TaxCount taxCount;

    public TaxCountDo(double salary, double bouns, TaxCount taxCount) {
        this.salary = salary;
        this.bouns = bouns;
        this.taxCount = taxCount;
    }

    //对外暴露
    public double count(){
        //调用自己的计算方法
        return this.do_count();
    }

    private double do_count(){
        //调用成员变量(具体策略角色)的计算方法
        return taxCount.count(this.salary,this.bouns);
    }
}
/**
 * 测试
 * @Date: 2019/4/16 15:57
 */
public class TaxCountTest {

    public static void main(String[] args) {
        //计算工资10000奖金2000需要纳税多少元
        TaxCountDo taxCount = new TaxCountDo(10000,2000,new SimpleTaxCount());
        double count = taxCount.count();
        System.out.println("需纳税:"+count+"元");
    }
}

 好,到这里,我们运行测试类就能够计算出我们想要的结果了,如图:

上面的代码已经实现了策略模式,所以我们现在变更一下需求,来体验一下策略模式的优点。

现在需求要变更为:

普通员工纳税标准不变;

对特殊员工特殊照顾,纳税标准为(工资 * 0.1 + 奖金 * 0.15 -  (工资 + 奖金) *  0.02)* 0.8,

按照新需求,我们不需要改动之前的任何算法,只需要新增具体策略角色,也就是TaxCount 接口的新实现类

/**
 * 具体策略角色(策略类)
 * @Date: 2019/4/16 14:51
 */
public class SimpleTaxCount_update implements TaxCount{

    private static final double SALARY_RATE = 0.1;
    private static final double BOUNS_RATE = 0.15;

    private static final double EXTRA_RATE = 0.02;
    private static final double PERCENT = 0.8;


    @Override
    public double count(double salary, double bouns) {

        return (salary * SALARY_RATE + bouns * BOUNS_RATE - ((salary + bouns) * EXTRA_RATE)) * PERCENT;
    }
}

环境角色不需要进行任何修改,只需要在客户端调用的时候改变具体策略角色,如下

/**
 * 测试
 * @Date: 2019/4/16 15:57
 */
public class TaxCountTest {

    public static void main(String[] args) {
        //计算工资10000奖金2000需要纳税多少元
        TaxCountDo taxCount = new TaxCountDo(10000,2000,new SimpleTaxCount());
        double count = taxCount.count();
        System.out.println("普通员工需纳税:"+count+"元");

        TaxCountDo taxCount_update = new TaxCountDo(10000,2000,new SimpleTaxCount_update());
        double count_update = taxCount_update.count();
        System.out.println("特殊员工需纳税"+count_update+"元");
    }
}

为了形成对比,所以测试类里两种纳税方式我都有调用。


谈谈优劣

使用了策略模式,我们就可以根据自己特定的业务需求,在客户端引用与业务需求相符的具体策略角色,实现最终效果。 如果某天业务需求有变动,我们不需要对代码大量改动,只需要新增一个与我们业务需求相符的具体策略角色, 在客户端调用环境角色的时候,将我们新增的具体策略角色作为环境角色的成员变量传入,就能实现调整后的业务需求最终实现效果。 但是这种模式也存在缺点,当我们的业务需求过于复杂,需要的算法很多的时候,我们就需要写大量的具体策略角色,造成项目过于臃肿。

今日小感想:只要学习,总会有意外惊喜。今天的策略模式算是个意外收获。很开心。

猜你喜欢

转载自blog.csdn.net/Peacock__/article/details/89336256