目录
1.什么是策略模式
策略模式(Strategy Pattern)是一种行为设计模式,它定义了一系列算法,并将每个算法封装到独立的策略类中,使得它们可以互相替换。它可以提高代码的可维护性和灵活性。
2.策略模式有什么缺点
2.1 增加系统的复杂性
假设我们要开发一个电商平台,它需要计算订单的运费。为了适应不同的运费计算规则,我们使用策略模式,每个运费规则是一个策略类。
FreeShippingStrategy
:免费配送策略。FlatRateShippingStrategy
:固定运费策略。WeightBasedShippingStrategy
:基于重量的运费策略。DistanceBasedShippingStrategy
:基于距离的运费策略。
存在的问题:
随着业务的扩展,我们可能需要添加更多的运费策略(例如基于会员等级、节假日优惠等),导致系统中策略类的数量急剧增加,类的管理变得复杂,难以维护。
2.2 客户端需要了解不同的策略
针对上述电商系统,现在有一个客户端需要选择合适的运费策略,那么客户端代码必须了解所有的运费策略,并根据不同的订单条件来选择合适的策略。例如:
if (order.isFree()) {
shippingStrategy = new FreeShippingStrategy();
} else if (order.isDistance()) {
shippingStrategy = new DishtanceBasedShippingStrategy();
} else if (order.isHeavy()) {
shippingStrategy = new WeightBasedShippingStrategy();
} else {
shippingStrategy = new FlatRateShippingStrategy();
}
存在的问题:
这种情况下,客户端代码变得复杂,且增加了策略选择的逻辑。如果以后有新的运费策略,还需要修改客户端代码,违反了开闭原则。
2.3 策略切换开销
假设有一个实时推荐系统,它根据用户的行为数据实时调整推荐算法(策略)。推荐算法可能包括基于协同过滤的策略、基于内容的策略、基于用户历史的策略等。
存在的问题:
如果推荐系统在短时间内需要频繁地切换策略,例如每分钟都需要重新评估并选择不同的推荐算法,就会导致频繁的策略实例化和销毁,增加系统的性能开销。
2.4 策略的冗余
假设我们有一个人力资源系统,负责计算不同类型员工的薪资。为了灵活应对各种薪资的计算规则,我们使用策略模式,每个薪资计算规则都被封装为一个策略类。
FullTimeEmployeeSalaryStrategy
:全职员工薪资计算策略。PartTimeEmployeeSalaryStrategy
:兼职员工薪资计算策略。ContractorSalaryStrategy
:合同工薪资计算策略。
策略类的实现:
// 全职员工薪资策略
public class FullTimeEmployeeSalaryStrategy implements SalaryStrategy {
@Override
public double calculateSalary(Employee employee) {
return employee.getBaseSalary() + employee.getBonus();
}
}
// 兼职员工薪资策略
public class PartTimeEmployeeSalaryStrategy implements SalaryStrategy {
@Override
public double calculateSalary(Employee employee) {
return employee.getHourlyRate() * employee.getHoursWorked();
}
}
// 合同工薪资策略
public class ContractorSalaryStrategy implements SalaryStrategy {
@Override
public double calculateSalary(Employee employee) {
return employee.getHourlyRate() * employee.getHoursWorked() + employee.getContractBonus();
}
}
存在的问题:
假设后来公司决定引入另一种员工类型,比如实习生,他们的薪资计算与兼职员工非常相似,只是薪资中需要额外考虑一个小额的交通补贴。
我们可能会因此创建一个新的策略类 InternSalaryStrategy,实现如下:
// 实习生薪资策略
public class InternSalaryStrategy implements SalaryStrategy {
@Override
public double calculateSalary(Employee employee) {
return employee.getHourlyRate() * employee.getHoursWorked() + employee.getTransportationAllowance();
}
}
以上大部分代码都是相同的。随着员工类型的增加,这种冗余会更加明显,导致维护这些策略类变得困难,增加了系统的复杂度。
2.5 违反开闭原则
假设我们在一个支付系统中使用策略模式来处理不同的支付方式,每个支付方式是一个策略类,例如信用卡支付、支付宝支付、微信支付等。
存在的问题:
如果我们想要增加一种新的支付方式(例如比特币支付),我们不仅需要增加一个新的策略类,还需要修改客户端代码以支持这种新的支付方式。这样就不符合开闭原则了(对扩展开放,对修改关闭)。
public class PaymentProcessor {
public void processPayment(Order order) {
PaymentStrategy strategy;
switch (order.getPaymentType()) {
case "CreditCard":
strategy = new CreditCardPaymentStrategy();
break;
case "Alipay":
strategy = new AlipayPaymentStrategy();
break;
case "WeChatPay":
strategy = new WeChatPayPaymentStrategy();
break;
case "Bitcoin": // 新增支付方式
strategy = new BitcoinPaymentStrategy();
break;
default:
throw new UnsupportedOperationException("不支持的支付方式!!");
}
strategy.pay(order);
}
}
每当新增一种支付方式时,都需要修改 PaymentProcessor
类中的 switch
语句,这违背了开闭原则。