zoukankan      html  css  js  c++  java
  • 设计模式(二十一)策略模式

    1、策略模式(Strategy):定义了一组算法,将每个算法都封装其类,并且使他们之间可以互换。

    2、UML结构图如下:

                                                                 

       其中,Context是上下文,用一个ConcreteStrategy来配置,维护一个对Strategy对象的引用;Strategy是策略类,用于定义所有支持算法的公共接口;ConcreteStrategy是具体策略类,封装了具体的算法或行为,继承于Strategy。

    3、使用场景

    •  多个类只有算法或行为上稍有不同的场景;
    • 算法需要自由切换的场景;
    • 需要屏蔽算法规则的场景。

    4、优缺点

    优点

    • 算法可以自由切换;
    • 避免使用多重条件判断(如果不用策略模式我们可能会使用多重条件语句,不利于维护);
    • 扩展性良好,增加一个策略只需实现接口即可。

    缺点

    • 策略类数量会增多,每个策略都是一个类,复用的可能性很小;
    • 所有的策略类都需要对外暴露。

    5、应用实例

    • 商场促销方式,打折、满减等;
    • 出行方式,自行车、汽车等,每一种出行方式都是一个策略;
    • Java AWT中的LayoutManager,即布局管理器。

    6、注意事项

    • 如果一个系统的策略多于四个,就需要考虑使用混合模式来解决策略类膨胀的问题。

    7、代码实例

    (1)上下文类

      首先声明一个CashSuper对象,通过构造方法,传入具体的收费策略,getResult()方法的功能为根据收费策略的不同获得计算结果。

     1 /**
     2  * @author it-小林
     3  * @desc   上下文类
     4  * @date 2021年09月28日 9:57
     5  */
     6 public class CashContext {
     7 
     8     private CashSuper cashSuper;
     9 
    10     public CashContext(CashSuper cashSuper) {
    11         this.cashSuper = cashSuper;
    12     }
    13 
    14     public double getResult(double money){
    15         return cashSuper.acceptCash(money);
    16     }
    17 }

    (2)现金收费抽象类

      策略类,为抽象类,抽象出收费的方法供子类实现。

     1 /**
     2  * @author it-小林
     3  * @desc   现金收费抽象类
     4  * @date 2021年09月28日 9:46
     5  */
     6 public abstract class CashSuper {
     7 
     8     public abstract double acceptCash(double money);
     9 
    10 }

    (3)正常收费子类

      没有任何活动的情况,正常收费,返回原价。

     1 /**
     2  * @author it-小林
     3  * @desc   正常收费子类
     4  * @date 2021年09月28日 9:48
     5  */
     6 public class CashNormal extends CashSuper{
     7 
     8 
     9     @Override
    10     public double acceptCash(double money) {
    11         return money;
    12     }
    13 }

     

    (4)打折收费子类

      打折活动,根据折扣返回打折后的价格。

     1 /**
     2  * @author it-小林
     3  * @desc   打折收费子类
     4  * @date 2021年09月28日 9:49
     5  */
     6 public class CashRebate extends CashSuper {
     7 
     8     private double moneyRebate = 1; //折扣
     9 
    10     public CashRebate(double moneyRebate) {
    11         this.moneyRebate = moneyRebate;
    12     }
    13 
    14     @Override
    15     public double acceptCash(double money) {
    16         return money * moneyRebate;
    17     }
    18 }

     (5)返利收费子类

    返利活动,输入返利条件和返利值,比如满300返100,moneyCoditation为300,moneyReturn为100。

       result = money - Math.floor(money / moneyConditation) * moneyReturn; 的意思为,如果当前金额大于等于返利条件,则使用当前金额减去返利值。

     1 /**
     2  * @author it-小林
     3  * @desc   返利收费子类
     4  * @date 2021年09月28日 9:53
     5  */
     6 public class CashReturn extends CashSuper {
     7 
     8     private double moneyConditation = 0.0;  //返利条件
     9     private double moneyReturn = 0.0d;      //返利值
    10 
    11     public CashReturn(double moneyConditation, double moneyReturn) {
    12         this.moneyConditation = moneyConditation;
    13         this.moneyReturn = moneyReturn;
    14     }
    15 
    16     @Override
    17     public double acceptCash(double money) {
    18         double result = money;
    19         if(money >= moneyConditation){
    20             result = money - moneyReturn;
    21         }
    22         return result;
    23     }
    24 }

    (6)测试类

     1 /**
     2  * @author it-小林
     3  * @desc   客户端
     4  * @date 2021年09月28日 9:58
     5  */
     6 public class Client {
     7     public static void main(String[] args) {
     8         CashContext context = null;
     9 
    10         Scanner scanner = new Scanner(System.in);
    11         System.out.println("请输入打折方式(1/2/3):");
    12         int in = scanner.nextInt();
    13         String type = "";
    14 
    15         switch (in) {
    16             case 1:
    17                 context = new CashContext(new CashNormal());
    18                 type += "正常收费";
    19                 break;
    20             case 2:
    21                 context = new CashContext(new CashReturn(300, 200));
    22                 type += "满300返100";
    23                 break;
    24             case 3:
    25                 context = new CashContext(new CashRebate(0.8));
    26                 type += "打8折";
    27                 break;
    28             default:
    29                 System.out.println("请输入1/2/3");
    30                 break;
    31         }
    32 
    33         double totalPrices = 0;
    34         System.out.print("请输入单价:");
    35         double price = scanner.nextDouble();
    36         System.out.print("请输入数量:");
    37         double num = scanner.nextDouble();
    38         totalPrices = context.getResult(price * num);
    39         System.out.println("单价:" + price + ",数量:" + num + ",类型:" + type + ",合计:" + totalPrices);
    40     }
    41 }

    运行结果

                                                                

                                                                

                                                                

    如本文有侵权行为,请及时与本人联系,多多包涵! 小生初出茅庐,多多指教!

    本文来自博客园,作者:it-小林,转载请注明原文链接:https://www.cnblogs.com/linruitao/p/15067877.html

  • 相关阅读:
    XAMPP配置8080端口
    Composer安装使用
    .Net商品管理(注释,百度,提问,对比,总结)
    .Net数据库操作
    VS链接数据库
    .Net中字典的使用
    一套解决方案,多个项目
    转化一下解决问题的思路,弯道超车
    灵活的运用Model类
    Razor数组数据
  • 原文地址:https://www.cnblogs.com/linruitao/p/15067877.html
Copyright © 2011-2022 走看看