Strategy Design Pattern

Ben Sizer kylotan at gmail.com
Fri Apr 21 04:40:32 EDT 2006


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




More information about the Python-list mailing list