By paddloPayday loans

Home > Factory Method, Lazy Initialization > ActionScript 3.0 Lazy Initialization and the Factory Method Design Pattern

ActionScript 3.0 Lazy Initialization and the Factory Method Design Pattern

Lazy Initialization

Lazy Initialization

The other day I was re-reading Chandima’s description of key OOP concepts used in the Factory Method design pattern. It is beautifully encapsulated in a little over a half a page (page 84). The Factory Method allows you to separate the creation of objects from their use. It says a bit more, but it is a nice piece in both describing a design pattern principle and explaining what the Factory Method does. This led to re-reading the Factory Method chapter in Design Patterns: Elements of Reusable Object-Oriented Software—the Gang of Four’s book. Normally, I just go over the main points, but I came across a little passage that read:

Just be careful not to call factory methods in the Creator’s constructor—the factory method in the ConcreteCreator won’t be available yet. (page 112)

The comment was directed at some issues in C++ which may or may not have any bearing on ActionScript 3.0, but just in case it did, I continued reading. The point being made was you can avoid these problems by accessing products only through accessor operations that create products on demand. So what are accessor operations? Generally these are public methods that you can call to initiate creation of a product.

Time Out! Before we get too far ahead of ourselves, you can download all of the .as files for the Factory Method example by clicking the following button:
kilroy

The example is a simple one that creates three different shapes—ellipse, rectangle and triangle. Figure 1 shows how the Client arranged them to display a house in front a a pond with a cloud overhead:

<em><strong>Figure 1:</strong>Triangle, Ellipse and Rectangle Products</em>

Figure 1:Triangle, Ellipse and Rectangle Products

The program uses concrete creators to fetch shapes. The Client makes requests that size, color, and position the shapes.

Don’t Enslave Your Constructor Functions

This issue of the constructor functions reminded me of a post by Miško Hevery, the guy at Google who helps set Google’s programming standards. One of the key flaws in a program is where the constructor does real work. Besides violating the single responsibility rule, Miško goes on to explain the tell-tale signs that one has used his constructor function with outrageous disregard for both agile programming and loose coupling. As a result of reading Hevery’s work, a year or so ago, I began to seriously gear back on using a class’ constructor function; primarily by not including one in most of my classes. (My Client class is a glaring exception to the rule.) I’d usually have just the properties and operations (methods, functions) that I needed. The properties would initialize themselves—sort of. They’d be given an ID and then typed and that was all. The child classes could then use them in operations. Whenever I needed something, the Client would type a request to the interface (including abstract classes) and then make a request through concrete method in an operation. With the Factory Method, I make requests to the ConcreteCreator through the abstract Creator class.

In returning to GoF, they point out,

Instead of creating the concrete product in the constructor, the constructor merely initializes it to 0. (Page 112)

In this discussion, they note that Factory methods in C++ are always virtual functions. WTF?! (What’s That Function?!) Simply stated, any function that can be overridden in the child classes is a virtual one. Well, we can do that in ActionScript 3.0. In fact, that’s what we do in creating Abstract classes. (Why we can override and yet not have real Abstract classes is still a mystery to me.)


But what about the constructor function—especially in an Abstract class that you cannot instantiate anyway? Well, there’s an automatic constructor in all classes; so if we initialize a product like this:

protected var product:Product;

It will be automatically initialized in the Creator. Or will it? The answer is sort of. The accessor is going to return the product in the ConcreteCreator, but it first checks to see if it exists. Even though we initialized the product in the Creator which is inherited by the ConcreteCreator, it does not exist until a new instance is declared.

The process of first checking to see if the product exists before instantiating it is called…ta da!…lazy initialization!

So, while ActionScript 3.0 may not be exactly like C++ in how it manages memory, they appear to share lazy initialization. In our Factory Method design, the following shows the generic code for this kind of lazy initialization (in a ConcreteCreator class that has inherited the product property from the Creator class):

?View Code ACTIONSCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
override public function factoryMethod():Object
{
	if (! product)
	{
		product=new ConcreteProduct();
		trace("new one");
	}
	else
	{
		trace("reusing existing product");
	}
	return product.getProduct();
}

The above code includes trace statements to see both new and existing products. All of the ConcreteCreator classes include this type of lazy initialization.

