avoid mickey mouse programming
Using the Abstract Factory pattern with Flex
Accordingly to the Gang of four the Abstract Factory pattern intent is to provide an interface for creating families of related or dependent objects without specifying their concrete classes.
This design pattern actually ensures that the patterns automatically get and use the correct object accordingly to the context in which the client is working.
There are many different situations in which this pattern can work, imagine for instance a system in which the drawing and printing method varies accordingly to the resolution supported by the system; the system has to use different drivers in different cases.
At a first glance you may be tempted to use two different switch case for the drawing and printing procedure in which your system reacts in a different way accordingly to the resolution but remember that switches may indicate the need of abstraction in your system and that it can bring your system to a combinatorial explosion (imagine to add new drivers for each different resolution and create and even more complex switch case).
A good way to solve this issue us to create a Factory that creates the appropriate object accordingly to the resolution supported by the system, in this way you avoid the combinatorial explosion I mentioned and you can keep the switches in a single place or even better accordingly to the language you are working on and to your code style you can avoid switches also in the factory.
We have talked since now about two possible families of objects to use, monitor and printer drivers. Give me a chance to introduce you to a more complex system, an e-commerce with a group of families related to the system payments
• Credit Card
• OnLine payment
• Other payment
For each of these families you may have the need to define multiple objects when you system starts
• Credit Card
o Visa
o American Express
o Master Card
• OnLine payment
o Paypal
o E-check
• Other payment
o Wire transfer
o Check
and add even more objects when the system grows or when new payment methods will be released over the net.
In an e-commerce system you may also have the need to show to the user the appropriate payment system accordingly to his preferences, in order to increase the abstraction of your system you can define multiple Abstract classes and keep the system ignorant on which particular implementation is in use because the factories are the responsible to instantiate them.
Imagine the scenario I described an put it in an UML diagram

The application is composed by a form that contains a submit button and the form fields vary accordingly to the user preferences retrieved by the system.
The CheckOutFactory class is an abstract class that have two concrete implementations able to return to the client the UI needed for each payment (actually the MXML representation of the class). The PaymentContainer is a VBox with a property used to store a reference to the payment form created from the factory that implements an interface that defines two common methods of the payment forms
• validateFields() • submit()
As you know ActionScript 3.0 doesn’t support abstract classes, so the CheckOutFactory simulates the abstraction of the class trough the use of an internal class in its constructor.
Another good way to implement the abstraction is the use of interfaces, this is the reason why I defined a common interface ICheckOut and two other interfaces (IOnlinePayment and ICreditCard) that extend the base interface and that will be implemented in the view of each payment form of the system.
Take a look to the class hierarchy in order to understand where we are and where we are going
The abstraction of the on-line and credit card payments is reached through the interfaces put on the top of the onLinePayment and creditCardPayment packaging, the view and it’s logic has been keep separated through the Model View Presenter pattern used from each payment form.
Each presenter implements a public submit() method, in this way you can call in a centralized fashioned way the submit of each form trough the PaymentContainer property named element, each presenter will have the responsibility to recover the data from the view and each view, due to the fact that implements the ICheckOut interface, validate it’s fields (a good idea is to validate each credit card with a different Validator, this is the reason why you find an instance of the CreditCardValidator class in the credit card payment forms.
In order to run this sample (view source enabled) I created an XML file that stores the name of some users and the payment preferences, each node has the following structure
<user name = "Giorgio Natili" mode = "OnlinePayment" type = "PayPal" />
In the main application a combo box is populated with this data and each time you change the selection a concrete factory is created and through the factory a new view is added to the PaymentContainer
private function onUserSelection(e:Event):void{
checkOutFactory = CheckOutFactory.getPaymentFacotry(e.target.selectedItem.@mode);
var s:String = e.target.selectedItem.@type;
checkOutModule = checkOutFactory.getUI(s.substr(0, 1).toLocaleLowerCase() + s.substring(1, s.length) + ".view." + s + "View");
paymentContainer.element = checkOutModule;
}
The checkOutFactory and the checkOutMopdule properties data type represents the layer of abstraction I’m searching for
private var checkOutFactory:CheckOutFactory;
private var checkOutModule:ICheckOut;
The method defined as a listener for the click event inside the PaymentContainer uses the methods defined in the ICheckOut interface to complete his task
private function doSubmit():void{
if(_element.validateData()){
_element.submit();
}else{
Alert.show("Invalid data in the form...", "Attention!");
}
}
At the end of the day we have a quite flexible sample, but which are the benefits of this pattern? It would be simpler to have a switch instead of all this code?
The main benefit is that if you have to add the support for another credit card you have to deal only with the logic stored in the MVP triad you need to add a payment form and the system automatically will be able to handle the new form.
The switch could be hard to maintain in a situation with more than 4 payment methods, moreover the abstraction layer that the system has reached give to you the flexibility to put each developer you want on the new payment forms the system needs without having to explain to the developer anything about the system itself.
There are other possible contexts in which the Abstract Factory pattern can be used
• Handle different operating systems API in a cross platform application
• Different traits for users of an application
• Different version of an application
• Different performance guidelines
At the end of the day we can recap with the following points the Abstract Factory pattern
• You want to have families or sets of objects for particular clients
• Families of related objects have to be instantiated
• You want to coordinate the creation of families of objects
• You need to isolates the rules of which objects are to be made
Obviously this is only a small sample and more complex implementation are out of the scope of this blog entry, so feel free to open a discussion on this topic.
| Print article | This entry was posted by Giorgio Natili on February 13, 2009 at 7:21 am, and is filed under design patterns, samples, solutions. Follow any responses to this post through RSS 2.0. You can leave a response or trackback from your own site. |
about 1 year ago
I would like to extend your work with some considerations:
The credit card presenters have a duplicated submit method, because all the credit cards have the same fields, regardless of the type (Visa, American Express, etc).
Maybe it would be better to write a CreditCardPresenter super-class, that implements the submit() public method and from which AmericanExpressCreditCard e VisaCreditCard derive.
We can do also another thing: CreditCardPresenter, ECheck and PayPal classes have to create their own VO (Value Objects), in order to communicate, for example, with a server. VO are of three different types because, for each of those payment types, there are different informations to provide.
However, you can think to unify the submit method with an empty interface (e.g. IPayment) that all the VO have to implement.
Following this approach, the submit method can send an IPayment object and can be shared by all the presenters.
So we can have a super-presenter that implements the submit method and we can reach a more abstract, modular and flexible structure.
I’ve send you a class diagram that should explain better what I mean.
about 1 year ago
Very good job! I think that you should write other articles related to the design patterns, because your approach is very easy to understand and implement following the examples.
about 1 year ago
Hi Emanuele,
Thanks for your comment, I believe that your idea is good, the only concern that I have is if you encounter in your development a server side team that is not so smart, but it’s trough, sending a value object and handling it on the server is a smarter solution…