I was tinkering with an example of the strategy pattern that can be found below.
from __future__ import annotations
from abc import ABC, abstractmethod
from typing import List
class Context():
    def __init__(self,strategy: Strategy) -> None:
        self._strategy = strategy
    @property
    def strategy(self) -> Strategy:
        return self._strategy
    
    @strategy.setter
    def strategy(self, strategy: Strategy) -> None:
        self._strategy = strategy
    
    def do_some_business_logic(self) -> None:
        print("Context: Sorting data using the strategy (not sure how it'll do it)")
        result = self._strategy.do_algorithm(["a", "b", "c", "d", "e"])
        print(",".join(result))
class Strategy(ABC):
    @abstractmethod 
    def do_algorithm(self, data:List):
        pass
class ConcreteStrategyA(Strategy):
    def do_algorithm(self, data: List) -> List:
        return sorted(data)
class ConcreteStrategyB(Strategy):
    def do_algorithm(self, data: List) -> List:
        return reversed(sorted(data))
if __name__ == "__main__":
    context = Context(ConcreteStrategyA())
    print("Client: Strategy is set to normal sorting.")
    context.do_some_business_logic()
    print()
    print("Client: Strategy is set to reverse sorting.")
    context.strategy = ConcreteStrategyB()
    context.do_some_business_logic()
Why are ABC and abstract method used? I tried to take it away from the code and the code still works. What does it add?
 
     
    