前言
在开发过程中,经常不得不使用if else逻辑判断语句,太多的 if…else增加了代码的可读性,这时你可能需要策略模式来帮助你!
1.概念
策略模式(Strategy Pattern)是一种行为型设计模式,它定义了一簇算法,将每个算法都封装起来,并且使它们之间可以互换。策略模式使得算法的变化独立于使用算法的客户端。
结构
-
环境类(Context): 持有一个策略对象,并在需要时调用策略对象的方法。环境类通常会将客户端的请求委托给策略对象。
-
策略接口(Strategy): 声明算法的接口,所有具体策略类都实现这个接口。
-
具体策略类(Concrete Strategy): 实现策略接口,提供具体的算法实现
2.基本用法
- 定义策略接口
- 实现具体的策略类
- 创建上下文类即环境类
- 通过调用环境类切换不同策略
定义策略接口和实现具体的策略类很好理解,重点在于环境类的构造方法形参是策略接口,使用时,通过调用环境类时传入的形参类型切换不同的策略模式。
3.代码示例
下面是一个商场销售的场景,要求根据不同的促销策略计算商品的最终价格。
示例中,PriceCalculator 是环境类,它持有一个具体的策略对象(PricingStrategy),并在需要时调用策略对象的方法。客户端可以根据不同的情况切换不同的策略,而不影响 PriceCalculator 的使用。这样,我们实现了算法的独立变化,使得系统更加灵活。
// 先定义一个策略接口,里面定义一个计算商品最终价格的抽象方法。
public interface PricingStrategy {
double calculatePrice(double originalPrice);
}
// 具体策略类 - 普通折扣策略
public class DiscountStrategy implements PricingStrategy {
private double discountRate;
public DiscountStrategy(double discountRate) {
this.discountRate = discountRate;
}
public double calculatePrice(double originalPrice) {
return originalPrice * (1 - discountRate);
}
}
// 具体策略类 - 满减策略
public class FullReductionStrategy implements PricingStrategy {
private double fullAmount;
private double reductionAmount;
public FullReductionStrategy(double fullAmount, double reductionAmount) {
this.fullAmount = fullAmount;
this.reductionAmount = reductionAmount;
}
public double calculatePrice(double originalPrice) {
return originalPrice >= fullAmount ? originalPrice - reductionAmount : originalPrice;
}
}
// 环境类
public class PriceCalculator {
private PricingStrategy pricingStrategy;
//调用环境类时传入一个PricingStrategy 形参,具体策略由PricingStrategy的实现类决定
public PriceCalculator(PricingStrategy pricingStrategy) {
this.pricingStrategy = pricingStrategy;
}
//通过setPricingStrategy方法切换策略
public void setPricingStrategy(PricingStrategy pricingStrategy) {
this.pricingStrategy = pricingStrategy;
}
//调用具体策略
public double calculateFinalPrice(double originalPrice) {
return pricingStrategy.calculatePrice(originalPrice);
}
}
// 客户端使用
public class Client {
public static void main(String[] args) {
// 创建具体策略对象
PricingStrategy discountStrategy = new DiscountStrategy(0.2);
PricingStrategy fullReductionStrategy = new FullReductionStrategy(100, 20);
// 创建环境类
PriceCalculator calculator = new PriceCalculator(discountStrategy);
// 计算最终价格
double finalPrice1 = calculator.calculateFinalPrice(100);
System.out.println("Final Price 1: " + finalPrice1);
// 切换策略
calculator.setPricingStrategy(fullReductionStrategy);
// 再次计算最终价格
double finalPrice2 = calculator.calculateFinalPrice(150);
System.out.println("Final Price 2: " + finalPrice2);
}
}
4.策略模式的优点与缺点
优点 | 描述 |
---|---|
***避免使用条件语句 | 使用策略模式可以避免大量的条件语句,提高代码的可读性和可维护性,这是使用策略模式的主要原因。 |
灵活性和可扩展性 | 策略模式使得算法独立于客户端而变得可替换和可扩展,因此系统更加灵活。 |
符合开闭原则 | 新的策略可以通过实现新的策略类来添加,而无需修改上下文类的代码,符合开闭原则。 |
缺点 | 描述 |
---|---|
类数量增加 | - 每个具体策略需一个独立策略类,可能增加类的数量。 |
客户端需要了解不同的策略 | - 客户端需了解所有策略类,选择合适策略可能增加复杂性。 |
通信开销 | - 切换策略时可能涉及上下文类与策略类之间的通信开销。 |
逻辑分散 | - 将算法逻辑分散到不同策略类,可能导致简单算法过度拆分。 |
5.总结
步骤 | 描述 |
---|---|
定义策略接口 | 确定共同的操作接口,各具体策略类将实现这一接口。 |
实现具体的策略类 | 为每个具体算法创建独立的策略类,分别实现策略接口中定义的操作。 |
创建上下文类(环境类) | 上下文类包含一个策略接口的引用,并提供一个方法用于切换不同的策略。 |
设置策略 | 在客户端中,创建具体的策略对象,并将其设置到上下文类中,用于指定当前使用的算法。 |
调用策略方法 | 通过上下文类调用策略的方法,执行具体的算法。 |
切换策略 | 在运行时,可以动态切换策略,更换当前的算法实现。 |
优势 | 通过策略模式,实现了算法的独立性和可维护性,客户端可以灵活地选择和切换算法,不影响上下文类的代码。 |