8

This is my first attempt at the Strategy Design Pattern.

I have no architectural experience using Python, so constructive comments would be welcome.

I'm posting this to Stack-Over-Flow because I would have found it useful as a sanity check this morning. Evidently, I am supposedly not providing enough context for this thread (the dreaded validation phrase) so I'm going to have to Quack like a Duck.

Quack, Quack, Quack :-)

#!/usr/bin/env python

"""
    Head First Design Patterns - Strategy Pattern
    My attempt to implement the Strategy Pattern, described in Chapter 1.

    Sanity Warning:  I am currently learning Python, so please don't expect the
    exquisite design, planning, construction, and execution of the Curiosity mission.

    Expect Ducks... Quacking...

    Design Principle: "Favour composition over inheritance" 

    To the Pythonista community: What is the most elegant, readable, and simplest way
    of implementing the HFDP Strategy Pattern?
"""

import abc

"""

Abstract Base Classes

Duck > QuackBehaviour > FlyBehaviour

"""

class Duck(object):
    __metaclass__ = abc.ABCMeta

    def __init__(self):
        self.quackBehaviour = None;
        self.flyBehaviour = None;

    @abc.abstractmethod
    def display(self):
        pass

    def performQuack(self):
        self.quackBehaviour.quack()

    def performFly(self):
        self.flyBehaviour.fly()

    def swim(self):
        print "All ducks float, even decoys!"

class QuackBehaviour(object):
    __metaclass__ = abc.ABCMeta

    @abc.abstractmethod
    def quack(self):
        """All sub classes agree to quack"""
        pass

class FlyBehaviour(object):
    __metaclass__ = abc.ABCMeta

    @abc.abstractmethod
    def fly(self):
        """All sub classes agree to fly"""
        pass

"""

Sub class implementations

MallardDuck > Quack > MuteQuack > SqueakQuack > FlyWithWings > FlyNoWay > FlyRocketPowered

"""

class MallardDuck(Duck):
    def __init__(self):
        Duck.quackBehaviour = Quack()
        Duck.flyBehaviour = FlyWithWings()

    def display(self):
        print "I'm a real Mallard Duck"

class Quack(QuackBehaviour):
    def quack(self):
        print "Quack"

class MuteQuack(QuackBehaviour):
    def quack(self):
        print "<< Silence >>"

class SqueakQuack(QuackBehaviour):
    def quack(self):
        print "Squeak"

class FlyWithWings(FlyBehaviour):
    def fly(self):
        print "I'm flying!!"

class FlyNoWay(FlyBehaviour):
    def fly(self):
        print "I can't fly"

class FlyRocketPowered(FlyBehaviour):
    def fly(self):
        print "I'm flying with a rocket!"

"""

Cue Space Odyssey Opening...

"""

if __name__ == '__main__':
    mallard = MallardDuck()
    mallard.display()
    mallard.performQuack()
    mallard.performFly()
    mallard.flyBehaviour = FlyRocketPowered()
    mallard.performFly()

"""

Output:

I'm a real Mallard Duck
Quack
I'm flying!!
I'm flying with a rocket!

"""
Dave Kirkby
  • 409
  • 1
  • 4
  • 14
  • 4
    Hi. Welcome :). StackOverflow is for asking questions about writing software. Your paste would be more welcome on the [Code Review](http://codereview.stackexchange.com/) site if you're looking for a code review, or on GitHub or pasted someplace else if you'd just like to share it with others. – Julian Aug 14 '12 at 20:46
  • 1
    +1 for writing thoroughly enjoyable code, and because the question "shows reseach effort, is useful and clear." :) – Lauritz V. Thaulow Aug 14 '12 at 20:48
  • 2
    This: `Duck.quackBehaviour = Quack()` should be this: `self.quackBehaviour = Quack()`. What you're actually doing is setting a class attribute on `Duck`, which is not what you want. – Lauritz V. Thaulow Aug 14 '12 at 20:50
  • Thanks for the links Julian and the "code review" Lazyr. I'll post future endeavours onto Code Review. – Dave Kirkby Aug 14 '12 at 21:28

0 Answers0