读前辈的大话设计模式(二)之策略模式,抒自己的读后感

    在上一篇文章里,我们了解了简单工厂设计模式之后,接下来我们要说的是策略设计模式。

    首先看一下策略模式(Strategy)的正式定义:它定义了算法家族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化不会影响到使用算法客户。

    如果你感觉看完这段定义之后,有些困惑或者不理解,没关系,我会逐步引导,让你找到一点点拨云见日的感觉。

    还是要用到前面的简单工厂设计模式来做引导,在那个模式里面,我们在测试环节传入的参数代表什么?答案是加减乘除的符号,通俗的讲传入的是能根据该符号判断产生对应的entity对象的标志,接着根据这个产生的entity对象,调用里面定义的方法进行运算得到我们需要的结果值,将结果值返回到测试环节中,然后将结果值打印显示。在这里我们的首要目的是得到entity对象,因为对象里面定义了获得结果方法。

    而策略模式,我们需要首先得到的是什么?答案就是解决需求的具体策略。而策略里面同样是定义了解决问题的方法,听起来是不是感觉两者很像。好了,我们来试试代码吧。代码过后我们再做一些对比总结。

  

    我们依旧是采用Java面向对象的思想来实现。

    1、定义抽象策略父类:

package main_operation;

/**
 * 策略父类
 * Created by Administrator on 2017/8/1.
 */
public abstract class CashSuperStrategy {

    /**
     * 定义一个抽象的策略方法
     * @param payment 消费额
     * @return
     */
    public abstract double acceptCash(double payment);

}

    2、定义对应的具体策略执行类

    无优惠支付策略类:

package entity;

import main_operation.CashSuperStrategy;

/**
 * Created by Administrator on 2017/8/1.
 */
public class CashNormal extends CashSuperStrategy {

    /**
     * 定义具体的策略执行方法
     * @param payment 消费额
     * @return
     */
    @Override
    public double acceptCash(double payment) {

        return payment;
    }
}

    打折策略执行类:

package entity;

import lombok.AllArgsConstructor;
import main_operation.CashSuperStrategy;

/**
 * Created by Administrator on 2017/8/1.
 */
@AllArgsConstructor
public class CashRebate extends CashSuperStrategy {

    /**
     * 打折率
     */
    private double discount = 1;
    @Override
    /**
     * 定义具体的策略执行方法
     */
    public double acceptCash(double payment) {
        return payment * discount;
    }
}

    满减策略执行类

package entity;

import lombok.AllArgsConstructor;
import main_operation.CashSuperStrategy;

/**
 * Created by Administrator on 2017/8/1.
 */
@AllArgsConstructor
public class CashReturn extends CashSuperStrategy {

    /**
     * 满减额度中满的值
     */
    private double discountCondition;

    /**
     * 满减额度中减的值
     */
    private double moneyReturn;

    @Override
    /**
     * 定义具体的策略执行方法
     */
    public double acceptCash(double payment) {

        double actualPayment = payment;
        if (payment >= discountCondition){
            actualPayment = payment - Math.floor(payment/discountCondition)* moneyReturn;
        }
        return actualPayment;
    }
}

   

    3、定义一个策略枚举

package enum_entity;

/**
 * Created by Administrator on 2017/8/1.
 */
public enum CashCondition {

    /**
     * 构造对应策略的枚举值
     */
    NORMAL,MONEY_RETURN,REBATE;
}

    4、定义策略开关类

package controller;

import entity.CashNormal;
import entity.CashRebate;
import entity.CashReturn;
import enum_entity.CashCondition;
import main_operation.CashSuperStrategy;

/**
 * Created by Administrator on 2017/8/1.
 */
public class CashContext {

    private CashSuperStrategy strategy;

    /**
     * 通过传入枚举值,判断选用何种策略
     * @param condition
     */
    public CashContext(CashCondition condition) {

        switch (condition){
            case NORMAL:
                strategy = new CashNormal();
                break;

            case REBATE:
                strategy = new CashRebate(0.6);
                break;

            case MONEY_RETURN:
                strategy = new CashReturn(200,50);
                break;
        }
    }

    public double getResult(double payment){

        /**
         * 根据上面构造器找到的策略,来调用相应的策略解决方法计算结果
         */
        return strategy.acceptCash(payment);
    }
}

    5、定义测试类:

import controller.CashContext;
import enum_entity.CashCondition;
import org.junit.Test;

/**
 * Created by Administrator on 2017/8/1.
 */
public class TestCash {

    @Test
    public void testCash(){

        /**
         * 传入策略对应的枚举值
         */
        CashContext context = new CashContext(CashCondition.MONEY_RETURN);

        /**
         * 传入消费额
         */
        double payment = context.getResult(200);
        System.out.println(payment);

    }
}

    至此,代码基本全部写完,由于Java switch分支判断只能传参数是char或者枚举,所以只好实用枚举来实现(作者水平有限)。

    刚才说到,策略和简单工厂很像,但区别是策略模式是由策略开关来传入实体对象,而简单工厂模式是根据工厂把对象造出来。

   

猜你喜欢

转载自blog.csdn.net/medier/article/details/76559680