java策略模式(代码片段)

小女子不才~~ 小女子不才~~     2022-10-24     379

关键词:

Java 策略模式

前记:欠下的迟早是要还的~~~还债第四篇~

需求

跟以前一样,先说需求:最近公司要做一个小商城,商城里的产品有不同的销售价格,有得是原价,有的是打7折的,有的是打5折的。

代码展示

如果需求一直不变,最简单粗暴的写法是这样的:

package signModel.strategy;
/**
 * @description:最简单粗暴的写法
 * @see:signModel.strategy.simpleFactory
 * @createTime:2021/8/9 17:10
 * @version:1.0
 */
public class simple 
    public static void main(String[] args) 
        String type="7折";
        double money = 100.0;  //总价
        double rs=  getResultAmt( type,money);
    
    private static double getResultAmt(String type, double money) 
        double result=0;
        switch (type)
            case "原价":
                return money;
            case "7折":
                return money*0.7;
            case "5折":
                return money*0.5;
        
        return result;
    


这种简单粗暴的写法,会带来一系列的麻烦,假如现在要增加一个打8折,就需要继续增加一个case,这样打5折,打7折,打8折的代码其实是一样的,重复代码很多。可以给提出来一个打折的函数,另外如果要增加一个满减的新需求,满200-20,这样的话,满400就得减40,这个满减就不能在case里写了,这个得写个函数才好使。
加上满减以后,计算价格的方法就会分为3类,原价,打折,满减。
上次的设计模式讲的是简单工厂模式,碰到这种,首先想到可以用来消除代码种的case和if-else.所以这里我们也用简单工厂测试来进行改造。简单工厂模式呢就是先写一个计算金额的抽象类,子类重写父类的计算金额的方法。另外还需要一个工厂类。
直接上代码:

/**
 * @description:简单工厂模式抽象父类
 * @see:signModel.strategy.simpleFactory
 * @createTime:2021/8/9 17:35
 * @version:1.0
 */
public abstract class CashSuper 
    public  abstract double geTotalCash(double money);


/**
 * @description:子类-原价商品
 * @see:signModel.strategy.simpleFactory
 * @createTime:2021/8/9 17:37
 * @version:1.0
 */
public class Normal extends CashSuper 

    @Override
    public double geTotalCash(double money) 
        return money;
    



/**
 * @description:子类2-打折商品
 * @see:signModel.strategy.simpleFactory
 * @createTime:2021/8/9 18:18
 * @version:1.0
 */
public class Rebate extends CashSuper 
    private double rebate; //几折
    public Rebate(double rebate) 
        this.rebate = rebate;
    
    @Override
    public double geTotalCash(double money) 
        return money* rebate/10;
    
    public double getRebate() 
        return rebate;
    
    public void setRebate(double rebate) 
        this.rebate = rebate;
    



/**
 * @description:子类-满减方法类
 * @see:signModel.strategy.simpleFactory
 * @createTime:2021/8/9 18:21
 * @version:1.0
 */
public class FullMinus extends CashSuper 
    private  double fullMoney;
    private double minusMoney;

    public FullMinus(double fullMoney, double minusMoney) 
        this.fullMoney = fullMoney;
        this.minusMoney = minusMoney;
    
    @Override
    public double geTotalCash(double money) 
        if(money>=fullMoney)
            return money-Math.floor(money/this.fullMoney)*minusMoney;
        
        return money;
    
    public double getMinusMoney() 
        return minusMoney;
    
    public void setMinusMoney(double minusMoney) 
        this.minusMoney = minusMoney;
    


/**
 * @description:
 * @see:signModel.strategy.simpleFactory
 * @createTime:2021/8/9 18:36
 * @version:1.0
 */
public class CashFactory 
    public static CashSuper getCash(String type)
        CashSuper cashSuper=null;
        switch (type)
            case "7折":
                cashSuper=new Rebate(7.0);
                break;
            case "满减":
                cashSuper= new FullMinus(300.0,20.0);
                break;
            case "原价":
                cashSuper=new Normal();
        
        return cashSuper;
    



/**
 * @description:测试主类,可直接运行看效果
 * @see:signModel.strategy.simpleFactory
 * @createTime:2021/8/9 18:42
 * @version:1.0
 */
