设计模式系列之策略模式(Strategy Pattern)

  • 意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。
  • 主要解决:在有多种算法相似的情况下,使用 if...else 所带来的复杂和难以维护。
  • 何时使用:一个系统有许多许多类,而区分它们的只是他们直接的行为。
  • 如何解决:将这些算法封装成一个一个的类,任意地替换。
  • 关键代码:实现同一个接口。
  • 应用实例:
    • 1、诸葛亮的锦囊妙计,每一个锦囊就是一个策略。
    • 2、旅行的出游方式,选择骑自行车、坐汽车,每一种旅行方式都是一个策略。
    • 3、JAVA AWT 中的 LayoutManager。
  • 优点:
  • 1、算法可以自由切换。
  • 2、避免使用多重条件判断。
  • 3、扩展性良好。
  • 缺点:
  • 1、策略类会增多。
  • 2、所有策略类都需要对外暴露。
  • 使用场景:
  • 1、如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。
  • 2、一个系统需要动态地在几种算法中选择一种。
  • 3、如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。

注意事项:如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。

案例说明

用户到超市购买东西不同的会员等级,不同的折扣

等级 折扣
NormalUser 100%
VIPUser 90%
SuperUser 80%
GlodUser 70%

通过实现CalPrice实现不同的计算方式,在User代码中设定总价和计算折扣的方式即可.

代码实现

普通实现

public class Demo {

    public static void main(String[] args) {
        float sumPrice = 100;
        if(sumPrice > 100){
            sumPrice = sumPrice * 0.9f;
        }else if(sumPrice > 60){
            sumPrice = sumPrice * 0.8f;
        }else if(sumPrice > 30){
            sumPrice = sumPrice * 0.7f;
        }

        System.out.println("计算之后的价格是:" + sumPrice);
        // 加入需求更改为满500元打5折???? 代码是不是越来越复杂?
    }
}


接口

package com.zhoutao123.design.pattern.Strategy.calprice;

public interface CalPrice {

    Float calPrice(Float sumPrice);
}

不同的实现方法

  • 普通会员

package com.zhoutao123.design.pattern.Strategy.calprice;

public class NormalUserCalPrice implements CalPrice {
    @Override
    public Float calPrice(Float sumPrice) {
        System.out.println(String.format("当前计算总价:%f 折扣:%f",sumPrice,1.0f));
        return sumPrice;
    }
}

  • VIP 会员
package com.zhoutao123.design.pattern.Strategy.calprice;

public class VIPUserCalPrice implements CalPrice {
    @Override
    public Float calPrice(Float sumPrice) {
        System.out.println(String.format("当前计算总价:%f 折扣:%f",sumPrice,0.9f));
        return sumPrice * 0.9f;
    }
}


  • SuperVIP会员
package com.zhoutao123.design.pattern.Strategy.calprice;

import com.zhoutao123.design.pattern.Strategy.calprice.CalPrice;

public class SuperUserCalPrice implements CalPrice {
    @Override
    public Float calPrice(Float sumPrice) {
        System.out.println(String.format("当前计算总价:%f 折扣:%f",sumPrice,0.8f));
        return sumPrice * 0.8f;
    }
}

  • GlodVIP会员
package com.zhoutao123.design.pattern.Strategy.calprice;

public class GlodUserCalPrice implements CalPrice {
    @Override
    public Float calPrice(Float sumPrice) {
        System.out.println(String.format("当前计算总价:%f 折扣:%f",sumPrice,0.7f));
        return sumPrice * 0.7f;
    }
}

用户代码

package com.zhoutao123.design.pattern.Strategy;

import com.zhoutao123.design.pattern.Strategy.calprice.*;

public class User {

    private float sumPrice = 0f;

    // 计算的对象,注意在setSumPrice(float)会根据不同的总额设置不同的实现
    private CalPrice calPrice;

    public void setSumPrice(float sumPrice) {
        this.sumPrice = sumPrice;
    }

    /**
     * 设置用户的折扣计算方式
     * @param
     */
    public void setCalPrice(CalPrice calPrice) {
        this.calPrice =calPrice;
    }

    /**
     * 获取用户的应当付钱
     * @return
     */
    public float payAmount() {
        return calPrice.calPrice(this.sumPrice);
    }
}


测试代码

package com.zhoutao123.design.pattern.Strategy;

import com.zhoutao123.design.pattern.Strategy.calprice.GlodUserCalPrice;
import com.zhoutao123.design.pattern.Strategy.calprice.NormalUserCalPrice;
import com.zhoutao123.design.pattern.Strategy.calprice.SuperUserCalPrice;
import com.zhoutao123.design.pattern.Strategy.calprice.VIPUserCalPrice;

public class Test {

    public static void main(String[] args) {
        User user1 = new User();
        // 设定用户的消费总额为10元,会员等级为普通会员,不大这
        user1.setSumPrice(10);
        user1.setCalPrice(new NormalUserCalPrice());
        System.out.println("user1 = " + user1.payAmount());

        // 后来用户觉得就买10元的东西不太好,于是又买了23快的东西
        // 他发现自己有张VIP 的会员卡,所以他的价格为
        user1.setSumPrice(33);
        user1.setCalPrice(new VIPUserCalPrice());
        System.out.println("user1 = " + user1.payAmount());

        // 后面的故事自己想,:>
        user1.setSumPrice(53.3f);
        user1.setCalPrice(new SuperUserCalPrice());
        System.out.println("user1 = " + user1.payAmount());

        user1.setSumPrice(130000);
        user1.setCalPrice(new GlodUserCalPrice());
        System.out.println("user1 = " + user1.payAmount());

    }
}

拓展

试想一下,假如说某一天VIP 会员机制改革了,要求满额100元才能打9折,那么我们只要修改VIP折扣计算中的代码即可,无需修改User的代码,只要修改计算方式,这样的代码看起来是不是更清爽一点.

package com.zhoutao123.design.pattern.Strategy.calprice;

public class VIPUserCalPrice implements CalPrice {
    @Override
    public Float calPrice(Float sumPrice) {
        if(sumPrice >= 100) {
            System.out.println(String.format("当前计算总价:%f 折扣:%f", sumPrice, 0.9f));
            return sumPrice * 0.9f;
        }else {
            System.out.println(String.format("当前计算总价:%f 折扣:%f", sumPrice, 1.0f));
            return sumPrice;
        }
    }
}

posted @ 2019-02-15 10:38  燕归来兮  阅读(191)  评论(0编辑  收藏  举报