优雅实现策略模式; 在awesome-python上有一个关于模式设计的包,对包中的代码做了一点修改。BaseStrateby最核心的方法是select.
# -*- coding: utf-8 -*-
"""
http://stackoverflow.com/questions/963965/how-is-this-strategy-pattern
-written-in-python-the-sample-in-wikipedia
In most of other languages Strategy pattern is implemented via creating some
base strategy interface/abstract class and subclassing it with a number of
concrete strategies (as we can see at
http://en.wikipedia.org/wiki/Strategy_pattern), however Python supports
higher-order functions and allows us to have only one class and inject
functions into it's instances, as shown in this example.
"""
import types
import random
class BaseStrategy:
def __init__(self, func=None):
if func is not None:
self.select(func)
def __call__(self, *args, **kwargs):
self.execute(*args, **kwargs)
def execute(self, *args, **kwargs):
pass
def select(self, func):
# redefine a method
self.execute = types.MethodType(func, self)
class StrategyExample(BaseStrategy):
def __init__(self, func=None):
self.name = 'Strategy Example 0'
if func is not None:
self.select(func)
def execute(self, arg='nothing'):
print(arg)
def make(self):
self.select(execute_replacement1)
def random(self):
r = random.random()
if r > 0.5:
self.select(execute_replacement1)
else:
self.select(execute_replacement2)
# strategies
def execute_replacement1(obj, s=' from execute'):
print(obj.name + s + '1')
def execute_replacement2(obj, s=' from execute'):
print(obj.name + s + '2')
class SubStrategy(StrategyExample):
def __init__(self, func=None):
super(SubStrategy, self).__init__(func)
self.name = 'Strategy Example x'
if __name__ == '__main__':
strat0 = StrategyExample()
stratx = SubStrategy()
stratx()
strat1 = StrategyExample(execute_replacement1)
strat1.name = 'Strategy Example 1'
strat2 = StrategyExample(execute_replacement2)
strat2.name = 'Strategy Example 2'
strat0()
strat1()
strat2()
strat2.select(execute_replacement1)
strat2()
for k in range(5):
stratx = SubStrategy()
stratx.random()
stratx('shit')
### OUTPUT ###
# nothing
# nothing
# Strategy Example 1 from execute 1
# Strategy Example 2 from execute 2
# Strategy Example 2 from execute 1
# Strategy Example xshit
# Strategy Example xshit
# Strategy Example xshit
# Strategy Example xshit
# Strategy Example xshit