To understand how memory is allocated you need to understand something about garbage collection, and Grant Skinner’s post on this topic is an excellent resource. Likewise, Grant Skinner’s article on memory management is equally helpful in understanding the issues here that involve creating optimum code. Keep in mind that we’re dealing with lazy initialization, and garbage collection and memory management are the details of how existing objects are allocated memory space and how they come to be deallocated in the process of garbage collection. Assume that the Flash player will handle memory allocation (and deallocation) as best it possibly can, but we need to be cognizant of what we’re doing as well. In setting up our Factory Method, we have learned that initialization does not create an object.

A Simple Factory Method Program

I’ve created a simple Factory Method example that displays different objects. Each of the three objects is a Product subclass and each of the three objects has its own concrete creator, all subclasses of a Creator class. The Product and Creator classes are abstract and so we can think of them as interfaces—program to the interface and not the implementation. All of the object creation begins with the Client class with a call to the factory to create the desired object; so the Client needs to have control over object creation. Figure 2 shows the class diagram for the program:

<em><strong>Figure 2:</strong> Factory Method with Lazy Initialization</em>

Figure 2: Factory Method with Lazy Initialization

As you can see, it’s a pretty standard Factory Method design pattern, and if you’re just getting started with this pattern, it’s a good one to use as a generic base.

Creator Classes

Beginning with the Creator, we’ll work our way to the Client making requests. The Creator class is set up as an Abstract class where we can lazily initialize a product object:

?View Code ACTIONSCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package
{
	import flash.display.Shape;
	import flash.errors.IllegalOperationError;
	// ABSTRACT Class (should be subclassed and not instantiated)
	public class Creator
	{
		protected var product:Product;
 
		// ABSTRACT Method (must be overridden in a subclass)
		public function factoryMethod(hor:Number,v:Number,col:uint,w:Number,h:Number):Shape
		{
			throw new IllegalOperationError("Abstract method: must be overridden in a subclass");
			return null;
		}
	}
}

The product instance initialization provides a type, instance name and accessor. As there is no constructor function, one is automatically created and so product is available as a property and can be passed to the Creator child classes—the ConcreteCreators.

The key method for creators is the factoryMethod. Here, I gave it five parameters one each for x and y position, color, and width and height. This gives the user more flexibility, but I have to admit that I’m not crazy about that many parameters. In the past, I’ve used a single array where all of the parameter values can be placed. The ConcreteCreators all implement the factoryMethod by setting up lazy initialization (checking a product to see if it exists before creating a new one). I’ve placed all of the three ConcreteCreators in the following listing:

?View Code ACTIONSCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
//Create Rectangle
package
{
	import flash.display.Shape;
	public class RecMaker extends Creator
	{
		override public function factoryMethod(hor:Number,v:Number,col:uint,w:Number,h:Number):Shape
		{
			if (! product)
			{
				product=new RecShape();
				trace("new one");
			}
			else
			{
				trace("reusing existing product");
			}
			return product.getFigure(hor,v,col,w,h);
		}
	}
}
 
//Create Ellipse
package
{
	import flash.display.Shape;
	public class EllipseMaker extends Creator
	{
		override public function factoryMethod(hor:Number,v:Number,col:uint,w:Number,h:Number):Shape
		{
			if (! product)
			{
				product=new Ellipse();
				trace("new one");
			}
			else
			{
				trace("reusing existing product");
			}
			return product.getFigure(hor,v,col,w,h);
		}
	}
}
 
//Create Triangle
package
{
	import flash.display.Shape;
	public class TriMaker extends Creator
	{
		override public function factoryMethod(hor:Number,v:Number,col:uint,w:Number,h:Number):Shape
		{
			if (! product)
			{
				product=new Triangle();
				trace("new one");
			}
			else
			{
				trace("reusing existing product");
			}
			return product.getFigure(hor,v,col,w,h);
		}
	}
}

The manner in which lazy initialization is set up in each of the factoryMethod() methods shows when a new product is created and when an existing one is used. (If you want to clean it up, you can just use the first if statement and remove both the else clause and trace statements.)

Each of the creators returns a Shape object by calling the Product method, getFigure(). All of the concrete creator classes do pretty much the same thing, and their only difference is the concrete product each calls and returns.

Product Classes

