【Java设计模式-4】策略模式,消灭if/else迷宫的利器
各位Java编程小伙伴们!今天咱们要一起探索一个超级厉害的Java设计模式——策略模式,它就像是一把神奇的魔法剑,专门用来斩断那些让我们代码变得乱糟糟的if/else语句迷宫!
一、if/else
的烦恼
在编程的奇妙世界里,我们常常会遇到这样的情况:要根据不同的条件执行不同的操作,这时候,if/else语句就像我们最先想到的武器,冲上去就一顿猛操作。比如说,你正在开发一个电商系统。在计算商品价格的时候,根据不同的用户类型,有着不同的折扣策略。比如,普通用户可能没有折扣,会员用户打9折,VIP用户打8折。要是按照常规的写法,那代码可能就会是这样的:
public class PriceCalculator {
public double calculatePrice(double originalPrice, String userType) {
if ("普通用户".equals(userType)) {
return originalPrice;
} else if ("会员用户".equals(userType)) {
return originalPrice * 0.9;
} else if ("VIP用户".equals(userType)) {
return originalPrice * 0.8;
} else {
throw new IllegalArgumentException("未知的用户类型");
}
}
}
看着这段代码,一开始可能觉得还行呀,不就几个if/else嘛。但随着我们用户类型和折扣规则越来越多,这个方法就会变得越来越臃肿。每次新增一种用户,都得在这个长长的if/else链里添加新的判断分支,这不仅让代码变得又长又难看,而且维护起来简直是噩梦。要是不小心改错了一个判断条件或者顺序,那可就会出现各种奇怪的错误。
而且,这种写法的代码可读性也越来越差,就好比走进了一个错综复杂的迷宫,别人(包括未来的自己)要看懂这段代码得费好大的劲儿,得在那一堆if/else里来回穿梭,试图搞清楚每个分支到底是干嘛的。这可不行呀,我们的代码应该像一本清晰易懂的故事书,而不是让人头疼的谜题集呢。
二、策略模式来救场啦!
这时候,策略模式就闪亮登场啦!它的核心思想呢,就是把不同的算法或者策略封装成一个个独立的类,然后让这些类可以相互替换,这样就可以根据不同的情况灵活地选择使用哪个策略啦。
咱们就用上面电商系统的例子来看看怎么用策略模式改写吧。
第一步:定义策略接口
首先,我们要定义一个折扣策略的接口,所有具体的折扣策略都要实现这个接口。
public interface DiscountStrategy {
double calculateDiscount(double originalPrice);
}
这个接口里只有一个方法calculateDiscount
,用来根据原价计算出折扣后的价格。
第二步:实现具体策略类
接下来,我们就为不同的用户类型分别创建具体的折扣策略类。
普通用户折扣策略类:
public class NormalUserDiscountStrategy implements DiscountStrategy {
@Override
public double calculateDiscount(double originalPrice) {
return originalPrice;
}
}
对于普通用户,就是直接返回原价,没有折扣嘛。
会员用户折扣策略类:
public class MemberUserDiscountStrategy implements DiscountStrategy {
@Override
public double calculateDiscount(double originalPrice) {
return originalPrice * 0.9;
}
}
会员用户就按照9折来计算。
VIP用户折扣策略类:
public class VIPUserDiscountStrategy implements DiscountStrategy {
@Override
public double calculateDiscount(double originalPrice) {
return originalPrice * 0.8;
}
}
VIP用户则是8折优惠。
第三步:使用策略模式的上下文类
最后,我们还需要一个上下文类,这个类负责持有一个具体的折扣策略对象,并且提供一个方法来执行折扣计算。
public class PriceCalculatorContext {
private DiscountStrategy discountStrategy;
public PriceCalculatorContext(DiscountStrategy discountStrategy) {
this.discountStrategy = discountStrategy;
}
public double calculatePrice(double originalPrice) {
return discountStrategy.calculateDiscount(originalPrice);
}
}
现在,我们再来看看怎么使用这些类来计算商品价格吧。
public class Main {
public static void main(String[] args) {
double originalPrice = 100;
// 普通用户价格计算
PriceCalculatorContext normalContext = new PriceCalculatorContext(new NormalUserDiscountStrategy());
double normalPrice = normalContext.calculatePrice(originalPrice);
System.out.println("普通用户价格:" + normalPrice);
// 会员用户价格计算
PriceCalculatorContext memberContext = new PriceCalculatorContext(new MemberUserDiscountStrategy());
double memberPrice = memberContext.calculatePrice(originalPrice);
System.out.println("会员用户价格:" + memberPrice);
// VIP用户价格计算
PriceCalculatorContext vipContext = new PriceCalculatorContext(new VIPUserDiscountStrategy());
double vipPrice = vipContext.calculatePrice(originalPrice);
System.out.println("VIP用户价格:" + vipPrice);
}
}
这样一看,代码是不是清晰多啦?每个折扣策略都有自己独立的类,而且如果以后要增加新的用户类型或者修改折扣规则,只需要再创建一个新的策略类或者修改对应的策略类就可以了,完全不需要在那个乱糟糟的if/else
语句里折腾啦。
三、策略模式的应用场景
其实我们在SpringBoot实际开发中策略模式经常用到,我一说你就有共鸣了,以下是一些用到常见的地方:
1. 数据源配置(DataSource)
在Spring Boot中,当配置多个数据源时会涉及到策略模式的应用。例如,你可能有一个主数据源用于核心业务操作,还有一个从数据源用于读取数据等场景。
-
策略接口:
javax.sql.DataSource
接口可以看作是一种策略接口,它定义了获取数据库连接等相关操作的规范。不同的数据库驱动厂商(如MySQL、PostgreSQL等)实现这个接口来提供各自特定的数据源实现,这就是不同的“策略”。 -
具体策略实现:像
com.mysql.cj.jdbc.MysqlDataSource
(MySQL数据库的数据源实现)、org.postgresql.ds.PGDataSource
(PostgreSQL数据库的数据源实现)等都是具体的策略类,它们根据各自数据库的特性来实现DataSource
接口中规定的获取连接等操作。 -
上下文使用:在SpringBoot应用中,当你在配置文件中指定了要使用的数据库类型及相关连接参数后,Spring会根据这些信息自动装配相应的数据源实现(即选择合适的策略)。例如,通过
spring.datasource.url
、spring.datasource.username
等配置项,Spring会解析并装配对应的数据源,就如同在策略模式的上下文环境中根据具体情况选用合适的策略一样。
2. 消息队列集成(Message Queuing)
SpringBoot可以方便地与多种消息队列进行集成,如RabbitMQ、Kafka等,这里也用到了策略模式。
-
策略接口:例如,
org.springframework.amqp.core.AmqpTemplate
(用于RabbitMQ的消息发送和接收操作的接口)和org.springframework.kafka.core.KafkaTemplate
(用于Kafka的消息发送和接收操作的接口)等类似接口可以看作是不同消息队列的策略接口,它们定义了各自与对应消息队列进行交互的操作规范。 -
具体策略实现:像
org.springframework.amqp.rabbit.core.RabbitTemplate
(RabbitMQ的具体实现)、org.springframework.kafka.core.KafkaTemplate
(本身就是Kafka的具体实现)等都是不同的消息队列的具体策略类,它们根据各自消息队列的特性来实现相应接口规定的操作。 -
上下文使用:在应用的配置文件中指定要集成的消息队列类型及相关参数(如
spring.rabbitmq.host
等对于RabbitMQ的配置,spring.kafka.bootstrap.servers
等对于Kafka的配置),Spring Boot会根据这些信息自动装配相应的消息队列实现(即选择合适的策略),并在需要进行消息发送、接收等操作的地方应用该策略。
这些只是SpringBoot中应用策略模式的一部分例子,实际上在很多涉及到多种可选方案、根据不同条件选择不同处理方式的场景下,都可能会运用到策略模式来使得代码更加清晰、可维护和可扩展。
四、总结
策略模式真的是一个非常实用的设计模式,帮我们把那些杂乱无章的if/else
语句统统消灭掉,让我们的代码更加清晰、可维护、可扩展。以后在遇到类似根据不同情况选择不同算法或者行为的问题时,大家可别忘了试试策略模式哦。
好啦,今天关于策略模式的分享就到这里啦,希望小伙伴们都能在自己的代码世界里用好这个神奇的模式,写出更加优秀的程序哟!
上述内容只代表个人观点,不代表啥组织。本人致力于宣扬正能量,若因浏览出啥岔子,纯属无心之举,我马上就改正,可千万别上纲上线哈,愿大家开心每一天,peace & love~😜