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,即布局管理器

    注意事项

    • 如果一个系统的策略多于四个,就需要考虑使用混合模式来解决策略类膨胀的问题
  • 相关阅读:
    Java学习笔记——动态代理
    Java学习随笔——RMI
    数据结构与算法——排序算法
    设计模式——装饰者模式
    Struts2中使用execAndWait后,在 Action中调用getXXX()方法报告java.lang.NullPointerException异常的原因和解决方法
    vs中debug的一个小技巧 -- debug时忽略某段代码
    SilverlightMVVM模式中的数据校验
    技能图谱
    MQ队列管理器损坏的处理方法
    informix数据库锁表处理方法
  • 原文地址:https://www.cnblogs.com/H1K777/p/12006884.html
Copyright © 2011-2022 走看看