Subscribe to Tutorial Feed

Flash and PHP Bible

The Flash and PHP Bible has been released! The book can be found on Amazon or wherever fine books are sold in your area.

The Flash and PHP Bible has a forum for quick support.

Scriptplayground » tutorials » as » Intro to Design Pattern and OOP with AS3

Intro to Design Pattern and OOP with AS3

Learn the basics of OOP while working with a Design Pattern.

Special thanks to aklement for writing and submitting this article.

OOP and Design Patterns have become more popular and quite the buzz words in the Flash community. It may be intimidating, but it shouldn't be.

Here is demonstrated a simple "Factory" design pattern that might be used in a game. I want to make weapons for my ship. Here are the fire buttons. The green circle shoots missiles and the blue button fires bombs, and it does this with just one line of code.

Click circles to fire

When thinking about the "Factory" pattern, it actually helps to think of it as a factory. Factories stamp out products in a fast and easy manner. They do this because all the products it makes are pretty much the same, and are based off a template.

First I need to make a template that my weapons will be made from. Imagine a steel mill, where a vat of hot liquid metal pours steel into a cast (template). This is my template:

package com.lovethelie.tutorial
{
	import flash.display.Sprite;
	import flash.events.Event;
	
	internal class Weapon extends Sprite
	{
		internal var speed:Number
		
		internal function buildWeapon($height:Number, $width:Number, $color:uint):void
		{
		}
		
		internal function setSpeed($speed:Number):void
		{
		}
		
		internal function initXY($initX:Number, $initY:Number):void
		{
			this.x = $initX
			this.y = $initY
		}
		
		internal function feuerFrei():void
		{
			addEventListener(Event.ENTER_FRAME, update)
		}
		
		protected function update($evt:Event):void
		{
			this.x += speed
		}
		
	}
}

Just like a factory doesn't output templates (it just uses them), we won't use this class directly. This class is what is refered to as an abstract class. This class is called "Weapon" and we will never write:

var myWeapon:Weapon = new Weapon()

Next, on our "blank" weapons come down the assembly line and workers add stuff to make them more unique. Some get rockets attached to them so they can go fast (our missiles) others get fins put on so they don't fall so fast (our bombs). These next two classes are our workers. They modify our weapons and turn them into missiles or bombs. Note the "extends" keyword; it extends "Weapon".

package com.lovethelie.tutorial
{
  internal class Missile extends Weapon
  {
	override internal function buildWeapon($height:Number, $width:Number, $color:uint):void
	{
		graphics.beginFill($color)
		graphics.drawRect(0,0,$width,$height)
		graphics.endFill()
	}
	
	override internal function setSpeed($speed:Number):void
	{
		speed = $speed * 2.5
	}
  }
}
package com.lovethelie.tutorial
{
  import flash.errors.IllegalOperationError;
	
  internal class Bomb extends Weapon
  {
	override internal function buildWeapon($height:Number, $width:Number, $color:uint):void
	{
		if($height == $width)
		{
			graphics.beginFill($color)
			graphics.drawRect(0,0,$width,$height)
			graphics.endFill()
		}
		else
		{
			throw new Error("Heght and Width must be the same");
			return null;
		}
	}
		
	override internal function setSpeed($speed:Number):void
	{
		speed = $speed
	}
  }
}

Wait a sec! What happened to the other methods, what is "override" and where did "speed" come from?!!!

The methods from "Weapon" are still there in our "Missile" and "Bomb" classes. Remember these classes are our workers. They don't need to make the whole weapon, just add the parts that make it different, the functions initXY(), feuerFrei(), and update() are already included. This is also where the word "override" keyword comes in. I left the functions makeWeapon() and setSpeed() blank, because I knew I was going to rewrite them later. I could have filled them in with anything, but whatever I had put in there would have been erased when the method was overridden later.

The variable "speed" was declared in the "Weapon" class. Just like these sub-classes already include initXY(), feuerFrei(), and update(), they will already include "speed". I also gave it the modifier "internal". You can see that I wrote "internal" in various places. In this example, everywhere you see "internal" I could have written "public" instead. I did this to isolate these classes from other classes I may write later. The word "internal" means "in the same folder"; also, because the classes are in the same folder, I don't have to import them to use them.

Lastly we come to our creator class. Think of this as the loading dock of our factory. Our goods have been made and are ready to ship. Now we just have to package and load them into the trucks.

