设计模式(行为型设计模式——策略模式)

设计模式(行为型设计模式——策略模式)

策略模式

基本定义

策略模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。

模式结构

  • Strategy 抽象策略类:所有策略类的父类,为所支持的策略算法声明了抽象方法。

  • ConcreteStrategy 具体策略类:实现了在抽象策略类中声明的方法。

  • Context 环境类:负责使用算法策略,其中维持了一个抽象策略类的引用实例。

代码实现

Strategy 抽象策略类
public abstract class Discount {
  //计算折扣抽象方法
    abstract double discountPrice(Double originalPrice);
}
ConcreteStrategy 具体策略类
//首单五折
public class FirstOrderDiscount extends Discount{

    double discount = 0.5; //五折

    @Override
    public double discountPrice(Double originalPrice) {
        return originalPrice * discount;
    }
}
//会员七折
public class MemberDiscount extends Discount{

    double discount = 0.7; //七折

    @Override
    public double discountPrice(Double originalPrice) {
        return originalPrice * discount;
    }
}
//前100名下单八折
public class Top100Discount extends Discount{

    double discount = 0.8; //八折

    @Override
    public double discountPrice(Double originalPrice) {
        return originalPrice * discount;
    }
}
Context 环境类
public class Context {
  //存储折扣算法
    public static Map<String, Discount> strategyMap = new ConcurrentHashMap<>();

    static {
        for (DiscountType discountType: DiscountType.values()){
            try {
                //基于反射创建全部折扣算法类
                strategyMap.put(discountType.toString(), (Discount) Class.forName(discountType.getClassName()).newInstance());
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    }

    //计算折扣
    public static double discountPrice(String type, Double originalPrice){
        return strategyMap.get(type).discountPrice(originalPrice);
    }

    //计算折扣
    public static double discountPrice(DiscountType type, Double originalPrice){
        return discountPrice(type.toString(), originalPrice);
    }
}

//折扣枚举类
public enum DiscountType {

    MEMBER("会员折扣", "com.yanyuan.gof.behavior.strategy.v2.MemberDiscount"),
    FIRST_ORDER("首次下单", "com.yanyuan.gof.behavior.strategy.v2.FirstOrderDiscount"),
    TOP100("前100名下单", "com.yanyuan.gof.behavior.strategy.v2.Top100Discount");

    private String name;

    private String className;

    DiscountType(String name, String className) {
        this.name = name;
        this.className = className;
    }

    public String getName() {
        return name;
    }

    public String getClassName() {
        return className;
    }
}
测试类
@Slf4j
public class Test {
    public static void main(String[] args) {
        Double originalPrice = 200d;
        //首次下单
        DiscountType type = DiscountType.FIRST_ORDER;
        double price = Context.discountPrice(type, originalPrice);
        log.info("尊敬的用户: 您所预定的游乐园门票使用 [{}] 折扣, 原价{} RMB, 折后价格 {} RMB ",  type.getName(), originalPrice, price);

        //会员折扣
        type = DiscountType.MEMBER;
        price = Context.discountPrice(type, originalPrice);
        log.info("尊敬的用户: 您所预定的游乐园门票使用 [{}] 折扣, 原价{} RMB, 折后价格 {} RMB ",  type.getName(), originalPrice, price);
    }
}
输出结果

尊敬的用户: 您所预定的游乐园门票使用 [首次下单] 折扣, 原价200.0 RMB, 折后价格 100.0 RMB 尊敬的用户:
您所预定的游乐园门票使用 [会员折扣] 折扣, 原价200.0 RMB, 折后价格 140.0 RMB

优点

  • 多重条件语句不易维护,而使用策略模式可以避免使用多重条件语句。

  • 策略模式提供了一系列的可供重用的算法族,恰当使用继承可以把算法族的公共代码转移到父类里面,从而避免重复的代码。

  • 策略模式可以提供相同行为的不同实现,客户可以根据不同时间或空间要求选择不同的。

  • 策略模式提供了对开闭原则的完美支持,可以在不修改原代码的情况下,灵活增加新算法。

  • 策略模式把算法的使用放到环境类中,而算法的实现移到具体策略类中,实现了二者的分离。

缺点

  • 客户端必须理解所有策略算法的区别,以便适时选择恰当的算法类。

  • 策略模式造成很多的策略类。

使用场景

  • 一个系统需要动态地在几种算法中选择一种时,可将每个算法封装到策略类中。

  • 一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现,可将每个条件分支移入它们各自的策略类中以代替这些条件语句。

  • 系统中各算法彼此完全独立,且要求对客户隐藏具体算法的实现细节时。

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值