Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Python and strategy pattern
#1
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")
Reply
#2
You could simply write
name = self._a_strategy.do_sth()
and have the do_sth() method of the A strategies return the name.
Reply
#3
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))
Reply
#4
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.
Reply
#5
I'll print this rule. Thanks a ton for this clarification !
Reply
#6
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!
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Help with Python Script to generate SVG Dot Matrix Pattern for LED Light Guide iamrickm 2 709 Aug-25-2023, 06:07 PM
Last Post: iamrickm
  Moving average strategy irina_shubina 2 1,746 Jul-31-2022, 05:11 PM
Last Post: paulyan
  strategy to troubleshoot what pyinstaller misses hammer 0 912 May-23-2022, 01:05 AM
Last Post: hammer
  Best strategy for creating .exe for windows hammer 4 1,453 Apr-05-2022, 12:47 AM
Last Post: hammer
  Strategy on updating edits back to data table and object variables hammer 0 1,164 Dec-11-2021, 02:58 PM
Last Post: hammer
  calculate daily return in percent in forex as to some strategy? alen 1 2,181 Mar-12-2021, 10:03 AM
Last Post: buran
  Python learning strategy IluvPython 6 3,169 Nov-04-2019, 07:41 PM
Last Post: buran
  What is the strategy for working with class variables? AlekseyPython 3 2,948 Feb-24-2019, 05:34 AM
Last Post: AlekseyPython
  create list from repeated pattern in python Code4fun 2 3,394 Sep-25-2018, 07:09 PM
Last Post: woooee
  best parallelisation strategy on python simona 1 2,180 Apr-19-2018, 01:51 AM
Last Post: Larz60+

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020