package com.lovethelie.tutorial
{
	import flash.display.Stage
	import flash.errors.IllegalOperationError;
	
	public class WeaponCreator
	{
		public static const MISSILE:int = 0
		public static const BOMB:int = 1
		
		internal var weapon:Weapon
		
		public function makeWeapon( $type:int, $target:Stage, 
							$initX:Number, $initY:Number, 
							$height:Number, $width:Number, 
							$color:uint, 
							$speed:Number):void
		{
			weapon = this.createWeapon($type)
			weapon.buildWeapon($height,$width,$color)
			weapon.setSpeed($speed)
			weapon.initXY($initX,$initY)
			$target.addChild(weapon)
		}
		
		public function fire():void
		{
			weapon.feuerFrei()	
		}
		
		private function createWeapon($type:int):Weapon
		{
			if($type == 0)
			{
				return new Missile()
			}
			
			if($type == 1)
			{
				return new Bomb()
			}
			
			else
			{
				throw new Error("Invalid kind of weapon");
				return null;
			}
		}
	}
}

Here we see why we made that abstract class. The function createWeapon() returns a Weapon class. Flash is expecting a weapon to be returned, and bombs and missiles are both weapons. Kinda like when you show your dad how to play a video game. You don't tell him "Dad shoot the Hell Hounds, Ogres, and Goblins!" You say "dad shoot the bad guys!". It's like that.

One thing of particular note, is that I declared the variable "weapon" outside of the makeWeapon() function. I did this because I wanted to be able to call the feurFrei() function outside of the makeWeapon() function. I could have put feurFrei() in the makeWeapon() function, but I wanted to keep them separate, this is just a personal preference because it gives me more flexibility later.

So now our weapons are all made and on the truck. Now we just have to use them. In our "Client" class we actually use them. The client is the class that will be your "main" or "document class" where we tell the factory to make the weapons, as well as whatever else you want your flash movie to do.

To do this I make a weapon creator:

private var _missileCreator:WeaponCreator
_missileCreator.makeWeapon(WeaponCreator.MISSILE, this.stage, 
    _fireMissileBtn.x,_fireMissileBtn.y, 10,50,0x00ff00,20)
_missileCreator.fire()

OK, so I kind of lied, it's REALLY 3 lines of code, but if you remember, I decided to keep the feurFrei() separate. I could have included it in the makeWeapon() function.

To see all the code used here in action go to:
http://www.lovethelie.com/factory_tutorial/

There you will see the example from above and you can right-click on the movie and choose "view source". Here you can then see all the classes used and download them.

Follow Scriptplayground on Twitter (@scriptplay)

Comments: Intro to Design Pattern and OOP with AS3

 Rob  Thu Oct 16, 2008 4:41 am  
Thanks man, this is helpful
 George  Tue Mar 3, 2009 9:12 pm  
Hi,

Wen i used the above code in Flex 3, it was not working. it throws an error "Cannot access a property or method of a null object reference".

How can i use this code in Flex 3.
 George  Tue Mar 3, 2009 9:19 pm  
Yes, I got it working by creating a new instance of the class WeaponCreator,

i.e,

private var myMissile:WeaponCreator = new WeaponCreator();

Is that right? is there something like we should not create new instance in Factory Design Pattern?

Thanks a lot for your post. It was very helpfull

George
 Mark A.  Sun Jun 21, 2009 12:05 am  
Isn't it common to just let the factory produce things? Here the creator class is also responsible for firering the weapon. I think what you are explaining here is more like the Factory Method rather than the Factory pattern
 ryanore  Fri May 14, 2010 3:00 pm  

I think the pattern applies, he is just keeping it clean on the surface. But I see your point. more factory-ish would be having makeWeapon() return a weapon
so...

private var _missileCreator:WeaponCreator

private var _M:Weapon = _missileCreator.makeWeapon(WeaponCreator.MISSILE, this.stage,_fireMissileBtn.x,_fireMissileBtn.y, 10,50,0x00ff00,20)

_M.fire()


btw/ nice tutorial.
.ore

 Ben  Mon May 17, 2010 10:09 am  
Nice. Quite helpful introduction to the factory idea.
 vivek  Thu Nov 4, 2010 6:45 am  
thanks a lot it was very useful for me to understand the conept
 mkeefe  Tue Nov 9, 2010 4:58 am  
@Ben, @vivek - Glad you found the tutorial useful. Always exciting to hear from the readers of Scriptplayground!
 Benoit  Tue May 10, 2011 6:08 am  
Would you make the makeWeapon() function a static function ? Would that keep the factory like pattern ?
 Raj Manchekar  Wed Jun 8, 2011 7:44 pm  
Very useful article and easy to understand.
Nicely made.

Raj
 kunjal  Fri Oct 7, 2011 10:25 pm  
Nice article. Thanks. The link at the end is broken please solve it.
Add a comment
The ability to add new comments has been disabled in this archived version.

Loading
Main | Tutorials | Articles