Factory Design Pattern Print Center Actionscript 3 – Sanders & Cumaranatunge – Part 1 of 2

By Lon (Alonzo) Hosford

This is the print center Factory design pattern from chapter 2 of William Sanders and Chandima Cumaranatunge Actionscript 3.0 Design Patterns.

Actionscript 3 Design Patterns Learn More

This is an ActionScript project created in Flex Builder and updated to Flex Builder 4. Download the example code. You can build this with the free Flex SDK by using the code in the src folder. Same for Flash CS3 and CS4. You need to create a Flash Document in the src folder and set the document class to Chapter02_Factory_PrintCenters. For your convenience you can download a Flash CS4 ready to go example.

This includes a basic Actionscript debugger console to display tracing statements on stage. Each class sends messages to the console to show their methods working. These messages help you follow the relationships in the Factory design pattern.

Application Class – Chapter02_Factory_PrintCenters
This is the client class. The class instantiates HighVolPrinterCenter and LowVolPrinterCenter classes and calls their print() method inherited from the PrintCenter class. The basic idea is the same as the minimalist example to uncouple the product classes from the clientInkJetPrintJob and WorkgroupPrintJob.

/**
 * Demonstrates a more concrete example of decoupling the client, this file, from the products.
 * In this case the products are print jobs on various printers. The print jobs are not coupled
 * to the client. Clients interface with creator classes representing a type of print center. 
 * The product classes doing the work are created by the print center creator classes.
 * <p>
 * This is part one of the example. 
 * </p>
 * */
package
{
	import com.lonhosford.util.debug.lite.DebugConsole;
	
	import flash.display.Sprite;
	
	import printcenters.HighVolPrinterCenter;
	import printcenters.LowVolPrinterCenter;
	import printcenters.PrintCenter;
	
	// {SET STAGE SIZE AND SPEED HERE}
	[SWF(width=500, height = 300, frameRate = 30)]
	public class Chapter02_Factory_PrintCenters extends Sprite
	{
		private var debugConsole:DebugConsole = DebugConsole.getInstance();
		public function Chapter02_Factory_PrintCenters()
		{
			stage.addChild(debugConsole);
			debugConsole.width = stage.stageWidth;
			debugConsole.height = stage.stageHeight;
			
			debugConsole.write("Actionscript 3.0 Design Patterns");
			debugConsole.write("William Sanders & Chandima Cumaranatunge");
			debugConsole.write("Chapter 2 Print Centers Example - Part 1");
			debugConsole.write("\n");
			
			
			debugConsole.write("\nPrint LongThesis.doc to high volume printer.");
			var pcHighVol:PrintCenter = new HighVolPrinterCenter();
			pcHighVol.print("LongThesis.doc");
			
			debugConsole.write("\nPrint ShortVita.doc to low volume printer.");
			var pcLowVol:PrintCenter = new LowVolPrinterCenter();
			pcLowVol.print("ShortVita.doc");
			

			
		}
	}
}

PrintCenter Class
This class provides a “factory method” interface to each of its subclasses LowVolPrintCenter and HighVolPrintCenter. The line 25 shows the createPrintJob()() method. The factory method cannot be called from a client class. The method throws an IllegalOperationError to prevent that coding option.


The createPrintJob()() method returns a IPrintJob interface. Each Creator subclass will return its own product all having a createPrintJob()() method defined by the IPrintJob interface discussed later in this post. This PrintCenter class then uses the product class start() method on line 19.

package printcenters
{
	import flash.errors.IllegalOperationError;
	/**
	 * Handles file printing.
	 * */
	public class PrintCenter
	{
		public function PrintCenter()
		{
		}
		/**
		 * Simulate printing a file.
		 * @param fileName Name of file to print.
		 * */		
		public function print(fileName:String):void
		{
			var printjob:IPrintJob = this.createPrintJob();
			printjob.start(fileName);
		}
		/**
		 * Creates the IPrintJob products.
		 * @throws flash.errors.IllegalOperationError Must override in subclass.
		 * */		
		protected function createPrintJob():IPrintJob
		{
			throw new IllegalOperationError("PrintCenter.createPrintJob() - override in subclass");
			return null;
		}
	}
}

LowVolPrinterCenter Class
This is a class the client classes use. The PrintCenter super class contains the print() method clients use to print a document. The LowVolPrinterCenter then creates the correct IPrintJob class to do the work. In this case it is the InkJetPrintJob class. If programming requires using another IPrintJob class, the change does not impact the print() method interface client classes use.

