zoukankan      html  css  js  c++  java
  • DesignMode_StrategyMode

    策略模式 -- 其实就是封装了不同算法的一种方式,让客户端代码只需要跟那个策略类进行交互,而不需要进行再与底层的其他什么类进行交互,耦合度大大的降低

    情景 :写一个商场打折促销的收费系统,促销方式有 : 打0.8折, 满500减200, 还有正常收费

    思路 :因为促销的方式分了几种,但是目的都是一样的,就是算最终的收费金额,所以,当方式不同,但目的一样时,就可以用工厂方法,

    上代码

    首先先定义一个父类来总结几个子类的接口,这个时候,就可以用抽象类,因为,这个类是几个具体方式的抽象出来的总结,不需要实例化

    package strategicMode;
    
    /* 对收钱的概念的抽象
     * */ 
    
    public abstract class CashSuper {
        public abstract double getResult(double money);
    }

    然后是那几个具体方式的实现

    package strategicMode;
    
    /*
     * 正常收费区
     * */
    
    public class CashNormal extends CashSuper{
        public CashNormal(){
            
        }
        @Override
        public double getResult(double money) {
    
            return money;
        }
    }
    package strategicMode;
    
    /*
     * 折扣区
     * */
    
    public class CashRebate extends CashSuper{
        private double rebate;
        private double result;
        public CashRebate(double rebate) {
            this.rebate = rebate;
        }
        
        public double getResult(double money) {
            result = money*rebate;
            return result;
        }
    }
    package strategicMode;
    
    /*
     * 返利区
     * */
    public class CashReturn extends CashSuper{
        private double minMon;
        private double returnMon;
        private double result;
        public CashReturn(double minMon, double returnMon) {
            this.minMon = minMon;
            this.returnMon = returnMon;
        }
        
    
        @Override
        public double getResult(double money) {
            if(money > minMon){
                result = money - returnMon;
            }
            return result;
        }
    }

    好了,下面就是套路了,写个工厂类判别什么时候调用哪个促销收费方式

    package strategicMode;
    
    /*
     *  促销方式的工厂方法
     * */
    
    public class CashWayFactory {
        CashSuper cashWay;
        public CashSuper getCashAcceptWay(String cashAcceptWay){
            
            switch(cashAcceptWay){
            case "打八折": cashWay = new CashRebate(0.8);
                         break;
            case "正常收费" : cashWay = new CashNormal();
                            break;
            case "满500返200" : cashWay = new CashReturn(500, 200);
                            break;
            }
            return cashWay;
        }
    }

    客户端代码

    package strategicMode;
    
    import java.util.Scanner;
    
    import org.junit.Test;
    
    /*
     * 客户端代码
     * */
    
    public class ClientCode {
        CashWayFactory cashWayFactoy = new CashWayFactory();
        CashSuper cashWay;
        @Test
        public void testCashWay(){
            System.out.println("请输入你的收费方式(打八折, 正常收费, 满500返200)");
            Scanner in = new Scanner(System.in);
            String cashAcceptWay = in.next();
            System.out.println("请输入总费用:");
            double money = in.nextDouble();
            cashWay = cashWayFactoy.getCashAcceptWay(cashAcceptWay);
            double result = cashWay.getResult(money);
            System.out.println("你需要交的总费用: "+result);
        }
    }

    但是上面的代码灵活性不是很高,当我需求改变了,要加一些其他的促销方式时,就还是要在工厂里面进行改动和维护,导致整个代码需要重新编译部署,包括了客户端的代码,引用客户端的代码是直接和工厂方法进行了交互的,所以这样来说还是非常鸡肋的。于是就有了策略方式

    策略模式 就是一种可以封装不同算法的方式,最终得到一个不同算法,但目的一样的值,简单明了的就是封装了变化性

    package strategicMode;
    
    /*
     * 维护对CashSuper对象的引用 
     * */
    
    public class StrategeContext {
        CashSuper cashWay;
        
        // 策略模式与工厂相结合
        public StrategeContext(String cashWayString) {
    
            switch(cashWayString){
            case "打八折": cashWay = new CashRebate(0.8);break;
            case "正常收费" : cashWay = new CashNormal();break;
            case "满500返200" : cashWay = new CashReturn(500, 200);break;
            }
            
        }
        
        // 现在我要的需求是 : 客户端的代码只需要调用这个方法就可以得到相应的结果了
        public double cashAcceptWay(double money){
            return cashWay.getResult(money);
        }
    }

    上面的策略类就是把所有不同的算法方式,都封装到一起了,现在只是需要得到一个值返回给客户端,而客户端的代码也会变得十分简洁

    package strategicMode;
    
    import java.util.Scanner;
    
    import org.junit.Test;
    
    /*
     * 拥有
     * */
    public class ClientCode2_0 {
        StrategeContext context;
        @Test
        public void testCashWay(){
            System.out.println("请输入总共花费:");
            Scanner in = new Scanner(System.in);
            double cash = in.nextDouble();
            System.out.println("请输入你的收费方式(打八折, 正常收费, 满500返200)");
            String cashWayString = in.next();
            context = new StrategeContext(cashWayString);
            
            System.out.println("你应该收取的费用是 : "+context.cashAcceptWay(cash));
        }
    }

    可以看到客户端只需要有一个策略类就能得到相应的结果,而不需要再跟工厂和促销方式这些底层的东西打交道了。。。就相当于,现在已经从经理直接升级为了ceo了,我只需要一个策略,其余的让下面的人去做,我不需要管,而策略类就是部署下面的人去做的中间商,可以看作经理。但是这个代码终归是不完整的,因为还有一个重要的问题没有解决,就是,我每次新加入一个需求促销方式,都要去策略类哪里部署,让他去做,这也是很麻烦的,所以就会引入反射这个方式,后面的blog我会继续提到。

  • 相关阅读:
    【转】QT创建子对话框的方法
    IplImage转为Mat的方法
    浅谈Android选项卡(二)
    浅谈Android选项卡(一)
    Android来电、去电监听
    文件加密
    Java实现文件重命名
    使用单个httpclient实例请求数据。
    获取Android状态栏的高度
    [置顶] 微软翻译接口
  • 原文地址:https://www.cnblogs.com/AmoryWang-JavaSunny/p/6517811.html
Copyright © 2011-2022 走看看