博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
设计模式梳理——策略模式
阅读量:4096 次
发布时间:2019-05-25

本文共 4511 字,大约阅读时间需要 15 分钟。

概述

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

主要解决

在有多种算法相似的情况下,使用 if...else 或 switch...case 所带来的复杂性和臃肿性。

编程实现

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

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);

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

 

 

 

 

 

 

 

 

 

 

 

转载地址:http://oklii.baihongyu.com/

你可能感兴趣的文章
数据结构与算法7-栈
查看>>
线性数据结构学习笔记
查看>>
Java并发编程 | 一不小心就死锁了,怎么办?
查看>>
(python版)《剑指Offer》JZ01:二维数组中的查找
查看>>
(python版)《剑指Offer》JZ06:旋转数组的最小数字
查看>>
(python版)《剑指Offer》JZ13:调整数组顺序使奇数位于偶数前面
查看>>
(python版)《剑指Offer》JZ28:数组中出现次数超过一半的数字
查看>>
(python版)《剑指Offer》JZ30:连续子数组的最大和
查看>>
(python版)《剑指Offer》JZ32:把数组排成最小的数
查看>>
(python版)《剑指Offer》JZ02:替换空格
查看>>
JSP/Servlet——MVC设计模式
查看>>
使用JSTL
查看>>
Java 8新特性:Stream API
查看>>
管理用户状态——Cookie与Session
查看>>
最受欢迎的前端框架Bootstrap 入门
查看>>
JavaScript编程简介:DOM、AJAX与Chrome调试器
查看>>
通过Maven管理项目依赖
查看>>
通过Spring Boot三分钟创建Spring Web项目
查看>>
Spring的IoC(依赖注入)原理
查看>>
Guava快速入门
查看>>