动态策略模式是一种设计模式,它允许在运行时根据具体情况选择不同的算法或策略。这种模式通常用于解决需要在运行时根据条件选择不同行为的问题。策略模式的核心思想是将算法封装成独立的对象,然后可以在运行时轻松地替换这些对象,从而改变行为。
主要组成部分
- Context(上下文):这是使用策略对象的类。它维护对策略对象的引用,并使用策略对象提供的接口。
- Strategy(策略接口):这是一个接口或抽象类,定义了所有具体策略类共同的方法。
- Concrete Strategy(具体策略):实现了策略接口的具体类,每个具体策略类提供了一种具体的算法实现。
动态策略模式的特点
- 灵活性:可以在运行时动态地选择和切换策略。
- 扩展性:新增策略非常容易,只需要增加一个新的具体策略类即可。
- 解耦:上下文与具体的策略实现解耦,上下文只依赖于策略接口。
示例
下面是一个使用 Python 和 PHP 实现动态策略模式的例子。假设我们有一个价格计算系统,需要根据不同的折扣策略来计算最终价格。
Python 实现
from abc import ABC, abstractmethod
# 策略接口
class DiscountStrategy(ABC):
@abstractmethod
def apply_discount(self, price: float) -> float:
pass
# 具体策略
class NoDiscount(DiscountStrategy):
def apply_discount(self, price: float) -> float:
return price
class TenPercentDiscount(DiscountStrategy):
def apply_discount(self, price: float) -> float:
return price * 0.9
class TwentyPercentDiscount(DiscountStrategy):
def apply_discount(self, price: float) -> float:
return price * 0.8
# 上下文
class PriceCalculator:
def __init__(self, strategy: DiscountStrategy):
self._strategy = strategy
def set_strategy(self, strategy: DiscountStrategy):
self._strategy = strategy
def calculate_final_price(self, original_price: float) -> float:
return self._strategy.apply_discount(original_price)
# 测试代码
calculator = PriceCalculator(NoDiscount())
original_price = 100.0
print(f"Original Price: ${original_price}")
print(f"Final Price with No Discount: ${calculator.calculate_final_price(original_price)}")
calculator.set_strategy(TenPercentDiscount())
print(f"Final Price with 10% Discount: ${calculator.calculate_final_price(original_price)}")
calculator.set_strategy(TwentyPercentDiscount())
print(f"Final Price with 20% Discount: ${calculator.calculate_final_price(original_price)}")
PHP 实现
<?php
// 策略接口
interface DiscountStrategy {
public function applyDiscount(float $price): float;
}
// 具体策略
class NoDiscount implements DiscountStrategy {
public function applyDiscount(float $price): float {
return $price;
}
}
class TenPercentDiscount implements DiscountStrategy {
public function applyDiscount(float $price): float {
return $price * 0.9;
}
}
class TwentyPercentDiscount implements DiscountStrategy {
public function applyDiscount(float $price): float {
return $price * 0.8;
}
}
// 上下文
class PriceCalculator {
private $strategy;
public function __construct(DiscountStrategy $strategy) {
$this->strategy = $strategy;
}
public function setStrategy(DiscountStrategy $strategy) {
$this->strategy = $strategy;
}
public function calculateFinalPrice(float $originalPrice): float {
return $this->strategy->applyDiscount($originalPrice);
}
}
// 测试代码
$calculator = new PriceCalculator(new NoDiscount());
$originalPrice = 100.0;
echo "Original Price: $" . $originalPrice . "\n";
echo "Final Price with No Discount: $" . $calculator->calculateFinalPrice($originalPrice) . "\n";
$calculator->setStrategy(new TenPercentDiscount());
echo "Final Price with 10% Discount: $" . $calculator->calculateFinalPrice($originalPrice) . "\n";
$calculator->setStrategy(new TwentyPercentDiscount());
echo "Final Price with 20% Discount: $" . $calculator->calculateFinalPrice($originalPrice) . "\n";
?>
解释
在上述两个示例中:
- DiscountStrategy 是一个策略接口,定义了一个
apply_discount
或applyDiscount
方法。 - NoDiscount, TenPercentDiscount, 和 TwentyPercentDiscount 是具体的策略类,分别实现了不同的折扣算法。
- PriceCalculator 是上下文类,它维护了一个策略对象,并提供了一个
calculate_final_price
或calculateFinalPrice
方法来计算最终价格。 - 测试代码 创建了一个
PriceCalculator
对象,并在运行时动态地更换不同的折扣策略,从而计算出不同的最终价格。
通过这种方式,动态策略模式允许我们在运行时灵活地选择和切换不同的策略,提高了代码的灵活性和扩展性。