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'}