如何在 Python 中编写与维基百科示例不同的策略模式? [英] How to write Strategy Pattern in Python differently than example in Wikipedia?
问题描述
在 2009 年维基百科条目中的策略模式,有一个例子 用 PHP 编写.
In the 2009 Wikipedia entry for the Strategy Pattern, there's a example written in PHP.
大多数其他代码示例执行以下操作:
Most other code samples do something like:
a = Context.new(StrategyA.new)
a.execute #=> Doing the task the normal way
b = Context.new(StrategyB.new)
b.execute #=> Doing the task alternatively
c = Context.new(StrategyC.new)
c.execute #=> Doing the task even more alternative
在 Python 代码中,提交按钮使用了不同的技术.我想知道如果 Python 代码也像其他代码示例那样做,它会是什么样子.
In the Python code a different technique is used with a Submit button. I wonder what the Python code will look like if it also did it the way the other code samples do.
更新:使用 Python 中的一流函数可以缩短吗?
Update: Can it be shorter using first-class functions in Python?
推荐答案
Python 中的示例与其他示例没有太大区别.模拟 PHP 脚本:
The example in Python is not so different of the others. To mock the PHP script:
class StrategyExample:
def __init__(self, func=None):
if func:
self.execute = func
def execute(self):
print("Original execution")
def executeReplacement1():
print("Strategy 1")
def executeReplacement2():
print("Strategy 2")
if __name__ == "__main__":
strat0 = StrategyExample()
strat1 = StrategyExample(executeReplacement1)
strat2 = StrategyExample(executeReplacement2)
strat0.execute()
strat1.execute()
strat2.execute()
输出:
Original execution
Strategy 1
Strategy 2
主要区别是:
- 您无需编写任何其他类或实现任何接口.
- 相反,您可以传递一个将绑定到您想要的方法的函数引用.
- 这些函数仍然可以单独使用,如果您愿意,原始对象可以具有默认行为(可以使用
if func == None
模式). - 确实,它与 Python 一样简洁而优雅.但是你会丢失信息;由于没有显式接口,程序员被假定为成年人,知道他们在做什么.
请注意,在 Python 中有 3 种方法可以动态添加方法:
Note that there are 3 ways to dynamically add a method in Python:
我向你展示的方式.但是该方法将是静态的,它不会传递self"参数.
The way I've shown you. But the method will be static, it won't get the "self" argument passed.
使用类名:
StrategyExample.execute = func
这里,所有的实例都将获得func
作为execute
方法,并将self
作为参数传递.
Here, all the instance will get func
as the execute
method, and will get self
passed as an argument.
仅绑定到实例(使用
types
模块):
strat0.execute = types.MethodType(executeReplacement1,strate0)
或者使用 Python 2,还需要被更改的实例的类:
or with Python 2, the class of the instance being changed is also required:
strat0.execute = types.MethodType(executeReplacement1,strat0,策略示例)
这会将新方法绑定到 strat0
,并且只绑定 strat0
,就像第一个示例一样.但是 start0.execute()
会将 self
作为参数传递.
This will bind the new method to strat0
, and only strat0
, like with the first example. But start0.execute()
will get self
passed as an argument.
如果你需要在函数中使用对当前实例的引用,那么你可以结合第一个和最后一个方法.如果不这样做:
If you need to use a reference to the current instance in the function, then you would combine the first and the last method. If you do not:
class StrategyExample:
def __init__(self, func=None):
self.name = "Strategy Example 0"
if func:
self.execute = func
def execute(self):
print(self.name)
def executeReplacement1():
print(self.name + " from execute 1")
def executeReplacement2():
print(self.name + " from execute 2")
if __name__ == "__main__":
strat0 = StrategyExample()
strat1 = StrategyExample(executeReplacement1)
strat1.name = "Strategy Example 1"
strat2 = StrategyExample(executeReplacement2)
strat2.name = "Strategy Example 2"
strat0.execute()
strat1.execute()
strat2.execute()
您将获得:
Traceback (most recent call last):
File "test.py", line 28, in <module>
strat1.execute()
File "test.py", line 13, in executeReplacement1
print self.name + " from execute 1"
NameError: global name 'self' is not defined
所以正确的代码是:
import sys
import types
if sys.version_info[0] > 2: # Python 3+
create_bound_method = types.MethodType
else:
def create_bound_method(func, obj):
return types.MethodType(func, obj, obj.__class__)
class StrategyExample:
def __init__(self, func=None):
self.name = "Strategy Example 0"
if func:
self.execute = create_bound_method(func, self)
def execute(self):
print(self.name)
def executeReplacement1(self):
print(self.name + " from execute 1")
def executeReplacement2(self):
print(self.name + " from execute 2")
if __name__ == "__main__":
strat0 = StrategyExample()
strat1 = StrategyExample(executeReplacement1)
strat1.name = "Strategy Example 1"
strat2 = StrategyExample(executeReplacement2)
strat2.name = "Strategy Example 2"
strat0.execute()
strat1.execute()
strat2.execute()
这将输出预期的结果:
Strategy Example 0
Strategy Example 1 from execute 1
Strategy Example 2 from execute 2
当然,如果函数不能再单独使用,但仍然可以绑定到任何对象的任何其他实例,没有任何接口限制.
Of course, in the case the functions cannot be used stand alone anymore, but can still be bound to any other instance of any object, without any interface limitation.
这篇关于如何在 Python 中编写与维基百科示例不同的策略模式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!