Archive

Posts Tagged ‘Software Patterns’

Design Patterns using Action Script 3: Structural Patterns (Decorator & Adapter & Composite)

March 8th, 2010 Pedro No comments

Decorator

Example related in book, that shows use of Decorator Pattern. It´s used when necessary to choose many properties dynamically like the sum of shopping cart products.

File Component.as:

package
{
    //Abstract Component in Decorator Design Pattern
    //**************
    //Abstract class
    public class Component
    {
    	internal var information:String;
        public function getInformation():String
	{
	    return information;
	}
    }
}

File Decorator.as:

package
{
    //Abstract Decorator in Decorator Design Pattern
    //**************
    //Abstract class
    public class Decorator extends Component
    {
	trace("|*|Decorator|*|");
	override public function getInformation():String
	{
            return information;
	}
    }
}

File ConcreteComponent.as:

package
{
    //Concrete Component
    public class ConcreteComponent extends Component
    {
	public function ConcreteComponent():void
	{
            //\u2794 is Unicode for a right-pointing arrow
	    information = "Concete Component is decorated with \u2794";
	}
    }
}

File DecConA.as:

package
{
    //Concrete Decorator "Alpha"
    public class DecConA extends Decorator
    {
	var components:Component;
	public function DecConA(components:Component)
	{
	    this.components=components;
	}
	override public function getInformation():String
	{
	    return components.getInformation() + " Decoration Alpha:";
	}
    }
}

File DecConB.as:

package
{
    //Concrete Decorator "Beta"
    public class DecConB extends Decorator
    {
	var components:Component;
	public function DecConB(components:Component):void
	{
	    this.components=components;
	}
	override public function getInformation():String
	{
	    return components.getInformation() + " Decoration Beta:";
	}
    }
}

File DecTest.as:

package
{
    import flash.display.Sprite;
    public class DecTest extends Sprite
    {
	public function DecTest():void
	{
	    //Instantiate Concrete Component
	    var testComponent:Component = new ConcreteComponent();
	    //Wrap first decorator around component
	    testComponent=new DecConA(testComponent);
	    //Wrap second decorator around component
	    testComponent=new DecConB(testComponent);
	    //Output results
	    trace(testComponent.getInformation());
	}
    }
}

Adapter

Example related in book, that shows use of Adapter Pattern. This pattern allows existing classes to be used in situations that didn´t exist or weren´t anticipated when they were developed.

File Adaptee.as:

package {
 
    public class Adaptee {
 
	public function specificRequest():void {
	    trace("Called Adaptee:specificRequest()");
	}
    }
}

File Itarget.as:

package {
 
    public interface ITarget {
	function request():void
	function newOperation():void
    }
}

File Adapter.as:

package {
 
    public class Adapter implements ITarget {
 
	private var adaptee:Adaptee;
 
	public function Adapter() { // constructor
	    this.adaptee = new Adaptee();
	}
 
	public function request():void {
	    adaptee.specificRequest();
	}
 
	public function newOperation():void {
	    trace("Called Adapter:newOperation()");
	}
    }
}

File Main.as:

package {
 
    import flash.display.MovieClip;
 
    /**
     *	Main Class
     *	@ purpose: Document class for movie
     */
    public class Main extends MovieClip {
 
	public function Main() {
 
	    var target:ITarget = new Adapter();
 
	    target.request();
	    target.newOperation();
	}
    }
}

Composite

Example related in book, that shows use of Composite Pattern. The Composite Pattern provides a robust solution to building complex systems that are made up of several smaller components.

File Component.as:

package {
 
    import flash.errors.IllegalOperationError;
 
    // ABSTRACT Class (should be subclassed and not instantiated)
    public class Component {
 
	protected var parentNode:Composite = null;
 
	public function add(c:Component):void {
	    throw new IllegalOperationError("add operation not supported");
	}
 
	public function remove(c:Component):void {
	    throw new IllegalOperationError("remove operation not supported");
	}
 
	public function getChild(n:int):Component {
	    throw new IllegalOperationError("getChild operation not supported");
	    return null;
	}
 
	// ABSTRACT Method (must be overridden in a subclass)
	public function operation():void {
	}
 
	public function getParent():Composite {
	    return this.parentNode;
	}
 
	internal function setParent(compositeNode:Composite):void {
	    this.parentNode = compositeNode;
	}
 
	internal function removeParentRef():void {
	    this.parentNode = null;
	}
 
	internal function getComposite():Composite {
	    return null;
	}
 
    }
}

File Composite.as:

