Паттерн "Стратегия" через наследование в Python реализуется созданием абстрактного базового класса (или интерфейса) для стратегий, и затем конкретные реализации стратегий наследуются от этого класса. Каждый подкласс переопределяет общий метод, реализуя свою логику. Контекстный класс содержит ссылку на объект стратегии и делегирует ему выполнение задачи.
class Strategy:
def execute(self, data):
raise NotImplementedError
class ConcreteStrategyA(Strategy):
def execute(self, data):
return f"Стратегия A: {data}"
class ConcreteStrategyB(Strategy):
def execute(self, data):
return f"Стратегия B: {data}"
class Context:
def __init__(self, strategy):
self.strategy = strategy
def process_data(self, data):
return self.strategy.execute(data)
# Пример использования
strategy_a = ConcreteStrategyA()
context = Context(strategy_a)
print(context.process_data("Некие данные")) # => Стратегия A: Некие данные
strategy_b = ConcreteStrategyB()
context.strategy = strategy_b # Изменение стратегии "на лету"
print(context.process_data("Другие данные")) # => Стратегия B: Другие данные
Основное преимущество: простота реализации при небольшом количестве стратегий. Недостатки: жесткая связь, необходимость изменять контекст при добавлении новых стратегий, усложнение структуры классов при большом количестве стратегий.
Паттерн "Стратегия" позволяет определить семейство алгоритмов, инкапсулировать каждый из них и сделать их взаимозаменяемыми. Он позволяет алгоритму изменяться независимо от клиентов, которые его используют. При реализации с использованием наследования в Python мы создаем абстрактный базовый класс (интерфейс стратегии) и конкретные классы стратегий, наследующиеся от него.
Вот пример реализации:
# Абстрактный базовый класс (интерфейс стратегии)
class Strategy:
def execute(self, data):
raise NotImplementedError("Метод execute должен быть реализован в подклассе")
# Конкретные стратегии
class ConcreteStrategyA(Strategy):
def execute(self, data):
return f"ConcreteStrategyA: Отсортировано по возрастанию: {sorted(data)}"
class ConcreteStrategyB(Strategy):
def execute(self, data):
return f"ConcreteStrategyB: Отсортировано по убыванию: {sorted(data, reverse=True)}"
class ConcreteStrategyC(Strategy):
def execute(self, data):
return f"ConcreteStrategyC: Сумма элементов: {sum(data)}"
# Контекст, использующий стратегию
class Context:
def __init__(self, strategy):
self._strategy = strategy
def set_strategy(self, strategy):
self._strategy = strategy
def process_data(self, data):
return self._strategy.execute(data)
# Пример использования
if __name__ == "__main__":
data = [5, 2, 8, 1, 9]
# Использование Strategy A
context = Context(ConcreteStrategyA())
result_a = context.process_data(data)
print(result_a) # Output: ConcreteStrategyA: Отсортировано по возрастанию: [1, 2, 5, 8, 9]
# Использование Strategy B
context.set_strategy(ConcreteStrategyB())
result_b = context.process_data(data)
print(result_b) # Output: ConcreteStrategyB: Отсортировано по убыванию: [9, 8, 5, 2, 1]
# Использование Strategy C
context.set_strategy(ConcreteStrategyC())
result_c = context.process_data(data)
print(result_c) # Output: ConcreteStrategyC: Сумма элементов: 25
Пояснения:
Преимущества использования наследования для "Стратегии":
Недостатки использования наследования для "Стратегии":
Альтернативы наследованию:
В заключение, реализация паттерна "Стратегия" с помощью наследования возможна, но важно учитывать недостатки и альтернативы, особенно при работе с большим количеством стратегий или сложной логикой.