The Product class is another abstract one with a single property and method. However, instead of a Product property, it has a Shape property. It is only initialized in the abstract class and then instantiated in the concrete products.

?View Code ACTIONSCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package
{
	import flash.display.Shape;
	import flash.errors.IllegalOperationError;
 
	// ABSTRACT Class (should be subclassed and not instantiated)
	class Product
	{
		protected var figure:Shape;
 
		public function getFigure(hor:Number,v:Number,col:uint,w:Number,h:Number):Shape
		{
			throw new IllegalOperationError("Abstract method: must be overridden in a subclass");
			return null;
		}
	}
}

Each of the ConcreteProduct classes draws the desired shape by overriding the getFigure() method. and creates a new Shape instance from the figure Shape object it inherits. (Again we find lazy initialization.) I had thought of instantiating the Shape in the Product abstract class and then each method would not have to. However, I’d been warned by Miško Hevery’s article about using the new keyword in a constructor function let alone an abstract class.

?View Code ACTIONSCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
//Draw Rectangle
package
{
	import flash.display.Shape;
 
	public class RecShape extends Product
	{
		public override function getFigure(hor:Number,v:Number,col:uint,w:Number,h:Number):Shape
		{
			figure=new Shape();
			figure.graphics.beginFill(col,.5 );
			figure.graphics.drawRect(hor, v, w, h)
			figure.graphics.endFill();
			return figure;
		}
	}
}
 
//Draw Ellipse
//Concrete Product
package
{
	import flash.display.Shape;
 
	public class Ellipse extends Product
	{
		public override function getFigure(hor:Number,v:Number,col:uint,w:Number,h:Number):Shape
		{
			figure=new Shape();
			figure.graphics.beginFill(col,.5 );
			figure.graphics.drawEllipse(hor, v, w, h)
			figure.graphics.endFill();
			return figure;
		}
	}
}
 
//Draw Triangle
//Concrete Product
package
{
	import flash.display.Shape;
 
	public class Triangle extends Product
	{
		public override function getFigure(hor:Number,v:Number,col:uint,w:Number,h:Number):Shape
		{
			figure=new Shape();
			figure.graphics.beginFill(col,.5 );
			figure.graphics.moveTo(hor,v);
			figure.graphics.lineTo(hor+w,v+h);
			figure.graphics.lineTo(hor-w,v+h);
			figure.graphics.lineTo(hor,v);
			figure.graphics.endFill();
			return figure;
		}
	}
}

That’s pretty much it. When I ran into a hitch, I decided to try and debug it by creating my own rectangle using the moveTo and lineTo methods. It was easy to add to this pattern; so, you can assume it’s been re-use and change tested.

The Client

Finally we come to the Client. Initially, I had planned to include a user interface, but I thought I’d let you create your own UI. (Why should I have all the fun?) All it does is to take the products and display them. If you want to make changes, it’s easy to do. All the requests are made through the Creator classes, and the only details that need concern us are getting the parameters straight.

?View Code ACTIONSCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package
{
	import flash.display.Sprite;
	import flash.display.Shape;
 
	public class Client extends Sprite
	{
		private var pond:Creator;
		private var house:Creator;
		private var roof:Creator;
 
		public function Client()
		{
			pond=new EllipseMaker();
			addChild(pond.factoryMethod(145,160,0x468966,300,120));
			//Add a cloud
			addChild(pond.factoryMethod(200,20,0xcccccc,100,50));
 
			house=new RecMaker();
			addChild(house.factoryMethod(250,100,0xFFB03B,75,50));
			//Add a door
			addChild(house.factoryMethod(270,120,0x8E2800,20,30));
			//Add a window
			addChild(house.factoryMethod(295,120,0x8E2800,20,20));
 
			roof=new TriMaker();
			addChild(roof.factoryMethod(285,75,0xB64926,50,25));
		}
	}
}

I’m sure that Miško Hevery would have a fit with the chores I gave the Client’s constructor class, but I decided that the Client doesn’t count because all it should be doing is making requests. As you can see, that’s all it does.

Seeing Lazy at Work

When you run the program, your trace output will be the following:

new one
reusing existing product
new one
reusing existing product
reusing existing product
new one

