Home > Programação, Software Patterns, Tecnologia > Design Patterns using Action Script 3: Structural Patterns (Decorator & Adapter & Composite)

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

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();
	}
    }
}
  1. No comments yet.
  1. No trackbacks yet.