CODESAMPLE
Policy - Python
The Policy pattern allows for runtime modification of object behavior without altering the object’s code. It achieves this by encapsulating the behavior within separate policy classes, and allowing the object to accept different policies as needed. This promotes flexibility and adheres to the Open/Closed Principle.
The Python example defines a Subject class representing the object whose behavior is to be modified. A Policy abstract base class defines the interface for behaviors. Concrete policies like ValidationPolicy and LoggingPolicy implement this interface. The Subject accepts a policy during initialization and delegates behavior to it. This is idiomatic Python due to its use of duck typing and ABCs for defining interfaces, and its flexible nature allows for easy extension with new policies.
from abc import ABC, abstractmethod
import logging
logging.basicConfig(level=logging.INFO)
class Policy(ABC):
@abstractmethod
def execute(self, data):
pass
class ValidationPolicy(Policy):
def __init__(self, rules):
self.rules = rules
def execute(self, data):
for rule in self.rules:
if not rule(data):
raise ValueError("Data validation failed.")
return data
class LoggingPolicy(Policy):
def execute(self, data):
logging.info(f"Data processed: {data}")
return data
class Subject:
def __init__(self, policy: Policy):
self.policy = policy
def process_data(self, data):
return self.policy.execute(data)
# Example Usage
def is_positive(data):
return data > 0
def is_string(data):
return isinstance(data, str)
if __name__ == "__main__":
# Process a positive number with validation and logging
validation_policy = ValidationPolicy([is_positive])
logging_policy = LoggingPolicy()
# Combine policies (chain of responsibility style)
combined_policy = lambda data: logging_policy.execute(validation_policy.execute(data))
subject = Subject(combined_policy)
try:
result = subject.process_data(5)
print(f"Processed data: {result}")
except ValueError as e:
print(f"Error: {e}")
try:
result = subject.process_data(-2)
print(f"Processed data: {result}")
except ValueError as e:
print(f"Error: {e}")
# Process a string with only logging
subject = Subject(logging_policy)
result = subject.process_data("Hello, Policy Pattern!")
print(f"Processed data: {result}")