Strategy Pattern in Python

The strategy pattern in Python is a behavioral design pattern that allows the selection of algorithms or behaviors at runtime. This pattern is very useful in scenarios such as testing frameworks, rule engines, and business logic processing.The traditional if-else approach for writing an assertion comparison function is very verbose:

def compare(operator, actual, expected):    if operator == '==':        return actual == expected    elif operator == '!=':        return actual != expected    elif operator == '>':        return actual > expected    elif operator == '<':        return actual < expected    elif operator == '>=':        return actual >= expected    elif operator == '<=':        return actual <= expected    elif operator == 'in':        return actual in expected    elif operator == 'not in':        return actual not in expected    elif operator == 'is':        return actual is expected    elif operator == 'is not':        return actual is not expected    elif operator == 'contains':        return expected in actual    elif operator == 'startswith':        return actual.startswith(expected)    elif operator == 'endswith':        return actual.endswith(expected)    elif operator == 'regex':        return re.search(expected, actual) is not None    elif operator == 'not regex':        return re.search(expected, actual) is None       else:        raise ValueError(f"Unsupported operator: {operator}")

Converting it to use the strategy pattern:

def compare(self, **kwargs):    comparators = {        '==': lambda a, b: a == b,        '!=': lambda a, b: a != b,        '>': lambda a, b: a > b,        '<': lambda a, b: a < b,        '>=': lambda a, b: a >= b,        '<=': lambda a, b: a <= b,        'in': lambda a, b: a in b,        'not in': lambda a, b: a not in b,        'is': lambda a, b: a is b,        'is not': lambda a, b: a is not b,        'contains': lambda a, b: b in a,        'not contains': lambda a, b: b not in a,        'startswith': lambda a, b: a.startswith(b),        'endswith': lambda a, b: a.endswith(b),        'regex': lambda a, b: re.search(b, a) is not None,        'not regex': lambda a, b: re.search(b, a) is None    }

Calling the strategy pattern:

comparators[operators](kwargs['actual'], kwargs['expected'])# Equality comparisonoperators = '=='actual = 5expected = 5result = comparators[operators](actual, expected)print(result)# Contains comparisonoperators = 'contains'actual = "abcdefg"expected = "ab"result = comparators[operators](actual, expected)print(result)

The execution process is as follows:

# Step 1: Get the function object from the dictionary# For example: operators = '=='function_obj = comparators[operators] # Step 2: Call the retrieved functionresult = function_obj(kwargs['actual'], kwargs['expected'])

This is equivalent to the traditional function call:

# Equivalent to: if operators == '==':     result = kwargs['actual'] == kwargs['expected'] elif operators == 'in':     result = kwargs['actual'] in kwargs['expected']

Leave a Comment