It first creates an Ellipse object and when it checks to see whether it exists or not, it finds a null; so it creates a new one. However with the next Ellipse, it finds that it exists, and so reuses it but changes the parameters. Then it creates one new Rectangle and then reuses it twice. Finally, it creates a single Triangle object but does not reuse it. The trace statements are a visual display of the lazy initialization.

Finally, just for the fun of it, see if you can figure out what the vintage Soviet poster says at the beginning of the post.(ленивое is the key!) You really should try your hand at adding more products and the creator classes that call them. While you’re at it, add a UI in the Client and really have some fun.

Share
  1. gropapa
    May 25, 2010 at 7:47 am | #1

    What about only leaving the check on the product instance in the abstract method, just adding a getConcreteObject() method that only builds an object.
    This method should then be overriden in the subclasses. It would allow you not to worry about the check of the product anymore.
    Another point in that if the constructor doesn t do real work… well it does in the Client class
    (Maybe I missed a point, my English is … well you know it would look like:

    ?View Code ACTIONSCRIPT
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    public function factoryMethod(hor:Number,v:Number,col:uint,w:Number,h:Number):Shape
    {
    	if(!product)
    	  product = getProduct(hor, v, col, w, h);
    	return product;
    }
    public function getProduct(hor:Number,v:Number,col:uint,w:Number,h:Number):Shape
    {
    	throw new IllegalOperationError("Abstract method: must be overridden in a subclass");
    	return null;
    }
  2. May 25, 2010 at 10:36 am | #2

    Hi Gropapa,

    As for the second part about having the Client constructor doing real work, I pointed out:

    …but I decided that the Client doesn’t count because all it should be doing is making requests. That’s exactly what it does.

    As the starting point, the Client is going to have to use its constructor function. The participants in the design patterns are the classes that should not have the constructor doing any real work—except the Client if it happens to be part of the pattern..

    Your first point about checking the product in the abstract method is an interesting idea. Could you expand on that a bit with a working class/subclass example?

    Kindest regards,
    Bill

  3. gropapa
    May 25, 2010 at 10:50 am | #3

    Well, as Misko talks a lot about unit testing and IoC, we could consider the Client as a light container (cf Spring, dependency injection principle) so it is ok for Client to instanciate the application objects (factories or singleton (not the pattern)
    I do not think there is a problem with doing business in the constructor for Client
    btw thanks for the article (I practice english the same time i learn stuff ;))

  4. May 25, 2010 at 10:57 am | #4

    Hi again Gropapa,

    Your English is much better than my practice of your language! BTW, what is your language?

    Kindest regards,
    Bill

  5. gropapa
    May 25, 2010 at 11:14 am | #5

    french .. and you how bad the french are about foreign language ;)
    tx

  6. May 25, 2010 at 11:22 am | #6

    Gropapa,

    Whenever I try to speak French, I sound awful! I love the sound of French (except when I speak it—which is seldom and not much.) So, your English is great compared to my French. Thank you for doing such a good job.

    Amicalement,
    Bill

  7. June 3, 2010 at 1:05 am | #7

    Hi there guys!

    Another interesting article! Dissecting the pattern in every hidden detail. This requires lots of insights and experience. Nice one!

    In my opinion, and experience, Abstract Factory and Factory Methods are the most “popular” design patterns. It’s really easy to spot where its needed (maybe I think that because I feel very comfortable with it).

    In a few hours I’m going to a presentation about Anti-patterns, something that I thought never heard before, but when I started reading I realize that everybody knows “a lot about it” they just don’t call it that way. They call it “instinct”. Here is a cool link with Anti-patterns catalog.
    http://c2.com/cgi/wiki?AntiPatternsCatalog

    Cheers guys!
    Bill_BsB

  8. June 3, 2010 at 2:26 am | #8

    Hi Bill,

    Those anti-patterns are so much fun! I read a few on the link you sent and it really cracked me up! The Big Ball of Mud anti-pattern is one of my favorite, but they’re all a great fun. What makes them even funnier is that they’re true!

    Speaking of variations, check out this Factory Method with the Client holding references to both the Creator and Product. (Ok, it’s PHP, but it’s pretty simple.)

    Elogios,
    Bill

  1. May 25, 2010 at 1:18 am | #1
  2. March 16, 2011 at 9:31 am | #2

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>