public class Main 

    public static void main(String[] args) 
        double money = 300.0;  //总价

        String type="7折";
        CashSuper cash = CashFactory.getCash(type);
        double result = cash.geTotalCash(money);
        System.out.println("打7折的价格:"+result);

        String type1="满减";
        CashSuper cashSuper=CashFactory.getCash(type1);
        double totalCash = cashSuper.geTotalCash(money);
        System.out.println(totalCash);

    


代码测试运行结果:

策略模式

以上是使用简单工厂模式的完成的写法,现在我们转换到主题策略模式上来,首先说一下什么是策略模式:
大话设计模式种对策略模式的定义:它定义了算法家族,分别封装起来,让他们直接可以相互替换,此模式让算法的变化,不会影响到使用算法的客户。
在上边的例子中,商场的促销方式,无论是打折还是促销,其实都是一些算法,用工厂来生成算法对象,这也是可以的,但是算法本身只是一种策略,最重要是的是这些算法是随时都可能相互替换的,这就是变化点,封装变化点是我们面向对象编程的一种很重要的思维方式。现在来看看策略模式的基本结构:
首先上一下UML图,一目了然:

介绍下上边图中的各个角色:
抽象策略角色(Strategy类):这是一个抽象角色,通常由一个接口或者抽象类实现。此角色给出所有的具体策略类所需的接口。
具体策略角色(StrategyNormal,StrategyRebate,StrategyFullMunus类,即Strategy类的子类):包含了具体的算法和行为。
环境角色类(Context类):持有一个Strategy类的引用。
下边是使用策略模式实现的需求的代码:

/**
 * @description:策略类,定义所有支持算法的公共接口
 * @see:signModel.strategy.strategy
 * @createTime:2021/8/10 10:36
 * @version:1.0
 */
public abstract class Strategy 
    public  abstract double geTotalCash(double money);


/**
 * @description:具体策略1-正常算法
 * @see:signModel.strategy.strategy
 * @createTime:2021/8/10 10:39
 * @version:1.0
 */
public class StrategyNormal extends Strategy 
    @Override
    public double geTotalCash(double money) 
        return money;
    


/**
 * @description:具体策略2-打折算法类
 * @see:signModel.strategy.strategy
 * @createTime:2021/8/10 10:40
 * @version:1.0
 */
public class StrategyRebate extends Strategy 
    private double rebate; //几折

    //有参构造
    public StrategyRebate(double rebate) 
        this.rebate = rebate;
    

    @Override
    public double geTotalCash(double money) 
        return money* rebate/10;
    

    public double getRebate() 
        return rebate;
    

    public void setRebate(double rebate) 
        this.rebate = rebate;
    



/**
 * @description:具体策略3-满减算法
 * @see:signModel.strategy.strategy
 * @createTime:2021/8/10 10:42
 * @version:1.0
 */
public class StrategyFullMinus extends Strategy 
    private  double fullMoney;
    private double minusMoney;

    public StrategyFullMinus(double fullMoney, double minusMoney) 
        this.fullMoney = fullMoney;
        this.minusMoney = minusMoney;
    

    @Override
    public double geTotalCash(double money) 
        if(money>=fullMoney)
            return money-Math.floor(money/this.fullMoney)*minusMoney;
        
        return money;
    

    public double getMinusMoney() 
        return minusMoney;
    

    public void setMinusMoney(double minusMoney) 
        this.minusMoney = minusMoney;
    


/**
 * @description:环境上下文角色-维护一个对Strategy类的引用
 * @see:signModel.strategy.strategy
 * @createTime:2021/8/10 10:48
 * @version:1.0
 */
public class Context 
    private Strategy strategy;
    //有参构造,直接传入具体的算法对象
   
    //调用策略种的具体方法并返回结果。
    public double runMethod(double money)
        double cash = this.strategy.geTotalCash(money);
        return cash;
    



测试主类:
/**
 * @description:测试主类
 * @see:signModel.strategy.strategy
 * @createTime:2021/8/10 10:56
 * @version:1.0
 */
public class Main 
    public static void main(String[] args) 
        double money = 300.0;  //总价

        String type="7折";
        double rs=  getResultAmt( type,money);
        System.out.println("打7折后的总价格:"+rs);

        String type1="满减";
        double rs1=  getResultAmt( type1,money);
        System.out.println("满减后的总价格:"+rs1);
    
    private static double getResultAmt(String type, double money) 
        Context context = null;
        switch (type) 
            case "原价":
                context = new Context(new StrategyNormal());
                break;
            case "7折":
                context = new Context(new StrategyRebate(7.0));
                break;
            case "满减":
                context = new Context(new StrategyFullMinus(300.0,20));
                break;
        
        return context.runMethod(money);
    


