策略模式

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

一家超市进行打折促销:促销形式分别有:“打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

posted @ 2018-11-20 18:55  认真对待世界的小白  阅读(111)  评论(0编辑  收藏  举报