Design Patterns in ActionScript-Strategy

Adivination-128x128 Today, we’re going to talk about the design patterns in ActionScript. You may be familiar with those patterns if you’re familiar with OO(object oriented). But I won’t suppose you have much knowledge about it, all you need to know is just some basic OO principles, such as encapsulation, inheritance and polymorphism.

This is the first topic of design patterns, and you’ll see all the 23 design patterns in the following days. Hope you will enjoy these topics.

Let’s begin the first one now.

Search-256x256 Demo | DownloadDownload Full Project

Suppose you need to write some codes to mimic some birds, the first is eagle, and the other is penguin. Those two animals have two methods named migration() and fly(). You may realize you need a super class named bird, and two methods in it. Then eagle and penguin can inherit from the super class, and override the methods, ‘cause those birds have different behaviors. It seems to be perfect. You quickly write down the code.

class bird {
public function migration():void{
}

public function fly():void{
}
}

class eagle extends bird {
public override function migration():void{
trace("Sorry, I don’t migrate");
}

public override function fly():void{
trace("flying");
}
}

class penguin extends bird {
public override function migration():void{
trace("migrating…");
}

public override function fly():void{
trace("Sorry, I can’t fly…");
}
}

OK, it does what you want. But what would you do when you want to add a new kind of birds into your program. Suppose you need to add a duck into your program now, you can inherit from the super class bird and override the methods again. It seems that the super class doesn’t save your time, reuse your code, you need to write every methods of subclasses.

How to fix this problem? I think you need this design pattern—Strategy. And here is the definition from the GoF book. “Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.” And what’re the algorithms here? The methods, migration() and fly(). Every bird has it’s own behavior about migration and fly, it migrates or not, it flies or not.

Let me say it more clearly, we just need to implement two situations about migration and two about fly. We need to implement each situation on a single class. And we’d better to have two interfaces named flyable and migrateable, and the classes just need to implement those interfaces. The UML diagram is showing below.

clip_image002

Now, the super class bird needs to handle two variables of those interfaces. Using polymorphism, the super class bird can do all things we do in the subclasses. When you want to ask a eagle to fly, you can simply call the function doFlying() of class bird. You can write the code like this:

var littleEagle:bird = new eagle();
littleEagle.doFlying();

I know you may be confused now, let me show you the code of the super class bird.

class bird {
var flyInterface:flyable;
var migrateInterface:migrateable;

public function bird(_fly:flyable,_migrate:migrateable){
flyInterface = _fly;
migrateInterface = _migrate;
}

public function doMigration():void{
migrateInterface.doMigration();
}

public function doFlying():void{
flyInterface.flying();
}
}

From the code, we can see the super class do all the things simply by call the methods of the interfaces. We don’t have to know which instance the interface points to, we only need to know it works. That’s it. Well, we’ll use the constructor to specify the instances of each interface. And here comes the code of each subclass.

class eagle extends bird {
public function eagle(){
super(new fly(), new neverMigration());
}

}

class penguin extends bird {

public function penguin(){
super(new neverFly(),new migration());
}

}

If you want to add a new kind of birds, all you need to do is just write a new class, and specify the constructor. And that’s it!

If you want to change the behavior of fly or neverFly, you just need to change the code of the specific class. And all the birds’ behavior will get changed. So, the code will be more easily to maintain. In this sample the behavior is easy to change, so we need to encapsulate the behavior. The UML of all classes is showing below.

clip_image004

Let’s back to the definition of this pattern, “Define a family of algorithms, encapsulate each one”, we have done it. And the result is we can change the behavior or add a new bird more easily. The algorithm means the way you solve a problem, when you have many ways to solve a problem, encapsulate it, and make it interchangeable.

This sample is not good enough to show the power of this pattern, if you want to learn more about this pattern, you can look up the GoF book.

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • Reddit
  • Technorati
  • StumbleUpon
  • Twitter
RSS Enjoy this Post? Subscribe to Ntt.cc

RSS Feed   RSS Feed     Email Feed  Email Feed Follow us Follow us
You can leave a response, or trackback from your own site.

10 Responses to “Design Patterns in ActionScript-Strategy”

  1. Steven Sacks says:

    I’m not trying to be nitpicky here, because helping the community is always a good thing, but you should always use initial caps on class names. Class names should never start with a lowercase letter.

  2. Mirco Veltri says:

    This is a good news.
    I am new in developping with AS, and I am curios to know a good way to implement gof’series patterns in AS.

    I hope to find good replies in your posts.

    Call to arms :)

    Bye

  3. [...] our last topic, we talk about the strategy pattern. And it helps us to encapsulate the change of algorithm. Today, we go on talking about the birds. [...]

  4. With all respect … that is something I can’t call strategy, maybe some kind of decorator .. or smt else.
    If Im thinking to a strategy Im thinking to “Something”, it can do some actions “defined” by a “strategy” passed to it …
    Let’s say a bird can Move() … and that case we can have a IMovementStrategy interface with method signature Move():void.
    Now we can have a specific type of movement (concrete class implementing IMovementStrategy) … of course with Move() method defined.
    As an example:
    class PenguinMovement implements IMovementStrategy{
    Move():void
    {
    trace (‘Im moving .. not flying so as an animal the strategy is to make steps … so Im a penguin … ‘)
    }
    }

    class EagleMovement implements IMovementStrategy{
    Move():void
    {
    trace (‘Im moving .. Im flying .. maybe I will migrate … so for sure Im an eagle …’)
    }
    }

    class CarMovement implements IMovementStrategy{
    Move():void
    {
    trace (‘Im moving .. I have wheels .. I can be a car .. .lets say some kind of animal :) … and this is my movement strategy ‘);
    }
    }

    Now defining the “KEY” class of the Strategy Pattern -> the “director and manipulator” of strategies we ca do smt like that:
    class MovementStrategyManager
    {
    private var _strategy:IMovementStrategy;

    public function set strategy( strategy_:IMovementStrategy):void
    {
    _strategy = strategy_;
    }

    public function Move():void
    {
    if (_strategy) _strategy.Move();
    else
    trace (‘I want to move .. but i dont have a strategy of movement … ‘)
    }
    }// end class

    Why and how this can be usefull:

    aStrategyChooser = new MovementStrategyManager();
    aStrategyChooser.Move(); // you’ll get … I want to move .. but have no strategy …
    aStrategyChooser:IMovementStrategy = new EagleMovement();
    aStrategyChooser.Move(); // will output specific Eagle … movement ..
    // … etc

    … so (in my opinion) this can be a more correct( based on your example ) strategy pattern.

    With all respect,
    Ciprian

  5. SORRY -> wrong implementation but to not create confusion, that s what i wanted to explain as client use:
    ……………………………………………………………………..
    var aStrategyChooser:MovementStrategyManager = new MovementStrategyManager();
    aStrategyChooser.Move() // you’ll get … I want to move .. but have no strategy …

    aStrategyChooser.strategy = new EagleMovement();
    aStrategyChooser.Move(); // will output specific Eagle … movement ..
    aStrategyChooser.strategy = new PenguinMovement();
    aStrategyChooser.Move(); // will output specific Penguin … movement ..
    // … etc
    ………..

  6. sike says:

    the UML picture is not so clearly, can you fix it, thanks. :)

Leave a Reply to Mirco Veltri