Design Patterns w/ AS3 Part 2: Decorator Pattern

The decorator pattern takes the concept of composition over inheritance a step further. In this pattern, we will attach additional responsibilities to an object to extend its functionality. Inheritance is used in this pattern for type matching, but not for applying behavior to an object. The behavior comes from the concrete components we will create as well as any decorators we will use on the object, and because this behavior does not come through inheritance we will not have to modify existing code to add new behavior. We simply add an additional decorator for the behavior(s) we want to add.

This is a place where we want to follow the Open-Closed Principle — Classes should be open for extension, but closed for modification. So in this example, we have a coffee shop that currently sells 4 types of coffee, with 4 types of condiments that can be added to each coffee. We *could* do this through inheritance, but any changes will result in making modifications to our parent class. For example, if new condiments are added or prices are changed it will force us to make changes to the code and potentially introduce new bugs. Also, beverages added at a later time may inherit certain condiments that do not apply (or taste very good either).
So to start, we are going to build our own coffee shop. First we start with the main class, the Beverage class:

public class Beverage {
    public var description:String = "Unknown Beverage";
 
    public function getDescription():String {
	return description;
    }
 
    public function cost():Number {
	return 0;
    }
}

Now we create our condiment decorator, that needs to match the type of our beverage class:

public class CondimentDecorator extends Beverage {
    override public function getDescription():String {
	return '';
    }	
}

Now for the coffee. We’ll start with an Espresso component that will extend the Beverage class:

public class Espresso extends Beverage {
    public function Espresso():void {
	description = "Espresso";
    }
 
    override public function cost():Number {
	return 1.99;
    }
}

And Finally, we’ll create our first decorator:

public class Whip extends CondimentDecorator {
    public var beverage:Beverage;
 
    public function Whip(beverage:Beverage) {
      this.beverage = beverage;
    }
 
    override public function getDescription():String {
      return beverage.getDescription() + ", Whip";
    }
 
    override public function cost():Number {
	return 0.10 + beverage.cost();
    }	
}

Now that we have our decorators and components set up, we can quickly and easily create a coffee and determine its price:

var beverage:Beverage = new Espresso();
beverage = new Whip(beverage);
trace('You ordered:' + beverage.getDescription() + ' $' + beverage.cost());

Here is a demo of everything compiled together, you can view the source as well.


Design Patterns w/ AS3 - Part 1: The Strategy Pattern

I am currently reading Head First Design Patterns, an amazing book for digging into Design Patterns and understanding the power behind them. I wanted to give a write up on each of these patterns with the book’s code ported to Actionscript 3. The first pattern in the series is the Strategy Pattern. This pattern takes a group of algorithms and encapsulates each to make them all interchangeable, while also giving each one the ability to vary independently from the clients that use it. The big takeaway from this pattern is to separate what changes from what stays the same, giving you fewer unintended consequences from updates and maintenance changes.

In the example, we have a simple duck class with four methods: quack(), swim(), display(), and fly().

If we were to create a MallardDuck class that inherits from the Duck class everything would work great. It can quack, fly, swim and display on the screen. However, if we were to create a RubberDuck class we would have some problems because rubber ducks dont quack and they cannot fly.
In this scenario, you would have to override your quack method to make the duck squeak, and override the fly method to do nothing. Since these things change and we are following the Strategy Pattern, we must pull these methods out of the Duck class and separate them. This is where we bring in our friend, the Interface. Programming to an interface allows us to avoid a concrete implementation of behavior from our Duck superclass and allows for a set of classes that are strictly used for behaviors. First, we create an interface for Flying Behavior:

//FlyBehavior.as class
 
public interface FlyBehavior {
    function fly()
}

Now that we have a FlyBehavior interface, we have a contract with classes that implement the FlyBehavior interface. If we create a FlyWithWings class that implements FlyBehavior, we must have a fly() method or the compiler will throw an error. Lets create our FlyWithWings class:

//FlyWithWings.as class
 
public class FlyWithWings implements FlyBehavior {
    public function fly() {
        trace('Im flying');
    }
}

And we will also make a class for those ducks that don’t fly, called FlyNoWay:

//FlyNoWay.as class
 
public class FlyNoWay implements FlyBehavior {
    public function fly() {
        trace('I cant fly');
    }
}

