1. 策略模式简介
策略模式是一种行为设计模式,它允许在运行时根据情况选择算法的行为。该模式通过定义一系列算法,并将每个算法封装在独立的类中,使得它们可以相互替换,而不影响客户端代码。策略模式将算法的选择与算法的实现分离开来,使得系统更加灵活,并且易于扩展。
2. 示例:【设计模式专题之策略模式】14. 超市打折
超市对促销商品经常推出各种五花八门的优惠策略,常见的有打折优惠以及满减优惠(详见链接内容),这时候我们除了使用“if-else”来选择不同的优惠方式之外,还可以使用策略模式更优雅地切换优惠方式。
2.1 UML图例
classDiagram
class DiscountContext {
__strategy: DiscountStrategy
__init__(strategy: DiscountStrategy): void
getStrategy(): DiscountStrategy
setStrategy(strategy: DiscountStrategy): void
discount(price: int)
}
class DiscountStrategy {
<<interface>>
discount(price: int): void
}
class TenPercentOffDiscount {
discount(price: int): void
}
class MiniumPurchaseDiscount {
discount(price: int): void
}
DiscountStrategy <|.. TenPercentOffDiscount
DiscountStrategy <|.. MiniumPurchaseDiscount
DiscountContext ..> TenPercentOffDiscount
DiscountContext ..> MiniumPurchaseDiscount
2.2 Python代码实现
from abc import ABC, abstractmethod
class DiscountStrategy(ABC):
@abstractmethod
def discount(self, price: int):
raise NotImplemented
class TenPercentOffDiscount(DiscountStrategy):
""" 九折优惠 """
def discount(self, price: int):
return price * 0.9
class MiniumPurchaseDiscount(DiscountStrategy):
""" 满减优惠 """
def discount(self, price: int):
if 100 <= price < 150:
return price - 5
if 150 <= price < 200:
return price - 15
if 200 <= price < 300:
return price - 25
if price >= 300:
return price - 40
class DiscountContext:
def __init__(self):
self.__strategy = None
@property
def strategy(self):
return self.__strategy
@strategy.setter
def strategy(self, s: DiscountStrategy):
self.__strategy = s
def discount(self, price: int):
p = self.__strategy.discount(price)
print(int(p))
def client():
ctx = DiscountContext()
n = int(input())
for _ in range(n):
price, strategyType = input().split()
price = int(price)
if strategyType == "1":
strategy = TenPercentOffDiscount()
else:
assert strategyType == "2"
strategy = MiniumPurchaseDiscount()
ctx.strategy = strategy
ctx.discount(price)
if __name__ == "__main__":
client()
3. 策略模式的结构
策略模式包含下面几个结构:
- 策略类
Strategy: 定义所有支持的算法的公共接口。 - 具体策略类
ConcreteStrategy: 实现了策略接口,提供具体的算法实现。 - 上下文类
Context: 包含一个策略实例,并在需要时调用策略对象的方法。
4. 优缺点及适用场景
-
优点:
- 提供了一种简洁的替代继承的方式,使得算法可以独立于客户端而变化。
- 降低了算法实现的复杂度,使得每个算法都可以被单独测试和理解。
- 方便在运行时切换不同的算法,提供了更大的灵活性和可扩展性。
-
缺点:
- 客户端需要了解所有的策略类,选择合适的策略类可能需要一定的判断逻辑。
- 增加了类的数量,可能会导致代码结构变得复杂。
-
适用场景:
- 当一个系统需要在多种算法之间切换时,且需要避免使用大量的条件语句时。
- 当一个类有多个行为,且这些行为在不同的情况下需要独立地变化时。
- 当一个类的算法需要频繁地变化时,策略模式可以使得算法的变化对客户端透明。