package printcenters
{
	import com.lonhosford.util.debug.lite.Debugger;
	/**
	 * LowVolPrinterCenter creator class
	 * */
	public class LowVolPrinterCenter extends PrintCenter
	{
		private var debugger:Debugger = Debugger.getInstance();
		public function LowVolPrinterCenter()
		{
			debugger.write("LowVolPrinterCenter() - This is a creator.")
		
		}
		/**
		 * Create InkJetPrintJob object.
		 * @return InkJetPrintJob
		 * */
		override protected function createPrintJob():IPrintJob
		{
			debugger.write("LowVolPrinterCenter.createPrintJob()");
			return new InkJetPrintJob();
		}
	}
}

HighVolPrinterCenter Class
This is a second subclass to the PrintCenter class. It uses the IPrintJob class WorkgroupPrintJob.

package printcenters
{
	import com.lonhosford.util.debug.lite.Debugger;
	/**
	 * HighVolPrinterCenter creator class
	 * */
	public class HighVolPrinterCenter extends PrintCenter
	{
		private var debugger:Debugger = Debugger.getInstance();
		public function HighVolPrinterCenter()
		{
			debugger.write("HighVolPrinterCenter() - This is a creator.")
		}
		/**
		 * Create WorkgroupPrintJob object.
		 * @return WorkgroupPrintJob
		 * */
		override protected function createPrintJob():IPrintJob
		{
			debugger.write("HighVolPrinterCenter.createPrintJob()");
			return new WorkgroupPrintJob();
		}
	}
}


Now there are two PrintCenter classes available to client programs. Both use the print() method to print documents. Next we look at the IPrintJob classes starting with the interface.

IPrintJob Interface
This interface defines one method start() for all IPrintJob classes to implement.

package printcenters
{
	/**
	 * Sets the interface for print job product classes
	 * */
	public interface IPrintJob
	{
		/**
		 * @param fileName Name of file to print.
		 * */		
		function start(fileName:String):void;
	}
}

InkJetPrintJob Class
This class implements the IPrintJob interface and includes the required start() method on line 18.

package printcenters
{
	import com.lonhosford.util.debug.lite.Debugger;
	/**
	 * InkJetPrintJob product class
	 * */
	internal class InkJetPrintJob implements IPrintJob
	{
		private var debugger:Debugger = Debugger.getInstance();
		public function InkJetPrintJob()
		{
			debugger.write("InkJetPrintJob()")
		}
		/**
		 * Simulate starting an InkJetPrintJob
		 * @param fileName Name of file to print.
		 * */		
		public function start(fileName:String):void
		{
			debugger.write("InkJetPrintJob.start() - fileName:" + fileName);
		}
	}
}

WorkgroupPrintJob Class
Like the InkJetPrintJob class this class implements the IPrintJob interface and includes the required start() method on line 18.

package printcenters
{
	import com.lonhosford.util.debug.lite.Debugger;
	/**
	 * WorkgroupPrintJob product class
	 * */
	internal class WorkgroupPrintJob implements IPrintJob
	{
		private var debugger:Debugger = Debugger.getInstance();
		public function WorkgroupPrintJob()
		{
			debugger.write("WorkgroupPrintJob()")
		}
		/**
		 * Simulate starting an WorkgroupPrintJob
		 * @param fileName Name of file to print.
		 * */		
		public function start(fileName:String):void
		{
			debugger.write ("WorkgroupPrintJob.start() - fileName:" + fileName);
		}
	}
}

Adding to the PrintCenter class
It is relatively easy to add another PrintCenter class. Here is the FancyPrintCenter class that creates the IProduct class MultifunctionPrintJob. Create the classes in the and see if you can add them to the application Chapter02_Factory_PrintCenters class.

FancyPrinterCenter class

package printcenters
{
	import com.lonhosford.util.debug.lite.Debugger;
	/**
	 * FancyPrinterCenter creator class
	 * */
	public class FancyPrinterCenter extends PrintCenter
	{
		private var debugger:Debugger = Debugger.getInstance();
		public function FancyPrinterCenter()
		{
			debugger.write("FancyPrinterCenter() - This is a creator.")
		}
		/**
		 * Create IPrintJob object.
		 * @return MultiFunctionPrintJob
		 * */
		override protected function createPrintJob():IPrintJob
		{
			debugger.write("FancyPrinterCenter.createPrintJob()");
			return new MultiFunctionPrintJob();
		}
	}
}

MultiFunctionPrintJob class

package printcenters
{
	import com.lonhosford.util.debug.lite.Debugger;
	/**
	 * MultiFunctionPrintJob product class
	 * */
	internal class MultiFunctionPrintJob implements IPrintJob
	{
		private var debugger:Debugger = Debugger.getInstance();
		public function MultiFunctionPrintJob()
		{
			debugger.write("MultiFunctionPrintJob()")
		}
		/**
		 * Simulate starting an MultiFunctionPrintJob
		 * @param fileName Name of file to print.
		 * */		
		public function start(fileName:String):void
		{
			debugger.write ("MultiFunctionPrintJob.start() - fileName:" + fileName);
		}
	}
}

Part 2 introduces parameters for selection product classes.