package {
 
    public class Composite extends Component {
 
	protected var sName:String;
	protected var aChildren:Array;
 
	public function Composite(sName:String) {
	    this.sName = sName;
	    this.aChildren = new Array();
	}
 
	override public function add(c:Component):void {
	    aChildren.push(c);
	    c.setParent(this);
	}
 
	override public function operation():void {
	    trace(this.sName);
	    for each (var c:Component in aChildren) {
		c.operation();
	    }
	}
 
	override public function getChild(n:int):Component {
	    if ((n > 0) && (n <= aChildren.length)) {
		return aChildren[n-1];
	    } else {
		return null;
	    }
	}
 
	override internal function getComposite():Composite {
	    return this;
	}
 
	private function safeRemove(c:Component) {
	    if (c.getComposite()) {
		c.remove(c); // composite
	    } else {
		c.removeParentRef();
	    }
	}
 
	override public function remove(c:Component):void {
	    if (c === this) {
		// remove all my children
		for (var i:int = 0; i < aChildren.length; i++) {
		    safeRemove(aChildren[i]); // remove children
		}
		this.aChildren = []; // remove references to children
		this.removeParentRef(); // remove my parent reference
	    } else {
		for (var j:int = 0; j < aChildren.length; j++) {
		    if (aChildren[j] == c) {
			safeRemove(aChildren[j]); // remove child
			aChildren.splice(j, 1); // remove reference
		    }
		}
	    }
	}
    }
}

File Leaf.as:

package {
 
    public class Leaf extends Component {
 
	private var sName:String;
 
	public function Leaf(sName:String) {
	    this.sName = sName;
	}
 
	override public function operation():void {
	    trace(this.sName);
	}
    }
}

File Main.as:

package {
 
    import flash.display.MovieClip;
 
    /**
     *	Main Class
     *	@ purpose:		Document class for movie
     */
    public class Main extends MovieClip {
 
	public function Main() {
 
	// create root node
	var root:Composite = new Composite("root");  
 
	// add a node to root
	root.add(new Composite("composite 1")); // add node to root as child
	root.getChild(1).add(new Leaf("leaf 1")); // add a child leaf
	root.getChild(1).add(new Leaf("leaf 2")); // add a child leaf
 
	// add another node
	root.add(new Composite("composite 2")); // add node to root as child
	root.getChild(2).add(new Leaf("leaf 3")); // add a child leaf
	root.getChild(2).add(new Leaf("leaf 4")); // add a child leaf
	root.getChild(2).add(new Leaf("leaf 5")); // add a child leaf
 
	// add a child leaf to the root node
	root.add(new Leaf("leaf 6"));
 
	trace("display tree");
	trace("============");
	root.operation(); 
 
	trace("remove first child of the second child of root");
	trace("==============================================");
	root.getChild(2).remove(root.getChild(2).getChild(1));
	root.operation();
 
	trace("remove the second child of root");
	trace("===============================");
	root.remove(root.getChild(2));
	root.operation();
	}
    }
}

Design Patterns using Action Script 3: Creational Patterns (Factory & Singleton)

March 4th, 2010 Pedro No comments

I´m reading the O´Reilly book “ActionScript 3.0 Design Patterns”. Following are examples related in this excellent book but modified by me. This is the first part, about creational patterns (Singleton and Factory).

Singleton

Class User.as, used to store user proprieties.

package classes
{
    public const User:_Singleton = new _Singleton();
}
 
/**
 * Class Singleton with proprieties to use in application
 */
internal class _Singleton
{
    function _Singleton(){}
 
    public var id:int;
    public var name:String;
    public var description:String;
    public var username:String;
    public var password:String;
}

Factory

Example related in book, that shows creation of products.

File Creator.as:

package example {
 
    import flash.errors.IllegalOperationError;
 
    // ABSTRACT Class (should be subclassed and not instantiated)
    public class Creator {
 
    	public function doStuff():void {
    	    var product:IProduct = this.factoryMethod();
	    product.manipulate();
        }
 
	// ABSTRACT Method (must be overridden in a subclass)
	protected function factoryMethod():IProduct {
            throw new IllegalOperationError("Abstract method: must be overridden in a subclass");
	    return null;
	}
    }
}

File CreatorA.as:

package example {
 
    // Concrete creator A (subclass of Creator)
    public class CreatorA extends Creator {
 
        override protected function factoryMethod():IProduct {
            trace("Creating product 1");
	    return new Product1(); // returns concrete product
        }
    }
}

File CreatorB.as:

package example {
 
    // Concrete creator B (subclass of Creator)
    public class CreatorB extends Creator {
 
        override protected function factoryMethod():IProduct {
            trace("Creating product 2");
	    return new Product2(); // returns concrete product
        }
    }
}

File IProduct.as:

package example {
 
    public interface IProduct {
        function manipulate():void;
    }
}

File Product1.as:

package example {
 
    internal class Product1 implements IProduct {
 
        public function manipulate():void {
	    trace("Doing stuff with Product1");
        }
    }
}

File Product2.as:

package example {
 
    internal class Product2 implements IProduct {
 
        public function manipulate():void {
	    trace("Doing stuff with Product2");
        }
    }
}
package classes
{
public const User:_Singleton = new _Singleton();
}

/**
* Class Singleton that represents proprieties used to change language
*/
internal class _Singleton
{
function _Singleton(){}

public var id:int;
public var name:String;
public var description:String;
public var username:String;
public var password:String;

}