L'exemple dans Python n'est pas si différent des autres. Pour se moquer du script PHP:
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()
Sortie:
Original execution
Strategy 1
Strategy 2
Les principales différences sont les suivantes:
- Vous n'avez pas besoin d'écrire une autre classe ou mettre en œuvre une interface.
- Au lieu de cela, vous pouvez passer une référence de fonction qui sera liée à la méthode que vous voulez.
- Les fonctions peuvent toujours être utilisées séparément, et l'objet d'origine peut avoir un comportement par défaut si vous le souhaitez (le modèle
if func == None
peut être utilisé pour cela).
- En effet, c'est propre et court comme d'habitude avec Python. Mais vous perdez des informations. sans interface explicite, le programmeur est supposé être un adulte pour savoir ce qu'il fait.
Notez qu'il existe 3 façons d'ajouter dynamiquement une méthode en Python:
La façon dont je vous ai montré. Mais la méthode sera statique, elle n'obtiendra pas l'argument "self".
Utilisation du nom de la classe:
StrategyExample.execute = func
Ici, tout l'instance va se func
comme méthode execute
et va se self
passé comme argument.
liaison à une instance uniquement (à l'aide du module types
):
strat0.execute = types.MethodType(executeReplacement1, strat0)
ou avec Python 2, la classe de l'instance en cours de modification est également nécessaire:
strat0.execute = types.MethodType(executeReplacement1, strat0, StrategyExample)
Ceci sera bi sd la nouvelle méthode à strat0
, et seulement strat0
, comme avec le premier exemple. Mais obtiendra self
passé en argument.
Si vous devez utiliser une référence à l'instance en cours dans la fonction, vous devez combiner la première et la dernière méthode. Si vous ne le faites pas:
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()
Vous obtiendrez:
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
Ainsi, le code approprié serait:
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()
Cette sortie sera le résultat attendu:
Strategy Example 0
Strategy Example 1 from execute 1
Strategy Example 2 from execute 2
Bien sûr, dans le cas où les fonctions ne peuvent pas être utilisé seul, mais peut toujours être lié à toute autre instance d'un objet, sans aucune limitation d'interface.
Il est un modèle de modèle, pas la stratégie que l'on – Twisty