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

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

策略模式

基本定义

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

模式结构

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

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

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

代码实现

Strategy 抽象策略类
java 复制代码
public abstract class Discount {
  //计算折扣抽象方法
    abstract double discountPrice(Double originalPrice);
}
ConcreteStrategy 具体策略类
java 复制代码
//首单五折
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 环境类
java 复制代码
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;
    }
}
测试类
java 复制代码
@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

优点

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

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

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

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

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

缺点

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

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

使用场景

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

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

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

相关推荐
暗黑起源喵2 分钟前
设计模式-工厂设计模式
java·开发语言·设计模式
WaaTong7 分钟前
Java反射
java·开发语言·反射
九圣残炎40 分钟前
【从零开始的LeetCode-算法】1456. 定长子串中元音的最大数目
java·算法·leetcode
wclass-zhengge43 分钟前
Netty篇(入门编程)
java·linux·服务器
Re.不晚1 小时前
Java入门15——抽象类
java·开发语言·学习·算法·intellij-idea
雷神乐乐1 小时前
Maven学习——创建Maven的Java和Web工程,并运行在Tomcat上
java·maven
码农派大星。1 小时前
Spring Boot 配置文件
java·spring boot·后端
顾北川_野1 小时前
Android 手机设备的OEM-unlock解锁 和 adb push文件
android·java
江深竹静,一苇以航1 小时前
springboot3项目整合Mybatis-plus启动项目报错:Invalid bean definition with name ‘xxxMapper‘
java·spring boot
confiself2 小时前
大模型系列——LLAMA-O1 复刻代码解读
java·开发语言