Following the same procedure, we can then make an interface for QuackBehavior and create classes that implement QuackBehavior like Quack, Squeak and MuteQuack. The benefit here is that we can now reuse these fly and quack behaviors for other objects because they are no longer within the Duck class. Also, if we decided we wanted to add a new behavior, we would not need to work with the Duck class or any other behaviors to do so. This is called Composition, because we composing the ducks with the correct behavior object(s) instead of inheriting them from their parent.

Now we put it all together in our Duck class. Since we previously took out quack() and fly(), we are going to add 2 new methods: performQuack() and performFly(). These methods will delegate to the behavior class to quack or fly. Our Duck class will look like this:

//Duck.as class
 
import FlyBehavior;
import QuackBehavior;
 
public class Duck {
	//behavior variables
	public var flyBehavior:FlyBehavior;
	public var quackBehavior:QuackBehavior;
 
	//constructor method
	public function Duck() {	
	}
 
	//make the duck fly
	public function performFly():void {
		flyBehavior.fly();
	}
 
	//make the duck quack
	public function performQuack():void {
		quackBehavior.quack();
	}	
}

Okay, so now we have our behaviors created and our Duck superclass created… it’s time to create some ducks. A mallard duck would look something like this:

//MallardDuck.as class
 
public class MallardDuck extends Duck {
	public function MallardDuck() {
		quackBehavior = new Quack();
		flyBehavior = new FlyWithWings();
	}
 
	public function display():void {
		trace('Im a mallard duck');
	}
}

To put it all together, lets finish it up with an application file:

//Application file
 
private function init():void {
	var mallard:Duck = new MallardDuck();
	mallard.performFly();
	mallard.performQuack();	
}

The result is a flying, quacking duck. Below is a sample application I created with source enabled (right click). In the next series, I will talk about the Observer pattern and the power that comes from using it.

Solution To Set FilterFunction=null in Flex GroupingCollection

I came across an issue in Flex where I was unable to set my filterFunction=null to bring back all data after it had been filtered. I was trying to use this on my reset function:

private function resetFilter():void {
  advancedDataGrid.dataProvider.filterFunction = null;
  advancedDataGrid.dataProvider.refresh();
}

Previously, when my dataprovider had been a simple ArrayCollection that would have worked fine. When using a groupingCollection you must do this:

private function resetFilter():void {
  advancedDataGrid.dataProvider.filterFunction = returnAllItems;
  advancedDataGrid.dataProvider.refresh();
}
 
private function returnAllItems(item:Object):Boolean {
  return true;
}

This workaround will allow your grouped data to return to its original state.

Convert Comma-Delimited String to Array in AS3

I came across the need to convert a comma delimited string into an Array in AS3 today, and surprisingly the answer did not pop up on Google like I would have thought. First we start off with a string:

myString = "1-John,2-Barry,3-Stacy,4-Bob"

The end result will look like:

myObject[0].name="John"
myObject[0].id="1"
 
myObject[1].name="Barry"
myObject[1].id="2"
 
myObject[2].name="Stacy"
myObject[2].id="3"
 
myObject[3].name="Bob"
myObject[3].id="4"

Actionscript 3 actually makes this task very simple. You first need to use the split() function with a comma delimiter to separate each item and store it within a new array:

var peopleList:Array = myString.split(",");

Next, we create a new object to hold the data and split the data once more using the hyphen:

myObject[0].people = new Array();
for (var x:int=0;x<peopleList.length;x++){
  var peopleDetail:Array = peopleList[x].split("-");
  var obj:Object = new Object();
  obj.id = peopleDetail[0];
  obj.name = peopleDetail[1];
  myObject[0].people.push(obj);
}

I’m sure there are plenty of ways to achieve this, but it seemed to work for me with not a whole lot of code. Hope this helps someone searching for the answer like I was.

Why Wont My Mate EventMap Listen To My Event?!?

I’ve been working with Mate for a couple weeks now and I’m still learning how to wrap my head around it. Today I spent about an hour trying to figure out why my events were not dispatching. After debugging, I found they were in fact being dispatched but my eventmap was never picking them up. A coworker of mine mentioned “hey, did you turn on bubbling” and it clicked… I forgot to turn on bubbling when I created the event class. When you are creating any event class, make sure you set bubbles:Boolean=true and everything will work great. One of those things you seem to overlook when in fact should have been the first thing to check. Stupid Brain.

Next »