AbstractI propose a modern OO language update of the Parameterized Factory Creational Pattern [Gamma95]. It is compact since it folds the Factory method into an abstract base class, and imposes a package structure on its concrete subclasses. The design is demonstrated in Java, but is also applicable to C# and other modern object-oriented languages. 1 INTRODUCTIONSuppose you are the lead software designer-developer at Consolidated Morsels, which is building a system to control the manufacture of a wide variety of treats including hard candy, filled chocolates, and cookies. Since Consolidated is the parent company for the recently independent Hershzweil, Swietinuff, and Venus companies, many manufacturing details for each kind of treat will vary. Certain specifics about each hard candy, filled chocolate, and cookie are defined via configuration. However, you can reasonably anticipate that as yet unknown kinds of treats, from existing and future subsidiaries, will be manufactured. Furthermore, you would like to impose order not only on the class implementations, but also upon the Java package structure they inhabit. Since the quantities and kinds of candy to create will vary amongst locations, season of the year, and general economic conditions, a Java client object should only call a generic series of methods for whichever treat. 2 BASE CLASS AND SUBCLASSESSince the differences in processes between each kind of candy by each subsidiary are quite large, you design a single abstract base class containing method signatures for each top-level processing stage common across the treats:
The 6th step, Cleanup, however, can be handled in a common way in the base class. Therefore, by now you have most of the elements visible in the class hierarchy in Figure 1: Figure 1: UML class diagram of BaseTreatMaker and subclasses 3 THE FACTORY METHODNext, you need a Factory method of some kind to create the concrete types, which should depend on parameters handed to it. You have reviewed the Creational patterns [Gamma95], but believe there may be a more elegant solution taking advantage of Java language features. Of course, you know that in contrast to say biological inheritance, any OO superclass lacks the complexity of state of any of its children – and that the Factory by design knows nearly nothing of what it constructs [Gamma95]. Remembering that static methods in Java exist within the class but are not subject to inheritance, you realize that the factory method should in fact reside in the BaseTreatMaker in static (class) scope, and could thereby return its own type, rather than, say, the overly generic java.lang.Object. Thus we have a compact implementation: no separate Factory class required outside the implementation class hierarchy. And by returning the specific type BaseTreatMaker, you impose some useful discipline over the results of the Factory method, which should especially aid junior developers. The Factory method signatureYou impose a package structure through 1..n String arguments, which are appended to one another to build that structure. Here, they are appended to the package of the BaseTreatMaker, in the order of Subsidiary, then Treat, using the Java Reflection API. Also in our case, the class naming logic ensures that the name of the Maker subclass is constructed from the name of the kind of treat – HardCandyMaker, etc. Then to facilitate the passing of an arbitrary number of parameters to each subclass, with minimal type restrictions on them (in this case with uniquely keyed parameter objects) you add the Hashtable parameter. You might also pass some other Collection framework object like an ArrayList per your real-world needs, but note that in any case, only the implementing subclass and the client of BaseTreatMaker need know how many such parameters it should receive and of what type(s) – the base class by design should not know. So our factory method signature becomes Passing Parameters to the ConstructorAfter building the canonical form class name using the String arguments, we use the Class class methods that allow us to instantiate not merely a no-argument constructor, but a constructor with whatever parameters suit our implementation – here, just the Hashtable. If any of our concrete classes do not share the number and type of arguments that our factory code expects, the runtime java.lang.NoSuchMethodException will be thrown. (see the Swietinuff HardCandyMaker for an example you can enable). The last step is to cast the result from the Reflection API getConstructor method to conform to our return type BaseTreatMaker. Here is the factory method implementation from BaseTreatMaker, deliberately omitting the catch blocks (complete code available in a zip archive from http://www.fortuitous-consulting.biz): You’ll also see that the example code provides simple (and identical) implementations of some of the subclasses from the design – enough for the reader to flesh out real-world implementations. But to illustrate how a client could call the factory method, here’s the main method from the BaseTreatMakerClient, for our purposes in the same package as BaseTreatMaker: Here’s the NameValuePair class, which was left in the BaseTreatMakerClient.java since it is a very simple class only referenced by BaseTreatMakerClient: 4 IMPLEMENTATION GUIDELINESIn describing the Factory pattern, [Gamma95] mentions the option of subclassing the Factory class. However, I recommend against that – it can too easily lead to an unnececessarily complex class creation hierarchy. Alternatives are to refactor using just the one Factory method, or perhaps to create some additional, independent Factory for an additional, independent class hierarchy should integration be a poor design choice. Also note that the base Class need not be abstract, though it typically has been in my implementations. The pattern could also be implemented of course quite naturally in other object-oriented languages besides Java, especially in those including a package-like concept such as C# namespaces [Obasanjo07]. REFERENCES[Gamma95] Gamma, E., Helm, R., Johnson, R., and Vlissides, J., Design patterns: Elements of reusable object-oriented systems, Addison-Wesley, 1995. [Obasanjo07] Dare Obasanjo: "A Comparison of Microsoft’s C# Programming Language to Sun Microsystem's Java Programming Language", http://www.25hoursaday.com/CsharpVsJava.html#namespace, 2001/2007 About the author
Harold Fortuin: "A Modern, Compact Implementation of the Parameterized Factory Design Pattern", in Journal of Object Technology, vol. 9, no. 1, January-February 2010, pp. 57-63. http://www.jot.fm/issues/issue_2010_01/column5/ |
||||||||