zoukankan      html  css  js  c++  java
  • 设计模式与代码的结构特性

    策略模式

      策略模式是对算法的包装,把使用算法的责任和算法本身分隔开,委派给不同的对象管理。策略模式通常把一系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类。比如我们去逛商场,商场现在正在搞活动,有打折的、有满减的、有返利的等等,其实不管商场如何进行促销,说到底都是一些算法,这些算法本身只是一种策略,并且这些算法是随时都可能互相替换的。  

    1. 何时使用

    • 一个系统有许多类,而区分它们的只是他们直接的行为时

    2. 方法

    • 将这些算法封装成一个一个的类,任意的替换

    3. 优点

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

    4. 缺点

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

    以商场促销为例使用策略模式实现商场促销算法。UML图如下:

    1. CashContext类

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

    public class CashContext {
        
        private CashSuper cashSuper;
        
        public CashContext(CashSuper cashSuper) {
            this.cashSuper = cashSuper;
        }
        
        public double getResult(double money) {
            return cashSuper.acceptCash(money);
        }
    
    }

    2. CashSuper类

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

    public abstract class CashSuper {
       
         public abstract double acceptCash(double money);
     
     }

    3. 三类收费子类

    public class CashNormal extends CashSuper {
    
        public double acceptCash(double money) {
            return money;
        }
    
    }
    
    
    public class CashRebate extends CashSuper {
        
        private double moneyRebate = 1;    //折扣
        
        public CashRebate(double moneyRebate) {
            this.moneyRebate = moneyRebate;
        }
    
        public double acceptCash(double money) {
            return money * moneyRebate;
        }
    
    }
    
    
    public class CashReturn extends CashSuper {
    
        private double moneyConditation = 0.0;    //返利条件
        private double moneyReturn = 0.0d;    //返利值
        
        public CashReturn(double moneyConditation, double moneyReturn) {
            this.moneyConditation = moneyConditation;
            this.moneyReturn = moneyReturn;
        }
    
        public double acceptCash(double money) {
            double result = money;
            
            if (money >= moneyConditation) {
                result = money - Math.floor(money / moneyConditation) * moneyReturn;
            }
            
            return result;
        }
    
    }

    4. 测试类测试结果

    public class Client {
        
        public static void main(String[] args) {
            CashContext cashContext = null;
            
            Scanner scanner = new Scanner(System.in);
            System.out.print("请输入打折方式(1/2/3):");
            int in = scanner.nextInt();
            String type = "";
            
            switch (in) {
                case 1:
                    cashContext = new CashContext(new CashNormal());
                    type += "正常收费";
                    break;
                    
                case 2:
                    cashContext = new CashContext(new CashReturn(300, 100));
                    type += "满300返100";
                    break;
                    
                case 3:
                    cashContext = new CashContext(new CashRebate(0.8));
                    type += "打8折";
                    break;
        
                default:
                    System.out.println("请输入1/2/3");
                    break;
            }
            
            double totalPrices = 0;
            
            System.out.print("请输入单价:");
            double price = scanner.nextDouble();
            System.out.print("请输入数量:");
            double num = scanner.nextDouble();
            totalPrices = cashContext.getResult(price * num);
            
            System.out.println("单价:" + price + ",数量:" + num + ",类型:" + type + ",合计:" + totalPrices);
            
            scanner.close();
        }
    
    }

    以输入2例输出结果

    总结

    使用场景

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

    应用实例

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

    注意事项

    • 如果一个系统的策略多于四个,就需要考虑使用混合模式来解决策略类膨胀的问题
  • 相关阅读:
    Windows 7的 磁盘管理中,某个磁盘或分区,突然变成只读。
    Python 静态变量 与 静态方法
    如何用手机上网给电信固话充值
    Windows,查看进程的连接的IP地址,批量模式,最后做成Excel
    如果在VMware上免费下载驱动
    DELL iDRAC 远程虚拟机报错:虚拟介质分离或所选虚拟磁盘驱动器的虚拟介质重定向已由另一用户使用
    Windows Server 2008安装 百度Wifi 360Wifi 小米Wifi 失败的解决方法
    让Windows 8 / 8.1 以及 Windows Server 2012 / 2012 R2的桌面,显示我的电脑图标
    让Windows 8 / 8.1 以及 Windows Server 2012 / 2012 R2的任务管理器的性能面板,显示磁盘数据
    企业CIO、CTO必读的34个经典故事
  • 原文地址:https://www.cnblogs.com/H1K777/p/12006884.html
Copyright © 2011-2022 走看看