行为型设计模式:策略模式
在软件开发中,我们经常会遇到需要根据不同场景实现同一功能的情况,而实现该功能可能存在多种算法或策略。传统的做法是将这些不同的算法或策略硬编码在一个类中,每个算法对应一个方法,或者将它们封装在一个方法内,通过条件语句(如 if-else 或 switch)来选择执行哪个。然而,当算法数量增多时,此类会变得臃肿且难以维护。若要添加新算法,还需要修改现有类的源代码,这违背了"开闭原则"(对扩展开放,对修改关闭)。
策略模式通过将算法抽象化并提供统一的接口来解决这个问题。每个具体的算法实现都封装在一个独立的类中。客户端代码可以通过注入不同的实现类来动态替换算法,从而提高了系统的可扩展性和灵活性。
模式定义 策略模式定义了一系列可互换的算法,并将每一个算法封装起来,使它们能够独立于使用它们的客户而变化。
应用场景示例:商品促销折扣 假设一家商场对不同会员等级的商品有不同的折扣策略。一件原价为 100 元的商品,根据会员等级会有不同的最终价格:
- 普通会员:无折扣,价格 100 元
- 白金会员:9 折优惠,价格 90 元
- 黄金会员:8 折优惠,价格 80 元
以下是使用策略模式实现的代码示例:
/**
* 定义计算商品价格的算法接口
*/
public interface DiscountStrategy {
/**
* 根据原价计算最终价格
* @param originalPrice 商品原价
* @return 计算后的价格
*/
double calculate(double originalPrice);
}
/**
* 普通会员折扣策略:无折扣
*/
public class NoDiscountStrategy implements DiscountStrategy {
@Override
public double calculate(double originalPrice) {
return originalPrice;
}
}
/**
* 白金会员折扣策略:9折
*/
public class PlatinumDiscountStrategy implements DiscountStrategy {
@Override
public double calculate(double originalPrice) {
return originalPrice * 0.9;
}
}
/**
* 黄金会员折扣策略:8折
*/
public class GoldDiscountStrategy implements DiscountStrategy {
@Override
public double calculate(double originalPrice) {
return originalPrice * 0.8;
}
}
/**
* 商场类,负责应用折扣策略
*/
public class Store {
private DiscountStrategy discountStrategy;
/**
* 设置当前的折扣策略
* @param discountStrategy 要应用的折扣策略
*/
public void setDiscountStrategy(DiscountStrategy discountStrategy) {
this.discountStrategy = discountStrategy;
}
/**
* 计算最终价格
* @param price 商品原价
* @return 应用策略后的价格
*/
public double checkout(double price) {
if (discountStrategy == null) {
throw new IllegalStateException("Discount strategy not set.");
}
return discountStrategy.calculate(price);
}
}
测试代码如下:
/**
* 策略模式测试类
*/
public class StrategyPatternTest {
public static void main(String[] args) {
testDiscounts();
}
public static void testDiscounts() {
Store store = new Store();
DiscountStrategy noDiscount = new NoDiscountStrategy();
DiscountStrategy platinumDiscount = new PlatinumDiscountStrategy();
DiscountStrategy goldDiscount = new GoldDiscountStrategy();
double itemPrice = 100.0;
// 普通会员结账
store.setDiscountStrategy(noDiscount);
System.out.println("普通会员购买,价格为:" + store.checkout(itemPrice));
// 白金会员结账
store.setDiscountStrategy(platinumDiscount);
System.out.println("白金会员购买,价格为:" + store.checkout(itemPrice));
// 黄金会员结账
store.setDiscountStrategy(goldDiscount);
System.out.println("黄金会员购买,价格为:" + store.checkout(itemPrice));
}
}
策略模式巧妙地利用了面向对象的继承和多态特性。通过将不同的算法封装在独立的类中并实现共同的接口,我们可以轻松地在运行时切换或添加新的策略,而无需修改现有的客户端代码。这符合里氏替换原则,即基类出现的地方,都可以被子类对象替换。