Re: Strategy Design Pattern



Daniel Santa Cruz wrote:
Well, I've gotten stuck with my first go at OO patterns with Python. I
guess it goes without say that some of the stuff that are taken for
granted in most of the books (ie. Interfaces, Abstract classes) don't
really apply to Python per say, but the idea behind the patterns can be
extracted out still.

In the original "Design Patterns" book, the authors pointed out that
although patterns are generally language-agnostic, the need for
formalised patterns to achieve a given goal is not. One example is
inheritance - if you're programming in C then you'd need a formal
pattern to model inheritance effectively, but in many other languages
it's built in. It may be the case that Python gives you the tools to
make some other patterns effectively redundant.

In the specific case of the Strategy pattern, I
think the goal is to abstract out of the class an algorithm that can
then be reused by some of the inherited classes. This way we don't
repeat ourselves. Maybe I got this all wrong...

The goal is to allow an object to have a certain behaviour which uses
an algorithm you can change by changing the object that performs that
algorithm. It essentially means you can change the algorithm later
without changing the object.

In Python, this is quite simple - decide upon an interface that the
algorithm should provide, and then assign an object that implements
that interface to your object. The object will then pass its data to
the interface methods on whichever algorithm object it's been given.

To aid commenters... we can use the example used in "Head First Design
Patterns". I've implemented this simple patter in Java and .NET... now
in python. I can't draw UML here, so I'll try to pseudo talk what the
example has:

Abstract Base Class: Duck
+ FlyBehavior _fly
+ swim()
+ fly() -> calls _fly.fly()

Interface: FlyBehavior
+ fly()

Concrete Interface FlyHigh (implements FlyBehavior):
+ fly()

Concrete Class Duck1 (Inherits Duck):
+ Constructor: _fly = new FlyHigh()

In this example, you can just assign a FlyHigh function to your Duck1 -
no Duck or FlyBehavior classes needed. The pattern is almost pointless
in situations like this when your language allows you to quickly and
easily assign functions between objects. However if, as is common, you
need more than 1 function in the interface, you can put them in an
object and assign that.

class FlyHigh(object):
def TakeOff(self, bird):
print "take off to fly high"
def Land(self, bird):
print "land from flying high"

class FlyLow(object):
def TakeOff(self, bird):
print "take off to fly low"
def Land(self, bird):
print "land from flying low"

class Duck(object):
def __init__(self, flyingBehavior):
self.flyBehavior = flyingBehavior
def TakeOff(self):
self.flyBehavior.TakeOff(self)
def Land(self):
self.flyBehavior.Land(self)

lowFlyingDuck = Duck(FlyLow())
highFlyingDuck = Duck(FlyHigh())


Note that I don't claim the above code is necessarily optimal (or even
correct!) but it should show that half of the Strategy pattern
boilerplate is unnecessary in Python. You can even use certain Python
tricks to automatically delegate calls on Duck to the behavior classes
without typing those out individually, for example.

--
Ben Sizer

.



Relevant Pages

  • Re: Need some advice
    ... parts are independent from the others, except for a few interface items ... def reduction: ... > the numerical equivalent of each letter in a name and I was going to ...
    (comp.lang.python)
  • Re: Freeing Algorithms
    ... detail about how the algorithm works, ... is the same shape whatever the power requirements of the ... OTOH, if the hardware interface were as specific as in your example with Years, ... And there's the same tension in the design of hardware interfaces. ...
    (comp.lang.java.programmer)
  • Re: Strategy pattern / interface design arrangement
    ... I realize Ruby doesn't explicitly support the concept of an interface ... GOF calls a Context) which clients can configure by giving it ... implementation of the Context and the various ConcreteStrategies, ... These were the authors of the book "Design Patterns" which was first ...
    (comp.lang.ruby)
  • Re: A little stricter type checking
    ... def f: ... but that the interface is there at least, while in the former both steps ... Of course it is not a full replacement of a type declaration, ...
    (comp.lang.python)
  • Re: IronPython and COM Interface
    ... I'm new to IronPython and COM so please bear with me. ... I have a COM interface provided to me. ... def OnLevel2Data: ... # Wrap the callback class to turn it into an IDispatch object ...
    (comp.lang.python)