Best Practices: Seeing Patterns: The Factory Method
This article may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist. To maintain the flow of the article, we've left these URLs in the text, but disabled the links.
Best Practices: Seeing Patterns: The Factory Method
Jefferey A. Donnici
This months Best Practices column closes out the "Seeing Patterns" series with an examination of the Factory Method pattern. The Factory Method design pattern is the second Creational pattern to be discussed in this series. While its not a terribly complex pattern, it does have a few unique traits that make it distinctive among the patterns Jefferey Donnici has discussed so far. When a class is responsible for creating other objects at runtime, the Factory Method pattern allows the subclasses to decide which objects to instantiate.
One of the many problems that object-oriented software development is meant to solve is the difficulty with creating dynamic applications that change their behavior at runtime. Any number of factors might affect a systems behavior, from user interaction to historical data values, and in many cases theres more than one factor to be considered at a time. As such, our applications have to have a variety of behaviors and functionality to address these conditions. Because we encapsulate behavior and functionality into distinct objects, this typically means dynamically creating an object based on the runtime needs of the system.
This months pattern, and the final pattern in this "Seeing Patterns" series, is the Factory Method. This pattern helps address this problem of "dynamic creation" by providing a design solution that allows the application to create different objects based on the current system state. As with the last couple of patterns, the Factory Method is a pattern that doesnt get as much "word of mouth" in online discussions and printed publications as some of the other, more popular patterns (the Bridge and Mediator patterns come to mind). My guess is that the Factory Method pattern, like the Template Method I discussed a couple of months ago, is just one of those patterns that doesnt immediately strike an "A-ha!" response from developers who read about it. Youll learn in this article that theres really no rocket science happening in designs based on this pattern; its a fairly straightforward pattern that, when you need it, can really be a lifesaver.
And for the final time in this series, let me run through the essential introductory information about the "Seeing Patterns" series. The idea behind this series, which started with the November 1998 issue of FoxTalk ("Seeing Patterns: The Bridge"), is to look at object-oriented design patterns individually, with a different pattern being discussed each month. The thing that makes these discussions different from most patterns articles in the object-oriented world is that the patterns are presented using Visual FoxPro examples and concepts. All of the examples use Visual FoxPro, and the VFP base classes are referred to when a specific type of class is being discussed. If this is the first month that youre tuning in for this series, Id humbly suggest that you check out some of the earlier Best Practices columns in this series. The first few columns in the series contain basic information about the concepts behind object-oriented design patterns, as well as details about the different types, or families, of patterns. The August and September 1999 columns served as a "mid-semester" break, using a question-and-answer format to discuss some of the common questions that have come up in the series. If this is the first month youre joining the series, those issues might be helpful in terms of catching up with whats been covered thus far.
Every pattern in this series, including this months Factory Method pattern, was initially presented to the object-oriented development community in Design Patterns: Elements of Reusable Object-Oriented Software, by E. Gamma, R. Helm, R. Johnson, and J. Vlissidescommonly referred to as the "Gang of Four" or "GOF" (published by Addison-Wesley, ISBN 0-201-63361-2). This book is also available on CD-ROM, including source code examples and hyperlinks between chapters and topics. As you read any of the columns in this series, you might find it useful to have the book or CD-ROM nearby as a reference.
And finally, its important for me to point out that Visual FoxPro is merely the language Im using to demonstrate the patterns in these series. The patterns, however, are object-oriented design patterns and not Visual FoxPro design patterns. Every pattern in this series can be (and is) used in just about any other object-oriented development environment. And because an "object-oriented design pattern" describes a solution to an object-oriented design problem, any implementation examples (code or diagrams) used in this series shouldnt be assumed to be the only possible implementations of designs based on these patterns. In other words, your mileage may vary, some restrictions apply, contest rules are subject to change, and this offer not valid in Wisconsin.
The Factory MethodAs I mentioned previously, the Factory Method pattern is really pretty simple to understand, provided that you recognize the never-underemphasized importance of the interface in object-oriented programming. By interface, I dont mean the more common "user interface" usage, which describes the windows and controls that a user interacts with while theyre using the application. Instead, I mean the programmatic interface that an object exposes to other objects within the system.
The programmatic interface consists of the member methods (and those methods parameters and return values) that an object uses to interact with other objects. If youve made member properties publicly available in your class definitions, then those properties also become a part of the objects interface at runtime.
As with the Template Method pattern (see the Best Practices column in the November 1999 issue of FoxTalk"Seeing Patterns: The Template Method"), the Factory Method pattern centers around a single method on an objects interface and, more importantly, the "door" that that method opens to increased reusability and/or functionality. Where the Template Method is a behavioral pattern, therefore addressing runtime object behavior issues, the Factory Method is a creational pattern.
Creational patterns address some aspect of the instantiation process wherein a class definition becomes an object within the system. Creational patterns serve to abstract the instantiation process so that it can be used to dynamically affect the behavior of the system based on the systems runtime state. As explained in Design Patterns, there are two types of creational patterns: "A class creational pattern uses inheritance to vary the class thats instantiated, whereas an object creational pattern will delegate instantiation to another object." Prior to this month, the only other creational pattern to be discussed in this series was the Singleton pattern (see the May 1999 issue of FoxTalk). While the Singleton is an object creational pattern, one of the fundamental assumptions in the Factory Method is that inheritance will be used, making it a class creational pattern.
With the Factory Method pattern, the idea is that a single method handles the creation of certain types of objects, providing an instantiated object to the system when its finished. Because this method is serving to create the object, the purpose of the word "factory" in the patterns name becomes immediately obvious. Most of the time, the Factory Method pattern is used with application frameworks or highly reusable and modular components. The component will typically have a method (or more than one) that creates some other object needed by the component, but the component doesnt know in advance what type of object it will be interacting with. Instead, it calls the factory method with the understanding that an object of a certain class-type will be created and either returned or otherwise made available to the component. By expecting an object of a specific class-type, the component is expecting an object thats at least a certain class within a class hierarchy; in other words, either a specific class or some subclass of that class.
By providing the Factory Method pattern, the component is stating that its subclasses should know which class to instantiate. As mentioned previously, this reliance on inheritance is what makes this pattern one of the "class creational" patterns (see Figure 1).
Putting it togetherSo how do factory methods in the subclassed components know which type of class within a class hierarchy to instantiate? As with many things in Visual FoxPro, it depends. In truth, the designer (thats you, by the way) can use a variety of methods to decide which approach to use in any given circumstance:
- 	You might have an abstract "creator" class that just provides the basic implementation around the factory method and leaves the decision over which ancillary class to instantiate (as well as how to instantiate it) entirely to the subclass.
- 	You could use a concrete "creator" class that provides a basic, "default" implementation so that the majority of situations are covered, and the creator class subclasses can handle the exceptions.
- 	Another option is to use some external mechanism for determining the class to instantiate, such as a GetUtilityClass or similar method.
- 	Finally, you might use a parameterized Factory Method so that a single "creator" can create multiple utility classesthe indicator for which class to instantiate comes into the Factory Method as a parameter, perhaps with the resulting object itself returned as the return value.
Regardless of which method you choose for deciding which class to instantiate, youve gained a significant amount of flexibility and reusability by having the Factory Method within the class create the object the component will need at runtime. In doing so, the Factory Method serves as a "hook" for subclasses to over-ride to provide some other, more specialized, version of the classs functionality (at least with regards to its associative relationship with other objects at runtime).
Theyre everywhere!As youve probably gathered by now, the Factory Method pattern is really a fairly small pattern, in terms of what its implementation looks like. Unlike other patterns, such as the Mediator or Bridge, the Factory Method and Template Method patterns are both relatively simple to "see in action." For an example of the Factory Method, Ill turn one last time to the Codebook application framework (from the book/CD combination, The Visual FoxPro 3 Codebook, by Y. Alan Griver, published by Sybex). If youve been following along for awhile, I suspect youve probably picked up an old copy by now to see what all of the fuss is about. When the Visual FoxPro community went object-oriented, nobody was ahead of the Codebook framework authors when it came to understanding and applying many of the more advanced object-oriented techniques.
At the core of the Codebook framework is the cApplication class, which is the abstract class from which any Codebook application object is subclassed. Because the cApplication class is a subclass of the cChildCollection class, it has a LoadChildren method that adds a variety of member objects to the application object (the baseclass for the collection classes is Container). For more details on how this works, see the Template Method discussion in the November 1999 Best Practices column. One of the objects thats added as a member, or child, object is the oToolbars object, a collection of the applications toolbars. This is specified by the LoadChildren method in the population of the aChildren member array:
laChildren[2, CHILD_CLASS] = "CToolbarCollection" laChildren[2, CHILD_NAME] = "oToolbars"
An instance of the cToolbarCollection is created, given the name oToolbars, and added as a member object to the application. With that in place, the application has a place to "hang" the toolbars that it might need during the lifetime of the application.
But how does it know which toolbar to create initially? Enter the Factory Method pattern.
While the process for creating a toolbar can remain consistent from one application to the next, especially given the strong toolbar base classes provided, the decision over which toolbar to create is left to the subclassesthat is, those classes that represent actual applications.
Within the cApplication class, theres a Do methodthis method provides the fundamental wait state for any Codebook-based application. This is where the READ EVENTS for the application occurs, and theres not much for that method to do but "run" the core application. Prior to the Do method being called, the development environment settings have been saved, and different settings have been changed as required for the application. This leaves the basics for the Do method:
THIS.ShowMenu() THIS.ReleaseSplash() THIS.ShowToolbar() *-- Shutdown handler omitted for clarity READ EVENTS
In total, there are fewer than 10 lines of code in the Do method, but our focus for this discussion is on the ShowToolbar method. Its there that we can see the Factory Method implemented in a clear, concise fashion. This method simply adds the toolbar object to the oToolbars collection previously created. Again, the means of adding the toolbar is consistent for all subclasses of cApplication, but each application must know which toolbar to create as part of its initial startup.
Here are the relevant lines of code from the ShowToolbar method:
IF NOT EMPTY(THIS.cMainToolbarClass) *-- UI message call omitted for clarity IF THIS.oToolbars.Add(THIS.cMainToolbarClass) THIS.oMainToolbar = ; THIS.oToolbars.Get(THIS.cMainToolbarClass) THIS.oMainToolbar.Show() ENDIF ENDIF
Notice the very first line of codethe method is checking to see whether a property of the application class, cMainToolbarClass, is present. Its there that our factory method, ShowToolbar, determines in the subclasses which toolbar class to instantiate. Assuming that the cMainToolbarClass property is populated with a string containing the name of a toolbar class definition available to the application, that toolbar becomes the main toolbar for the system.
From there, the method proceeds to tell the oToolbars collection to add an instance of that class to itself. If that process succeeds, the method gets an object reference to that new toolbar and assigns it to its own oMainToolbar object propertythis allows the application and its main toolbar, presumably the toolbar referenced most often by the application, to communicate directly via that object reference. Finally, the method calls the Show method to make the toolbar visible to the user.
Ta-da! The Factory Method pattern really is that simple. While there are probably dozens of variations on this particular implementation, the motivating principle behind this pattern is present. The basic idea is to provide a method in a superclass that will create some sort of utility object that the overall component will need at runtimethe key, however, is that the class defers to its subclasses to decide which class to instantiate and how that class should be instantiated.
Whew!Well, that wraps up the Best Practices "Seeing Patterns" series. Hopefully, Ive achieved the goals I outlined when the series started more than a year agoto discuss object-oriented design patterns in a way thats familiar to Visual FoxPro developers and to dispel some of the myths or "black magic" surrounding design patterns. I know that, by virtue of writing about them, Ive gained quite a bit more understanding of how to really use these patterns in my own work. With any luck, some of you have gained similar insights or otherwise found the past years worth of Best Practices columns to be worthwhile in your object-oriented design work.
Next month, the Best Practices column returns to "normal" (Yeah, right!Ed.), with the usual fare of topics chosen to separate the hackers from the programmers from the professional software developers. As always, feel free to let me know if you have any suggestions or comments for this column.
Jefferey A. Donnici is the senior Internet developer at Resource Data International, Inc. in Boulder. Jeff is a Microsoft Certified Professional and a five-time Microsoft Developer Most Valuable Professional. 303-444-7788, fax 303-928-6605, firstname.lastname@example.org, email@example.com.
To find out more about FoxTalk and Pinnacle Publishing, visit their website at http://www.pinpub.com/html/main.isx?sub=57
Note: This is not a Microsoft Corporation website. Microsoft is not responsible for its content.
This article is reproduced from the January 2000 issue of FoxTalk. Copyright 2000, by Pinnacle Publishing, Inc., unless otherwise noted. All rights are reserved. FoxTalk is an independently produced publication of Pinnacle Publishing, Inc. No part of this article may be used or reproduced in any fashion (except in brief quotations used in critical articles and reviews) without prior consent of Pinnacle Publishing, Inc. To contact Pinnacle Publishing, Inc., please call 1-800-493-4867 x4209.