• 策略模式


    在说明策略模式之前,先看一个打折促销的例子

    一家超市进行打折促销:促销形式分别有:“打8折”和“满300减100”,该怎么实现?

    用简易的工厂模式:

    创建收费接口

    public interface CashSuper {
        double acceptCash(double money);
    }

    创建正常收费子类:实现收费接口

    public class CashNormal implements CashSuper {
        @Override
        public double acceptCash(double money) {
            return money;
        }
    }

    创建打折收费子类:实现收费接口

    public class CashRebate implements CashSuper {
        private double moneyRebate = 1d;
        
        public CashRebate(double moneyRebate) {
            this.moneyRebate = moneyRebate;
        }
        
        @Override
        public double acceptCash(double money) {
            return money*moneyRebate;
        }
    }

    创建返利收费子类:实现收费接口

    public class CashReturn implements CashSuper {
        private double moneyCondition = 0.0d;
        private double moneyReturn =0.0d;
        
        public CashReturn(double moneyCondition, double moneyReturn) {
            super();
            this.moneyCondition = moneyCondition;
            this.moneyReturn = moneyReturn;
        }
    
        @Override
        public double acceptCash(double money) {
            double result = money;
            if(money>=moneyCondition){
                result = money-Math.floor(money/moneyCondition)*moneyReturn;
            }
            return result;
        }
    }

    创建收费工厂类

    public class CashFactory {
        public static CashSuper createCashAccept(String type,double moneyCondition,double moneyReturn,double moneyRebate){
            CashSuper cs = null;
            switch (type) {
                case "正常收费":
                    cs = new CashNormal();
                    break;
                case "满X返Y":
                    cs = new CashReturn(moneyCondition, moneyReturn);
                    break;
                case "打X折":
                    cs = new CashRebate(moneyRebate);
                    break;
                default:
                    break;
            }
            return cs;
        }
    }

     模拟打折测试

    public class Test {
        public static void main(String[] args) {
            double moneyNormal = 300;
            CashSuper cs1 = CashFactory.createCashAccept("正常收费",0,0,0);
            double result = cs1.acceptCash(moneyNormal);
            System.out.println("正常收费"+moneyNormal+"元的结果:"+result);
            
            double moneyRebate = 0.8;
            CashSuper cs2 = CashFactory.createCashAccept("打X折",0,0,moneyRebate);
            double result2 = cs2.acceptCash(moneyNormal);
            System.out.println(moneyNormal+"元打"+0.8*10+"折的结果:"+result2);
            
            double moneyCondition = 300;
            double moneyReturn =100;
            CashSuper cs3 = CashFactory.createCashAccept("满X返Y",moneyCondition,moneyReturn,0);
            double result3 = cs3.acceptCash(moneyNormal);
            System.out.println(moneyNormal+"元进行满"+moneyCondition+"减"+moneyReturn+"元的结果:"+result3);
        }
    }

    输出结果:

    正常收费300.0元的结果:300.0
    300.0元打8.0折的结果:240.0
    300.0元进行满300.0减100.0折的结果:200.0

    策略模式介绍:http://www.runoob.com/design-pattern/strategy-pattern.html

    策略模式定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。

    根据策略模式修改后的代码

    修改 CashFactory 类,并在类中添加 getResult() 方法,在 getResult() 方法内调用 acceptCash() 方法

    public class CashContext {
        CashSuper cs = null;
        
        public CashContext(String type,double moneyCondition,double moneyReturn,double moneyRebate){
            switch (type) {
                case "正常收费":
                    cs = new CashNormal();
                    break;
                case "满X返Y":
                    cs = new CashReturn(moneyCondition, moneyReturn);
                    break;
                case "打X折":
                    cs = new CashRebate(moneyRebate);
                    break;
                default:
                    break;
            }
        }
        public double getResult(double money){
            return cs.acceptCash(money);
        }
    }

    模拟打折测试

    public class Test {
        public static void main(String[] args) {
            double moneyNormal = 300;
            CashContext cc = new CashContext("正常收费",0,0,0);
            double result  = cc.getResult(moneyNormal);
            System.out.println("正常收费"+moneyNormal+"元的结果:"+result);
            
            double moneyRebate = 0.8;
            CashContext cc2 = new CashContext("打X折",0,0,moneyRebate);
            double result2  = cc2.getResult(moneyNormal);
            System.out.println(moneyNormal+"元打"+0.8*10+"折的结果:"+result2);
            
            double moneyCondition = 300;
            double moneyReturn =100;
            CashContext cc3 = new CashContext("满X返Y",moneyCondition,moneyReturn,0);
            double result3  = cc3.getResult(moneyNormal);
            System.out.println(moneyNormal+"元进行满"+moneyCondition+"减"+moneyReturn+"元的结果:"+result3);
        }
    }

    对比CashFactory和CashContext类,区别在于CashContext新增了 getResult() 方法,并在其内部调用收费类的 acceptCash() 方法,main方法不直接调用收费类的 acceptCash() 方法。

    工厂模式侧重于创建类,策略模式侧重于行为的选择。

    在打折促销的案例中,收费类都实现了CashSuper接口,并重写 acceptCash() 方法,我们可以在不同的场景中调用对应的类中的 acceptCash() 方法。但我们真正在乎的是 acceptCash() 方法。哪怕收费类中有一万个其他的方法,我们也只需要这一个方法。

    因为侧重点的不同,策略模式并不需要暴露完整的收费类,对收费类进行封装,暴露出 acceptCash() 方法即可。

    参考网上的文章:策略模式和工厂模式的区别

    https://blog.csdn.net/gaibian0823/article/details/27842443

    https://blog.csdn.net/tengzhaorong/article/details/6827093

    https://blog.csdn.net/basycia/article/details/50478245

  • 相关阅读:
    换手机了,dopod566,小E丢了 :(
    在a标签的href与onclick中使用javascript的区别
    我的SQL相关TIPS
    asp.net的ajax服务器端代理
    IE和Firefox中的dom加载完成执行代码(defer)
    看几个源码,自己多做项目了!
    数据层使用Server对象;动态生成控件多文件上传
    ref,out(摘)
    JavaScript和jQuery的DOM操作
    闭包
  • 原文地址:https://www.cnblogs.com/jwen1994/p/9989398.html
Copyright © 2020-2023  润新知