Strategy
- hivecore.patterns.Strategy(cls: Type) Type
Decorator to indicate that a class is a strategy.
- Parameters:
cls (Type) – The class to decorate.
- Returns:
The decorated class indicating it as a strategy.
- Return type:
Type
Context
- hivecore.patterns.Context(cls: Type) Type
Decorator to add a set_strategy method to a class, allowing it to set and inherit behavior from a strategy.
- Parameters:
cls (Type) – The class to decorate.
- Returns:
The class decorated with the set_strategy method.
- Return type:
Type
ConcreteStrategy
- hivecore.patterns.ConcreteStrategy(methods: str | Callable | dict, custom_strategy: str | None = None) Callable[[Type], Type]
Decorator to add strategy methods to a class, allowing it to dynamically switch behavior.
- Parameters:
methods (Union[str, Callable, dict]) – The strategy method(s) to add. Can be a single method, a dictionary of multiple methods, or a string representing a method name.
custom_strategy (Optional[str]) – The custom name for the strategy method. Only applicable when methods is a single method.
- Returns:
The class decorated with the added strategy method(s).
- Return type:
Callable[[Type], Type]
Example
To implement the strategy pattern, the library provides decorators to define strategies and a context class to set and execute the chosen strategy. The decorators allow for multi-method strategies or single-method strategies. The example demonstrates the usage of both types of strategies.
Defining Strategies
We define a multi-method strategy using the @ConcreteStrategy decorator and the outside_strategy function:
def outside_strategy(self, *args, **kwargs):
print("Executing outside_strategy")
print("Args:", args)
print("Kwargs:", kwargs)
@ConcreteStrategy({"process_a": outside_strategy, "process_b": "internal_strategy_a"})
class ConcreteStrategyA:
def internal_strategy_a(self, *args, **kwargs):
print("Executing ConcreteStrategyA's internal_strategy")
print("Args:", args)
print("Kwargs:", kwargs)
We define a single-method strategy using the @ConcreteStrategy decorator and the internal_strategy method:
@ConcreteStrategy("internal_strategy", "my_strategy")
class ConcreteStrategyA:
def internal_strategy(self, *args, **kwargs):
print("Executing ConcreteStrategyA's internal_strategy")
print("Args:", args)
print("Kwargs:", kwargs)
Setting and Executing Strategies
We create a context class using the @Context decorator:
@Context
class Context_:
def __init__(self):
pass
We create an instance of the context class and set the strategy to an instance of ConcreteStrategyA:
context = Context_()
context.set_strategy(ConcreteStrategyA())
print(context.__dir__())
context.process_a("Argument 1", "Argument 2", key1="Value 1", key2="Value 2")
context.process_b("Argument 1", "Argument 2", key1="Value 1", key2="Value 2")
Output
----------------------------------------------------------------------------------------------------
EXAMPLE: Multi Method
----------------------------------------------------------------------------------------------------
['strategy', 'internal_strategy_a', 'process_a', 'process_b', '__module__', '__init__', '__dict__', '__weakref__', '__doc__', 'set_strategy', '__new__', '__repr__', '__hash__', '__str__', '__getattribute__', '__setattr__', '__delattr__', '__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__', '__reduce_ex__', '__reduce__', '__subclasshook__', '__init_subclass__', '__format__', '__sizeof__', '__dir__', '__class__']
Executing ConcreteStrategyA's process_b
Executing ConcreteStrategyA's process_b
----------------------------------------------------------------------------------------------------
EXAMPLE: Single Method
----------------------------------------------------------------------------------------------------
Executing ConcreteStrategyA's internal_strategy
Args: ('Argument 1', 'Argument 2')
Kwargs: {'key1': 'Value 1', 'key2': 'Value 2'}