美文网首页Java Springapp开发
Java设计模式 - 策略模式

Java设计模式 - 策略模式

作者: 梦想编织者灬小楠 | 来源:发表于2016-08-19 21:18 被阅读234次

    策略模式属于对象的行为模式。其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。 --摘选自《JAVA与模式》

    理论有些抽象,举个简单的例子各位就容易理解了...

    我们去上课、上班、出差、旅游,需要选择合适的出行方式,是选择步行?公交?火车?还是飞机?...


    哈哈,这种选择其实就是一种“策略”。当然,针对这个例子,一种出行方式可能满足不了我们的需求,我们可能需要搭配不同的出行方式出行,这种多重选择其实也是一种“策略”。

    Java策略模式实战

    今天小编准备根据现实实例,用Java写一个基于“策略模式”的解决方案。好了,小伙伴们赶快上车...

    需求是这样的:某商场想要开展3种销售模式,而且可以相互之间任意选择转换...

    第1种销售模式:正常销售

    第2种销售模式:打折销售(如:全场商品9折、全场8折...)

    第3种销售模式:返现销售(如:全场商品满500元返现100元)

    直白点分析,其实就是让我们对用户购买商品的总金额进行“模式处理”,得到最终付款金额。

    话不多说,开始上代码...

    1.搭建抽象策略角色

    /**
     * 价格策略接口(所有价格策略的父类)
     * Created by Wangnan on 2016/8/19.
     */
    public interface PriceStrategyInterface {
    
        /**
         * 获取执行策略后得到的金额
         */
        float getStrategyResult();
    }
    

    2.构建具体策略角色(正常价格策略,打折价格策略,返现价格策略)

    /**
     * @ClassName: NormalPriceStrategy
     * @Description: 正常价格策略
     * @Author Wangnan
     * @Date 2016/8/19
     */
    public class NormalPriceStrategy implements PriceStrategyInterface{
    
        private float mPrice; // 用户购物总价
        
        public NormalPriceStrategy(float totalPrice){
            mPrice = totalPrice;
        }
    
        @Override
        public float getStrategyResult() {
            return mPrice;
        }
    }
    

    /**
     * @ClassName: DiscountPriceStrategy
     * @Description: 打折价格策略
     * @Author Wangnan
     * @Date 2016/8/19
     */
    public class DiscountPriceStrategy implements PriceStrategyInterface{
    
        private float mPrice; // 用户购物总价
        private float mDiscountRate; // 折扣率(0F ~ 1F)
    
        public DiscountPriceStrategy(float price , float discount){
            mPrice = price;
    
            if(discount >= 0F && discount <= 1F) { //折扣率越界判断
                mDiscountRate = discount;
            }else{
                mDiscountRate = 1;
            }
        }
    
        @Override
        public float getStrategyResult() {
            return mPrice * mDiscountRate;
        }
    }
    

    /**
     * @ClassName: ReturnPriceStrategy
     * @Description: 返现价格策略
     * @Author Wangnan
     * @Date 2016/8/19
     */
    public class ReturnPriceStrategy implements PriceStrategyInterface{
    
        private float mPrice; // 用户购买总价
        private float mReturnPriceStandard; // 返现标准
        private float mReturnPrice; // (满足返现标准) 返现金额
    
        public ReturnPriceStrategy(float price, float returnPriceStandard, float returnPrice){
            mPrice = price;
            mReturnPriceStandard = returnPriceStandard;
            mReturnPrice = returnPrice;
        }
    
        @Override
        public float getStrategyResult() {
            if(mPrice > mReturnPriceStandard){
                return mPrice - (( mPrice / mReturnPriceStandard) * mReturnPrice); // 返现叠加:(举例)满300减100,满600减200,...依次类推
            }else {
                return mPrice;
            }
        }
    }
    

    3.构造环境角色。【环境角色:持有一个策略类的引用,最终给客户端调用。其实就是策略的调度者(或者说是执行者)】

    /**
     * @ClassName: PriceContext
     * @Description: 价格环境角色
     * @Author Wangnan
     * @Date 2016/8/19
     */
    public class PriceContext {
    
        private PriceStrategyInterface mPriceStrategyInterface; // 价格策略接口
    
        public PriceContext(PriceStrategyInterface priceStrategyInterface){
            mPriceStrategyInterface = priceStrategyInterface;
        }
    
        /**
         * 执行价格策略 -> 调度策略对象,获取最终价格
         */
        public float executePriceStrategy(){
            return mPriceStrategyInterface.getStrategyResult();
        }
    }
    

    4.策略模式构造完毕,开始使用(这里给出了3种策略的使用方式)。

        // 假设用户购买1000元商品,商场没有购物活动
        float mPrice = 1000F;
        PriceContext context = new PriceContext(new NormalPriceStrategy(mPrice)); // 走正常价格策略
        float finalPrice = context.executePriceStrategy(); // 执行策略,finalPrice = 1000.0
    
        // 假设用户购买1000元商品,商场进行全场商品打9折活动
        float mPrice2 = 1000F;
        float discountRate = 0.9F;
        PriceContext context2 = new PriceContext(new DiscountPriceStrategy(mPrice2, discountRate)); // 走打折价格策略
        float finalPrice2 = context2.executePriceStrategy(); // 执行策略,finalPrice2 = 900.0
    
        // 假设用户购买1000元商品,商场进行全场商品满500减100返现活动
        float mPrice3 = 1000F;
        float returnPriceStandard = 500F; // 返现标准
        float returnPrice = 100F; // (满足返现标准)返现金额
        PriceContext context3 = new PriceContext(new ReturnPriceStrategy(mPrice3, returnPriceStandard, returnPrice)); // 走返现价格策略
        float finalPrice3 = context3.executePriceStrategy(); // 执行策略,finalPrice3 = 800.0
    

    至此,我们的“策略模式”就结束了,看完的朋友是不是觉得有点小题大做,把简单的问题给复杂化了呢...哈哈,针对这个问题确实是!但是,如果你的需求更加多样,更加复杂...你会发现这种设计模式其实可以把你的复杂问题简单化、流程化...

    总结

    策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化,使算法自身更具灵活性。

    拓展

    针对看过我上一篇文章Java设计模式 - 简单工厂模式的朋友,我给你们带来一个新的福利 - 组合两种设计模式,我们常常听说或正在使用的MVC、MVP、MVVM...等模式,其实在很大程度上是将设计模式进行组合规整后形成的...我们今天也要组合一个新模式 - 简单策略工厂模式(将调度的策略进一步用简单工厂模式进行封装,让工厂去生产我们需要的策略)。

    1.开始改造价格环境角色,封装价格策略工厂

    /**
     * @ClassName: PriceContext
     * @Description: 价格环境角色
     * @Author Wangnan
     * @Date 2016/8/19
     */
    public class PriceContext {
    
        private PriceStrategyInterface mPriceStrategyInterface; // 价格策略接口
    
        public static final int TYPE_NORMAL_PRICE = 0x0001; // 正常价格策略标识符
        public static final int TYPE_DISCOUNT_PRICE = 0x0002; // 折扣价格策略标识符
        public static final int TYPE_RETURN_PRICE = 0x0003; // 返现价格策略标识符
    
        /**
         *
         * 创建环境角色
         * @param type TYPE_NORMAL_PRICE(正常价格策略),TYPE_DISCOUNT_PRICE(折扣价格策略) or TYPE_RETURN_PRICE(返现价格策略)
         * @param args type = TYPE_NORMAL_PRICE时,只需传入购物总价(args[0])。
         *             type = TYPE_DISCOUNT_PRICE时, 需要传入购物总价(args[0])和折扣率(args[1])
         *             type = TYPE_RETURN_PRICE时,需要传入购物总价(args[0])、返现价格标准(args[1])和返现价格(args[2])
         */
        public PriceContext(int type, float...args){
            switch (type){
                case TYPE_NORMAL_PRICE:
                    mPriceStrategyInterface = new NormalPriceStrategy(args[0]); // 创建正常价格策略
                    break;
                case TYPE_DISCOUNT_PRICE:
                    mPriceStrategyInterface = new DiscountPriceStrategy(args[0], args[1]); // 创建折扣价格策略
                    break;
                case TYPE_RETURN_PRICE:
                    mPriceStrategyInterface = new ReturnPriceStrategy(args[0], args[1], args[2]); // 创建返现价格策略
                    break;
                default:
                    mPriceStrategyInterface = new NormalPriceStrategy(args[0]);
                    break;
            }
        }
    
        /**
         * 调度策略对象,执行策略 -> 获取最终价格
         */
        public float executePriceStrategy(){
            return mPriceStrategyInterface.getStrategyResult();
        }
    }
    

    2.使用价格环境角色(举例)

        // 假设用户消费1000元,商品开展全场商品打8.8折活动
        PriceContext mPriceContext = new PriceContext(PriceContext.TYPE_DISCOUNT_PRICE, 1000, 0.88F);
        float finalPrice = mPriceContext.executePriceStrategy(); // finalPrice = 880.0
    

    今天的内容就分享到这了...Good,Lucky!

    相关文章

      网友评论

      • 有梦南柯:这个例子很好
      • sugaryaruan:这里结合的静态工厂会不会更合适?不必引入静态常量,而是用一个静态方法对应创建一个策略。

      本文标题:Java设计模式 - 策略模式

      本文链接:https://www.haomeiwen.com/subject/nqobsttx.html