运行结果:

策略模式+简单工厂

当然了,这样写,你会发现,测试主类里又写了一堆switch-case语句,只是把算法这部分给提了出来,看上去不如简单工厂模式封装的好。既然这样,那我们把简单工厂模式和策略模式给结合一下,把switch-case 这部分代码放到Context类中,这样,Context代码和测试主类代码如下:

/**
 * @description:环境上下文角色-维护一个对Strategy类的引用
 * @see:signModel.strategy.strategy
 * @createTime:2021/8/10 10:48
 * @version:1.0
 */
public class Context 
    private Strategy strategy;
    //有参构造,直接传入具体的算法对象
    public  Context(String type) 
        switch (type) 
            case "原价":
                this.strategy = new StrategyNormal();
                break;
            case "7折":
                this.strategy = new StrategyRebate(7.0);
                break;
            case "满减":
                this.strategy =new StrategyFullMinus(300.0,20);
                break;
        
    
    //调用策略种的具体方法并返回结果。
    public double runMethod(double money)
        double cash = this.strategy.geTotalCash(money);
        return cash;
    


测试主类:
/**
 * @description:测试主类
 * @see:signModel.strategy.strategy
 * @createTime:2021/8/10 10:56
 * @version:1.0
 */
public class Main 
    public static void main(String[] args) 
        double money = 300.0;  //总价

        String type="7折";
        Context context=new Context(type);
        double rs= context.runMethod(money);
        System.out.println("打7折后的总价格:"+rs);

        String type1="满减";
        Context context1=new Context(type1);
        double method = context1.runMethod(money);
        System.out.println("满减后的总价格:"+method);
    


策略模式是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类直接的耦合。策略模式的优点就是:一方面Strategy类层次为Context定义了一系列的可供重用的算法或行为。继承有助于提取出这些算法种的公共功能。另一方面就是简化了单元测试,因为每个算法都有自己的类,可以通过自己的算法单独测试。
策略模式就是用来封装算法的,但在实践中,我们发现可以用他来封装几乎任何类型的规则,只要在分析的过程中听到在不同时间应用不用的业务规则,就可以考虑使用策略模式处理这种变化的可能性。上面的需求在使用策略模式以后,如果想要增加新的促销模式,只需加一个算法类,改动一下Context类的构造方法即可。有新需求是肯定要改动的,使用策略模式会降低改动成本。这也是策略模式的好处之一了。

设计模式不光是纸上谈兵,要分析需求,根据需求使用对应的设计模式。

后记:天道好轮回,苍天饶过谁~~~,欠下的迟早是要还的~~

java策略模式(代码片段)

Java策略模式需求代码展示策略模式策略模式+简单工厂前记:欠下的迟早是要还的~~~还债第四篇~需求跟以前一样,先说需求:最近公司要做一个小商城,商城里的产品有不同的销售价格,有得是原价,... 查看详情

java策略模式(代码片段)

Java策略模式需求代码展示策略模式策略模式+简单工厂前记:欠下的迟早是要还的~~~还债第四篇~需求跟以前一样,先说需求:最近公司要做一个小商城,商城里的产品有不同的销售价格,有得是原价,... 查看详情

设计模式中的多态——策略模式详解(代码片段)

目录1.关于策略模式2.策略模式详解2.1策略模式定义2.2策略模式的UML类图3.策略模式的优点3.1一个使用策略模式的例子3.2与其他实现方式的对比3.3使用策略模式的优点4.使用工厂方法模式改进原有策略模式5.总结5.参考资料1.关于策... 查看详情

java使用函数式接口处理if-else的策略模式(代码片段)

目录常规策略模式示例函数式接口策略定义函数方法函数策略调用常规策略模式示例publicabstractclassStrategyabstractvoiddoSomething();//策略ApublicclassAStrategyextendsStrategy@OverridevoiddoSomething()//策略BpublicclassBStrategyextendsStrategy 查看详情

java策略模式之总有你想不到的知识(代码片段)

文章目录策略模式概念代码示例优缺点策略模式优点策略模式缺点应用场景综合实战:多个算法切换策略模式概念策略模式(StrategyPattern)也叫政策模式,是一种比较简单的模式。它的目的是定义一组算法,... 查看详情

day321.策略模式&职责链模式-java设计模式(代码片段)

