设计模式——策略模式

《Head First 设计模式》 学习笔记
码云同步更新中
如有错误或不足之处,请一定指出,谢谢~

往期回顾
  1. 设计模式——策略模式
  2. 设计模式——装饰者模式
  3. 设计模式——观察者模式
策略模式
  • 定义:
    • 策略模式——定义算法族,分别封装起来,让他们可以互相替换,此模式让算法的变化独立与使用算法的客户
  • 适用范围:
    • 几个类的主要逻辑相同,只在部分逻辑的算法和行为上稍有区别的情况
    • 有几种相似的行为(算法),客户端需要动态决定使用哪一种
  • 优点:
    • 动态改变对象的行为
    • 扩展性良好
  • 缺点:
    • 客户端必须知道所有的策略类,并自行决定使用哪一个
    • 会产生很多策略类
    • 只适合扁平的结构,策略之间层级平等,不能互相嵌套
  • 设计原则:
    • 找出应用中可能需要变化的地方,把它们独立出来,不要和那些不需要变化的代码混在一起
    • 针对接口编程,而不是针对实现编程
    • 多用组合,少用继承
  • 结构
    • 抽象策略:抽象类或接口,约束具体策略的行为
    • 具体策略:抽象策略的实现
    • 上下文类:负责具体交互,相当于一个容器,持有具体策略实现的引用
  • 执行顺序:
    • 创建具体策略实现
    • 创建上下文类,并注入策略
    • 通过上下文类处理数据
  • 案例
    • 电子商城,客户下单时需要根据不同的客户类型计算折扣后价格
      • 普通客户:无优惠
      • vip客户:9折
      • 其他自定义策略…
    • 还用到了工厂模式,工厂类用到了单例模式,达到消除if/else语句的目的
  • 代码
/**
 * 策略接口
 *
 * @author prik
 * @date 2019/7/18
 */
public interface DiscountStrategy {

    /**
     * 计算折扣后价格
     *
     * @param originalPrice 原价
     * @return 折扣后应付价格
     */
    BigDecimal calDiscountPrice(BigDecimal originalPrice);
}

/**
 * 普通客户策略实现
 *
 * @author prik
 * @date 2019/7/18
 */
public class OrdinaryDiscountStrategy implements DiscountStrategy {
    @Override
    public BigDecimal calDiscountPrice(BigDecimal originalPrice) {
        System.out.println("普通客户,无优惠");
        return originalPrice;
    }
}

/**
 * vip客户策略实现,九折
 *
 * @author prik
 * @date 2019/7/18
 */
public class VipDiscountStrategy implements DiscountStrategy {
    @Override
    public BigDecimal calDiscountPrice(BigDecimal originalPrice) {
        System.out.println("VIP客户,九折优惠~");
        return originalPrice.multiply(new BigDecimal("0.9"));
    }
}

/**
 * 顾客
 * 注:@Data为lombok注解
 *
 * @author prik
 * @date 2019/7/18
 */
@Data
public class Customer {

    /**
     * 姓名
     */
    private String name;

    /**
     * 客户类型
     */
    private Integer type;

    /**
     * 普通客户
     */
    public static final int TYPE_ORDINARY = 1;
    /**
     * vip客户
     */
    public static final int TYPE_VIP = 2;
    /**
     * 合作伙伴
     */
    public static final int TYPE_PARTNER = 3;
}

/**
 * 策略工厂
 * 单例
 *
 * @author prik
 * @date 2019/7/18
 */
public class DiscountStrategyFactory {

    /**
     * private修饰的构造函数,防止使用者手动创建
     */
    private DiscountStrategyFactory() {
    }

    private static DiscountStrategyFactory factory = new DiscountStrategyFactory();

    private static Map<Integer, DiscountStrategy> strategyMap = new HashMap();

    static{
        strategyMap.put(Customer.TYPE_ORDINARY, new OrdinaryDiscountStrategy());
        strategyMap.put(Customer.TYPE_VIP, new VipDiscountStrategy());
        strategyMap.put(Customer.TYPE_PARTNER, new PartnerDiscountStrategy());
    }

    public DiscountStrategy creator(int customerType) {
        return strategyMap.get(customerType);
    }

    public static DiscountStrategyFactory getInstance() {
        return factory;
    }
}

/**
 * 上下文类
 *
 * @author prik
 * @date 2019/7/18
 */
public class DiscountContext {
    private static DiscountStrategyFactory strategyFactory = DiscountStrategyFactory.getInstance();
    
    public BigDecimal calDiscountPrice(BigDecimal originalPrice, int customerType) {
        DiscountStrategy strategy = strategyFactory.creator(customerType);
        return strategy.calDiscountPrice(originalPrice);
    }
}

/**
 * 测试类
 *
 * @author prik
 * @date 2019/7/18
 */
public class Test {
    public static void main(String[] args) {
        BigDecimal originalPrice = new BigDecimal(100);

        // 普通客户
        DiscountContext discountContext = new DiscountContext();
        BigDecimal price1 = discountContext.calDiscountPrice(originalPrice, 1);

        System.out.println("普通客户下单,原价:" + originalPrice + "元,应付款:" + price1 + "元");

        // vip客户
        BigDecimal price2 = discountContext.calDiscountPrice(originalPrice, 2);
        System.out.println("vip客户下单,原价:" + originalPrice + "元,应付款:" + price2 + "元");
    }
}

执行结果:
    普通客户,无优惠
    普通客户下单,原价:100元,应付款:100元
    VIP客户,九折优惠~
    vip客户下单,原价:100元,应付款:90.0元
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值