如何在 Python 中编写与维基百科示例不同的策略模式? [英] How to write Strategy Pattern in Python differently than example in Wikipedia?

查看:7
本文介绍了如何在 Python 中编写与维基百科示例不同的策略模式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