策略模式

52 阅读2分钟

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. 优缺点及适用场景

  • 优点

    • 提供了一种简洁的替代继承的方式,使得算法可以独立于客户端而变化。
    • 降低了算法实现的复杂度,使得每个算法都可以被单独测试和理解。
    • 方便在运行时切换不同的算法,提供了更大的灵活性和可扩展性。
  • 缺点

    • 客户端需要了解所有的策略类,选择合适的策略类可能需要一定的判断逻辑。
    • 增加了类的数量,可能会导致代码结构变得复杂。
  • 适用场景

    • 当一个系统需要在多种算法之间切换时,且需要避免使用大量的条件语句时。
    • 当一个类有多个行为,且这些行为在不同的情况下需要独立地变化时。
    • 当一个类的算法需要频繁地变化时,策略模式可以使得算法的变化对客户端透明。

5. 参考文章

  1. 卡码网设计模式-策略模式