Python Forum

Full Version: Python and strategy pattern
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi There,

I need your help to understand how to use Strategy pattern properly in Python.
Indeed i don't know how to transfer a result coming from a strategy to another.
Structure is : (files are at the bottom of this post)
  • App.py
  • AStrategyAbstract.py
  • BStrategyAbstract.py
  • CStrategyAbstract.py

Running the app below, App.py is giving me the following :
A1 Strategy applied Give me your name Foo ! B3 Strategy applied C2 Strategy applied ___ A2 Strategy applied Give me your name Bar ! B1 Strategy applied C2 Strategy applied
I would like to get the following, but I don't understand how.
Should i declare a getter/setter within app class but how to access it ?
Any other way ?


A1 Strategy applied Give me your name Foo ! B3 Strategy applied Name given was Foo! C2 Strategy applied ___ A2 Strategy applied Give me your name Bar ! B1 Strategy applied Name given was Bar ! C2 Strategy applied
Can please someone point me on the right direction ?
Regards,
Pierre

Filename : App.py
from AStrategyAbstract import A1Strategy,A2Strategy,A3Strategy from BStrategyAbstract import B1Strategy,B2Strategy,B3Strategy from CStrategyAbstract import C1Strategy,C2Strategy,C3Strategy a1_strategy = A1Strategy() a2_strategy = A2Strategy() a3_strategy = A3Strategy() b1_strategy = B1Strategy() b2_strategy = B2Strategy() b3_strategy = B3Strategy() c1_strategy = C1Strategy() c2_strategy = C2Strategy() c3_strategy = C3Strategy() class App(object): def __init__(self, a_strategy, b_strategy, c_strategy): self._a_strategy = a_strategy self._b_strategy = b_strategy self._c_strategy = c_strategy self.name = None def do_sth(self): self._a_strategy.do_sth() self._b_strategy.do_sth() self._c_strategy.do_sth() class AApp(App): def __init__(self): super(AApp, self).__init__(a1_strategy, b3_strategy, c2_strategy) def start(self): self.do_sth() class BApp(App): def __init__(self): super(BApp, self).__init__(a1_strategy, b1_strategy, c2_strategy) def start(self): self.do_sth() if __name__ == '__main__': myaapp = AApp() myaapp.start() print("___") mybapp = BApp() mybapp.start()
Filename : AStrategyAbstract.py
import abc class AStrategyAbstract(object): __metaclass__ = abc.ABCMeta @abc.abstractmethod def do_sth(self): """Required Method""" class A1Strategy(AStrategyAbstract): def do_sth(self): print("A1 Strategy applied") print("Give me your name") name = input() class A2Strategy(AStrategyAbstract): def do_sth(self): print("A2 Strategy applied") print("Give me your name") name = input() class A3Strategy(AStrategyAbstract): def do_sth(self): print("A3 Strategy applied") print("Give me your name") name = input()
Filename : BStrategyAbstract.py
import abc class BStrategyAbstract(object): __metaclass__ = abc.ABCMeta @abc.abstractmethod def do_sth(self): """Required Method""" class B1Strategy(BStrategyAbstract): def do_sth(self): print("B1 Strategy applied") class B2Strategy(BStrategyAbstract): def do_sth(self): print("B2 Strategy applied") class B3Strategy(BStrategyAbstract): def do_sth(self): print("B3 Strategy applied")
Filename : CStrategyAbstract.py
import abc class CStrategyAbstract(object): __metaclass__ = abc.ABCMeta @abc.abstractmethod def do_sth(self): """Required Method""" class C1Strategy(CStrategyAbstract): def do_sth(self): print("C1 Strategy applied") class C2Strategy(CStrategyAbstract): def do_sth(self): print("C2 Strategy applied") class C3Strategy(CStrategyAbstract): def do_sth(self): print("C3 Strategy applied")
You could simply write
name = self._a_strategy.do_sth()
and have the do_sth() method of the A strategies return the name.
Thank you for this quick reply, and sorry for this dumb question. Big Grin
Btw why the abstract method B for example doesn't care of param ?
Was more expecting
@abc.abstractmethod def do_sth(self, nom): """Required Method"""
than
@abc.abstractmethod def do_sth(self): """Required Method"""
I did update App.py to be

from AStrategyAbstract import A1Strategy,A2Strategy,A3Strategy from BStrategyAbstract import B1Strategy,B2Strategy,B3Strategy from CStrategyAbstract import C1Strategy,C2Strategy,C3Strategy a1_strategy = A1Strategy() a2_strategy = A2Strategy() a3_strategy = A3Strategy() b1_strategy = B1Strategy() b2_strategy = B2Strategy() b3_strategy = B3Strategy() c1_strategy = C1Strategy() c2_strategy = C2Strategy() c3_strategy = C3Strategy() class App(object): def __init__(self, a_strategy, b_strategy, c_strategy): self._a_strategy = a_strategy self._b_strategy = b_strategy self._c_strategy = c_strategy self.name = None def do_sth(self,name): self.name = self._a_strategy.do_sth() self._b_strategy.do_sth(self.name) self._c_strategy.do_sth(self.name) class AApp(App): def __init__(self): super(AApp, self).__init__(a1_strategy, b3_strategy, c2_strategy) def start(self): self.do_sth(self.name) class BApp(App): def __init__(self): super(BApp, self).__init__(a2_strategy, b1_strategy, c2_strategy) def start(self): self.do_sth(self.name) if __name__ == '__main__': myaapp = AApp() myaapp.start() mybapp = BApp() mybapp.start()
AStrategyAbstract.py

import abc class AStrategyAbstract(object): __metaclass__ = abc.ABCMeta @abc.abstractmethod def do_sth(self): """Required Method""" class A1Strategy(AStrategyAbstract): def do_sth(self): print("A1 Strategy applied") print("Give me your name") name = input() return name class A2Strategy(AStrategyAbstract): def do_sth(self): print("A2 Strategy applied") print("Give me your name") name = input() return name class A3Strategy(AStrategyAbstract): def do_sth(self): print("A3 Strategy applied") print("Give me your name") name = input() return name
BStrategyAbstract.py

import abc class BStrategyAbstract(object): __metaclass__ = abc.ABCMeta @abc.abstractmethod def do_sth(self): """Required Method""" class B1Strategy(BStrategyAbstract): def do_sth(self, name): print("B1 Strategy applied {}".format(name)) class B2Strategy(BStrategyAbstract): def do_sth(self, name): print("B2 Strategy applied {}".format(name)) class B3Strategy(BStrategyAbstract): def do_sth(self, name): print("B3 Strategy applied {}".format(name))
Python functions cannot be overloaded. One can only override functions in subclasses. I guess python doesn't even look at the parameters, even in the case of abstract methods. That said, I'm breaking a zen of python's rule: "In the face of ambiguity, refuse the temptation to guess." :) The answer is probably in abc's documentation.
I'll print this rule. Thanks a ton for this clarification !
If you come from the Java world, don't think ABCMeta plays a similar role in Python as interfaces do in Java. I would have written these classes with a base class, but without using the abc module. You're adding an unnecessary complexity in the code. I think python's abc is only useful for extremely general functionalities, such as in collections.abc, otherwise it will come in your way rather than help you. Without ABCMeta, you can simply raise NotImplementedError in the base class' method. Last but not least, use python 3!