设计模式之策略模式

来源:互联网 发布:护眼灯推荐 知乎 编辑:程序博客网 时间:2024/06/03 13:07

前言:

策略模式(strategy Pattern):定义了算法家族,分别封装;算法之间可以替换,但不会影响使用算法的客户。

一.策略模式的简介:

类的作用:面向对象的过程中,并不是类越多越好,类的划分基础是抽象,类是具有相同属性和功能的对象集合。

策略类的作用:面向对象中,类的作用就是封装变化点,将可变化的算法进行封装,就是策略类。

生活中的策略模式:犹如诸葛亮给赵云的3个锦囊妙计,护送刘备逃离孙权的江东,返回荆州。每一个锦囊,就是一个策略(算法)的封装类,3个锦囊就是就是算法家族。让客户(刘备)根据不同局势,选择不同的锦囊(算法)解决问题,最终成功逃回荆州。

二.策略模式的实例:

案例:电商网站购物订单结算计费,实现正常计费、打折后计费、返利后计费。

1 .UML类图:

这里写图片描述

2 .策略的抽象父类

package com.pattern.strategy;/** * 收费算法的抽象父类 * @author 葫芦娃 * */public abstract class CashBase {    //抽象方法    public abstract double chargeMoney(double money);}

3 .算法家族(各种策略):

正常计费算法:

package com.pattern.strategy;/** * 正常计费类 *  * @author 葫芦娃 * */public class CashNormal extends CashBase {    @Override    public double chargeMoney(double money) {        return money;    }}

打折计费算法:

package com.pattern.strategy;/** * 打折计费类 *  * @author 葫芦娃 * */public class CashDiscount extends CashBase {    //折扣    private double discount;    //获取折扣的构造方法    public CashDiscount(double discount) {        super();        this.discount = discount;    }    //最终计费    @Override    public double chargeMoney(double money) {        money = money*discount;        return money;    }}

返利计费算法:

package com.pattern.strategy;/** * 返利计费类 *  * @author 葫芦娃 * */public class CashReturn extends CashBase {    //返利消费底线 ,如消费满200返现10元    private double returnCondition;    //返现金额    private double returnMoney;    //传递参数的构造器    public CashReturn(double returnCondition, double returnMoney) {        super();        this.returnCondition = returnCondition;        this.returnMoney = returnMoney;    }    @Override    public double chargeMoney(double money) {        //如果消费金额满足返现条件,就返现        if (money>=returnCondition) {            money = money - returnMoney;        }        return money;    }}

4 .创建策略管理类:

该类实现根据传入的策略,实例化策略对象,调用对象方法的过程。

但为了能够在客户端中隐藏创建策略的过程,实现更好的封装,我们在此处结合了简单工厂模式(点击查看详解),用以根据不同的参数,创建不同的策略对象。如果想完全消除switch-case的条件判断,简化代码的话,可以利用反射来解决,具体实现查看上面的简单工厂模式即可。

package com.pattern.context;import com.pattern.strategy.CashBase;import com.pattern.strategy.CashDiscount;import com.pattern.strategy.CashNormal;import com.pattern.strategy.CashReturn;/** * 策略选择器 * @author 葫芦娃 * */public class CashContext {    private CashBase cBase;//收费策略    private int cashType; //计费策略类型,用户拥有优惠特权    private double discount;//折扣    private double returnCondition;//返现条件    private double returnMoney;//返现金额    public CashContext(int cashType, double discount, double returnCondition, double returnMoney) {        super();        this.cashType = cashType;        this.discount = discount;        this.returnCondition = returnCondition;        this.returnMoney = returnMoney;    }    //获取最终付款金额方法(结合简单工厂模式创建策略)    public double getResult(double money) {        switch (cashType) {        case 1:            //正常计费            cBase = new CashNormal();            break;        case 2:            //打折计费            cBase = new CashDiscount(discount);        break;        case 3:            //返利计费            cBase = new CashReturn(returnCondition, returnMoney);        break;        default:            break;        }        return cBase.chargeMoney(money);    }}

5 .客户端:

单一职责:对一个类而言,应只有一个引起它变化的原因。

从客户端代码中可以体会到,通过运用简单工厂模式策略模式提供创建策略对象的服务,客户端只需要引入一个实体类CashContext,降低耦合度,减轻了客户端的职责,符合面向对象的单一职责原则

客户端不需要认识(import引用)各个策略类,通过参数即可完成对不同策略的创建,使收费算法和客户端彻底分离

package com.pattern.client;import com.pattern.context.CashContext;/** * @author 葫芦娃 * */public class Client {    /**     * @param args     */    public static void main(String[] args) {        double money = 888.88;// 订单金额        // 正常收费,CashContext(收费策略, 折扣, 返利条件, 返利金额)        CashContext nomalContext = new CashContext(1, 0, 0, 0);        double realMoney1 =  nomalContext.getResult(money);        System.out.println("本次消费"+money+"元,实付款:" + realMoney1+ "元,正常收费");        // 打折收费,CashContext(收费策略, 折扣, 返利条件, 返利金额)        CashContext discountContext = new CashContext(2, 0.8, 0, 0);        double realMoney2 =  discountContext.getResult(money);        System.out.println("本次消费"+money+"元,实付款:" + realMoney2 + "元,打8折");        // 返利收费,CashContext(收费策略, 折扣, 返利条件, 返利金额)        CashContext returnContext = new CashContext(3, 0, 800, 100);        double realMoney3 =  returnContext.getResult(money);        System.out.println("本次消费"+money+"元,实付款:" + realMoney3 + "元,满800元返利100元");    }}

6 .运行结果:

本次消费888.88元,实付款:888.88元,正常收费本次消费888.88元,实付款:711.104元,打8折本次消费888.88元,实付款:788.88元,满800元返利100元

总结:

1 .策略模式是一种定义了一系列算法的方法,所有的算法完成的都是相同的工作(本例中计算消费总价),只是具体的实现不同。

2 .策略模式可以用相同的方式调用所有的算法,减少了定义算法与使用算法之间的耦合。

3 .策略模式的策略层(CashBase抽象类)为Context上下文层(CashContext抽象类)提供了可复用的算法行为(chargeMoney()方法),通过继承提取出公共功能。

4 .策略模式封装算法,避免了用条件判断语句,选择行为。将每个算法进行封装,消除了聚集在一个类中的条件判断。

5 .策略模式还简化了单元测试,每个算法都可以通过自己的接口进行单元测试。

原创粉丝点击