19年之后由于某些原因断更了三年,23年重新扬帆起航,推出更多优质博文,希望大家多多支持~
古之立大事者,不惟有超世之才,亦必有坚忍不拔之志
个人CSND主页——Micro麦可乐的博客
《Docker实操教程》专栏以最新的Centos版本为基础进行Docker实操教程,入门到实战
《RabbitMQ》本专栏主要介绍使用JAVA开发RabbitMQ的系列教程,从基础知识到项目实战
《设计模式》专栏以实际的生活场景为案例进行讲解,让大家对设计模式有一个更清晰的理解
如果文章能够给大家带来一定的帮助!欢迎关注、评论互动~
我们先来思考一个问题,在日常开发中涉及到支付往往并非单纯的一个支付厂商,可能涉及支付宝、微信支付等等,再比如项目中根据用户的类型给予不同的折扣,如果你还在使用if -else
来进行支付类型、用户类型判断,那么请认真看完本篇内容,相信能让你有一个新的认识
我们还是以上述场景来模拟一个支付功能,在你们的项目中是否是这样子判断的,前端传递一个支付类型 payType
,在业务代码中判断这个类型从而执行对应的厂商支付
if ("ALIPAY".equals(payType)) {
//调用支付宝支付
} else if ("WECHAT_PAY".equals(payType)) {
//调用微信支付
} else if ("UNION_PAY".equals(payType)) {
//调用银联支付
} else if ...
从代码可以看出,如果设计到很多种支付类型,那么会出现大量的if-else
,着实是一件很影响性能的事情,有没有更好的方案可以替代?答案是有的!
在项目中我们可以使用枚举(enum
)来实现策略模式,并通过枚举常量来消除 if-else
语句,使代码更加灵活、可维护和可扩展,还是上述的支付场景,我们如何使用策略枚举更优雅的实现
定义策略枚举,分别定义 ALIPAY、WECHAT_PAY、UNION_PAY 代表支付宝、微信、银联支付
// 定义策略枚举
public enum PaymentStrategyEnum {
ALIPAY {
@Override
public String pay(int amount) {
System.out.println("使用支付宝支付: " + amount );
// 具体的支付逻辑
return "ALIPAY SUCCESS";
}
},
WECHAT_PAY {
@Override
public String pay(int amount) {
System.out.println("使用微信支付:" + amount);
// 具体的支付逻辑
return "WECHAT_PAY SUCCESS";
}
},
UNION_PAY {
@Override
public String pay(int amount) {
System.out.println("使用银联支付:" + amount);
// 具体的支付逻辑
return "WECHAT_PAY SUCCESS";
}
};
// 定义抽象方法
public abstract String pay(int amount);
}
定一个通用的调用支付类,传递枚举对象以及支付金额
public class CheckPay {
public String toPay(PaymentStrategyEnum paymentStrategyEnum, int amount) {
return paymentStrategyEnum.pay(amount);
}
}
前端唤起支付使用了哪个厂商的支付,就传递约定好的参数值,这里为了方便我们就直接以 ALIPAY、WECHAT_PAY、UNION_PAY 作为类型参数
演示代码
public class PayServiceTest {
public static void main(String[] args) {
// // 在应用中选择支付策略
// PaymentStrategyEnum alipay = PaymentStrategyEnum.ALIPAY;
// PaymentStrategyEnum wechatPay = PaymentStrategyEnum.WECHAT_PAY;
//
// alipay.pay(100);
// wechatPay.pay(150);
pay("ALIPAY",100);
pay("WECHAT_PAY",150);
pay("UNION_PAY",200);
}
public static String pay(String payType, int amount) {
CheckPay checkPay = new CheckPay();
return checkPay.toPay(PaymentStrategyEnum.valueOf(payType),amount);
}
}
最终输出效果
在这个示例中,通过使用枚举,每个支付方式都被表示为一个枚举常量,并且每个枚举常量都实现了抽象方法 pay
。这种方式可以消除传统的 if-else
语句,并通过直接调用枚举常量的方法来执行相应的支付逻辑。如果需要添加新的支付方式,只需简单地在枚举中添加新的常量即可。
通过上述支付的代码演示,我们可以思考一下针对不同的用户类型,给予不同的优惠折扣是否也可以使用这种模式?来看看简单的代码样列
// 用户类
class User {
private UserType userType;
public User(UserType userType) {
this.userType = userType;
}
public double calculateDiscount(double amount) {
return userType.calculateDiscount(amount);
}
}
// 用户类型的策略枚举
enum UserType {
REGULAR {
@Override
public double calculateDiscount(double amount) {
return amount * 0.1;
}
},
PREMIUM {
@Override
public double calculateDiscount(double amount) {
return amount * 0.2;
}
};
// 定义抽象方法
public abstract double calculateDiscount(double amount);
}
public class Main {
public static void main(String[] args) {
double amount = 100.0;
//这里模拟知道了用户类型
User regularUser = new User(UserType.REGULAR);
//User premiumUser = new User(UserType.PREMIUM);
double regularDiscount = regularUser.calculateDiscount(amount);
//double premiumDiscount = premiumUser.calculateDiscount(amount);
System.out.println("Regular User Discount: " + regularDiscount);
//System.out.println("Premium User Discount: " + premiumDiscount);
}
}
使用策略枚举可以很灵活处理各种复杂判断,且可读性与扩展性都比较好,它更像是函数式编程,即传进一个参数,就可以得到对应模式下返回的数值。这样的设计使得系统更具可读性、可维护性,也更符合开放/封闭原则。