设计模式梳理——策略模式

一、概述

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

二、编程实现

       该程序主要通过模拟商场收费打折的功能实现。

1、创建现金收费抽象类

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

2、创建各种收费的具体实现

      2.1 正常收费

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

      2.2 返利收费 满300送100

public class CashReturn extends CashSuper {

    private double moneyCondition;
    private double moneyReturn;

    public CashReturn(double moneyCondition, double moneyReturn) {
        this.moneyCondition = moneyCondition;
        this.moneyReturn = moneyReturn;
    }

    @Override
    public double acceptCash(double money) {
        double result = 0d;
        if(money > moneyCondition){
            result = money - Math.floor(money/moneyCondition) * moneyReturn;
        }
        return result;
    }
}

      2.3 打折收费

public class CashRebate extends CashSuper {

    private double rebateRate = 1d;

    public CashRebate(double rebateRate) {
        this.rebateRate = rebateRate;
    }

    @Override
    public double acceptCash(double money) {
        return money*rebateRate;
    }
}

3、context上下文,维护一个对Strategy对象的引用

public class Context {

    private CashSuper cashSuper;

    public Context(CashSuper cashSuper) {
        this.cashSuper = cashSuper;
    }

    public double getMoney(double money){
        return cashSuper.acceptCash(money);
    }
}

4、策略模式测试

      //策略模式应用
        Context context = null;
        String type = "normal";
        switch (type){
            case "normal":
                context = new Context(new CashNormal());
                break;
            case "return":
                context = new Context(new CashReturn(300,100));
                break;
            case "rebate":
                context = new Context(new CashRebate(0.8));
                break;
        }
        double total = context.getMoney(2000);
        System.out.println(total);

至此,策略模式的解释已经结束,可以看出以上代码的优缺点:

优点:1、算法可以自由切换。 2、避免使用多重条件判断。 3、扩展性好。

缺点:1、客户端必须知道所有的策略类,并自己决定由那个策略类。   2、策略类会很多。

解决这个缺点方法:策略+简单工厂

5、策略模式+简单工厂结合

          策略模式需要在客户端判断用哪个算法,那么为了解决这个问题就可以将策略模式和简单工厂结合起来。具体的方法就是       简单工厂与策略模式中的Context类结合

改进的Context代码:

public class SimpleFactoryContext {
    CashSuper cashSuper = null;

    public SimpleFactoryContext(String type){
        switch (type){
            case "normal":
                cashSuper = new CashNormal();
                break;
            case "return":
                cashSuper = new CashReturn(300,100);
                break;
            case "rebate":
                cashSuper = new CashRebate(0.8);
                break;
        }
    }
    public double getResult(double money){
        return cashSuper.acceptCash(money);
    }
}

优点:解决了需要在客户端判断使用那个实现的缺点;

缺点:在cashContext中用到了swith,也就是说,如果我们需要增加一种算法,比如"满200减50",就必须更改cashContext中的switch代码。

6、策略模式+简单工厂+反射机制

          策略模式需要在客户端判断用哪个算法,那么为了解决这个问题就可以将策略模式和简单工厂结合起来。具体的方法就是       简单工厂与策略模式中的Context类结合

改进的Context代码:

public class FsContext {
    private static final String[] CUSH_CLASS_NAME = {
            "com.zbf.strategyMode.CashNormal",
            "com.zbf.strategyMode.CashRebate",
            "com.zbf.strategyMode.CashReturn"
    };
    CashSuper cashSuper = null;

    public FsContext(int type,Class[] paramsType, Object[] params){
        try {
            Class<?> clazz=Class.forName(CUSH_CLASS_NAME[type]);
            Constructor<?> constructor=clazz.getConstructor(paramsType);
            this.cashSuper=(CashSuper)constructor.newInstance(params);

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
    public double getResult(double money){
        return cashSuper.acceptCash(money);
    }
}

7、测试

       /**
         * 策略模式与简单工厂模式的结合,使得客户端只需知道sfc类即可,而单纯的策略模式客户端需要认识context及caseSuper,
         * 此方式降低了耦合度
         */
        SimpleFactoryContext sfc = new SimpleFactoryContext("return");
        double m = sfc.getResult(2000);
        System.out.println(m);

        //反射机制
        Class[] paramTypes2 = {double.class};
        Object[] params2 = {0.8d};
        FsContext fc = new FsContext(1,paramTypes2,params2);
        double mon = fc.getResult(2000);
        System.out.println(mon);

注:参考文献《大话设计模式》程杰著。

猜你喜欢

转载自blog.csdn.net/sinat_35322593/article/details/82590682