策略模式将原本继承的方式,换成组合、聚合,让算法变化(策略)与算法客户(对象)分离一、编写鸭子项目,具体要求如下:1)有各种鸭子(比如野鸭、北京鸭、水鸭等,鸭子有各种行为,比如叫、飞行等)2)显示鸭... 查看详情

设计模式系列——策略模式(代码片段)

...关注JAVA基础编程及大数据,注重经验分享及个人成长。策略模式常用于一个对象的行为在运行时有多个不同的策略和算法。举个例子可以通过实现一个加、减、乘三种不用策略的运算,通过该示例演示策略模式。先来看一下UML... 查看详情

java设计模式——策略模式(代码片段)

1、简介策略模式(StrategyPattern)是一种比较简单的模式,也叫做政策模式(PolicyPattern)。其定义如下:Defineafamilyofalgorithms,encapsulateeachone,andmaketheminterchangeable.(定义一组算法,将每个算法都封装起来,并且使它们之间可以互... 查看详情

java策略模式(代码片段)

Java策略模式需求代码展示策略模式策略模式+简单工厂前记:欠下的迟早是要还的~~~还债第四篇~需求跟以前一样,先说需求:最近公司要做一个小商城,商城里的产品有不同的销售价格,有得是原价,... 查看详情

第一梦策略模式(代码片段)

写在之前这篇博客是自己开始Java设计模式系统学习之路记录,以前学习都是零零散散的,很多东西都是不常用就慢慢忘记了。为了跳出怪圈,也对学习过的知识整理成册,避免反复学习,让我们开始吧!--------------------------------... 查看详情

java中的设计模式(代码片段)

...计模式的时候,最好能够结合源码来进行理解,逼格更高策略模式泛型接口比较实用的使用场景就是用作策略模式的公共策略,比如 Java解惑:Comparable和Comparator的区别 中介绍的Comparator,它就是一个泛型接口 迭代器... 查看详情

java设计模式之策略学习与掌握(代码片段)

文章目录前言定义优点缺点模式的结构与实现模式的结构模式的实现应用场景前言个人建议设计模式这一系列的文章,多关注定义和模式的代码实现。至于模式结构和扩展或者是应用场景,基本了解过一下就好,没必... 查看详情

java嵌套ifelse优化(代码片段)

文章目录1.传统实现2.策略模式+工厂模式+单例模式优化2.1策略接口2.2不同策略实现类2.2.1处理策略一2.2.2处理策略二2.2.3处理策略三2.2.4处理策略四3.策略工厂4.使用5.参考资料多分支复杂条件嵌套判断会让逻辑变得更加复杂&#... 查看详情

从零开始学习java设计模式|行为型模式篇:策略模式(代码片段)

...们来学习一下行为型模式里面的第二个设计模式,即策略模式。概述先看下面的图片,我们去旅游选择出行方式能有很多种,可以骑自行车、可以坐汽车、可以坐火车、可以坐飞机。作为一个程序猿,开发需要选... 查看详情

从零开始学习java设计模式|行为型模式篇:策略模式(代码片段)

...们来学习一下行为型模式里面的第二个设计模式,即策略模式。概述先看下面的图片,我们去旅游选择出行方式能有很多种,可以骑自行车、可以坐汽车、可以坐火车、可以坐飞机。作为一个程序猿,开发需要选... 查看详情

代码片-策略模式+工厂模式(代码片段)

通过策略类实现不同场景的策略处理,通过工厂模式创建不同的策略对象1.策略实现接口、策略实现类1.1策略接口/***策略接口*/publicinterfaceIWarnRulepublicvoidwarn();1.2策略实现类/***防拆告警策略实现类*/publicclassAntiRemovalWarnimplements... 查看详情

代码片-策略模式+工厂模式(代码片段)

通过策略类实现不同场景的策略处理,通过工厂模式创建不同的策略对象1.策略实现接口、策略实现类1.1策略接口/***策略接口*/publicinterfaceIWarnRulepublicvoidwarn();1.2策略实现类/***防拆告警策略实现类*/publicclassAntiRemovalWarnimplements... 查看详情

代码片-策略模式+工厂模式(代码片段)

通过策略类实现不同场景的策略处理,通过工厂模式创建不同的策略对象1.策略实现接口、策略实现类1.1策略接口/***策略接口*/publicinterfaceIWarnRulepublicvoidwarn();1.2策略实现类/***防拆告警策略实现类*/publicclassAntiRemovalWarnimplements... 查看详情