Design Patterns
How to use “Factory Method”
2The Factory Method design pattern is a creational design pattern. This means that its main objective is to create objects. The official definition by GOF is as follows:
Define an interface for creating an object, but let the subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.
Note 1: By “decide” in the definition above it does not mean that the subclass magically decides which object to create (at least not in a parameterized version of the Factory Method). The decision actually happens in the client; however, the work of creating the appropriate object that the client is going to work with is done by the subclass that overrides the Factory Method.
Note 2: This pattern relies on inheritance for creating objects. The current trend is to use the Abstract Factory Pattern, which relies on composition.
Note 3: By “client” I mean the calling code, the final user of the API that makes up the subsystem.
The Problem
Consider a simple application that deals with vehicles with the following hierarchy in the mind map below:
Question: What would happen if we want to create a particular type of vehicle and we do not use any kind of Factory Pattern?
That we would be giving the client the responsibility of having to know how to instantiate a particular type of Vehicle. As far as the client is concerned it just wants a Vehicle, then it’s going to do whatever he wants with it.
Question: What would happen if we add many more types (Car, Truck, Bike) and many more subtypes (Van, Sedan …)?
In this example it may not be as obvious as we only have three types of Vehicles (Car, Truck, and Bike) and two specific implementations under each. But if we had ten different cars, trucks, and bikes then the amount of if/else logic that you would have to do in the client in order to instantiate the right type would be quite tedious. This is considered boilerplate code at the same time that is difficult to maintain.
Question: What if you want to add a new type of Vehicle (e.g a Boat)?
If you do not use the Factory Method or other Abstraction layer you would have to make changes to the client to support that.
Solution
The Factory Method
Since the definition of the Factory Method states that the purpose is to defer instantiation of an object in the family to a subclass, then we have to make the class that will contain the factory method abstract. Also to ensure that subclasses are the ones really responsible for the creation of a particular object (in our case it will be a Vehicle) we have to provide with an abstract method, this way subclasses must provide the implementation. This method is what is popularly known as the factory method. It usually takes the name of createXYZ or newXYZ (that seems to be the industry standard for what I have seen) . It looks as follows:
package factorymethod;
public abstract class VehicleFactory {
//Factory method
abstract Vehicle newVehicle(String type);
}
The Common Interface
The client should work with a known interface, this way it will allow us to change the subsystem transparently. It will look as follows:
package factorymethod;
import java.util.List;
public abstract class Vehicle {
public abstract List<String> getFeatures();
public abstract List<String> getSpecs();
}
The Factory
A Car Factory would be responsible for knowing all the types that fall under the category of Car. Do you see how much cleaner is to have the branching logic in this factory rather than having a big method somewhere with all types in there? It would look as follows:
package factorymethod;
public class CarFactory extends VehicleFactory {
@Override
Vehicle newVehicle(String type) {
if(type.equals("Sedan")){
return new Sedan();
}else{
return new Van();
}
}
}
The Product
This is what the client asked for:
package factorymethod;
import java.util.List;
public class Sedan extends Vehicle{
//Put some specific properties of a SEDAN here
//Put some other specific methods of a SEDAN here (To differentiate from Van for example)
@Override
public List<String>getFeatures() {
//Put code to query your Car database here
return null;
}
@Override
public List<String>getSpecs() {
//Put code to query your Car database here
return null;
}
}
The Client
Notice how the client uses the appropriate factory to go get the specific type of product. If the client wanted a Bike for the example, the Car and Truck factories would be ignored. Also notice that since the client gets a generic Vehicle product you can add many more specific products transparently without affecting the client code. It looks as follows (You could improve the client using Reflection like done at the end of this other post) :
package factorymethod;
public class Starter {
public static void main(String[] args) {
VehicleFactory vehicleFactory = new CarFactory();
Vehicle vehicle = vehicleFactory.newVehicle("Sedan");
vehicle.getFeatures();
vehicle.getSpecs();
}
}
Now you could repeat what I have done above for the BikeFactory, and TruckFactory and its corresponding products as follows (Click on the image to enlarge):
Important: Your Specific “Products” should really be different (algorithm or logic wise)
While studying this pattern carefully from Head First Design Patterns (p.129) there was something that bothered me with their Pizzas example. If you look at all their specific Pizzas there wasn’t really any difference between the products, only String values!!! Yes that is different but what good is that in real life? If all that was read from a database for example you could get away with one class only. There was no need for 8 different Pizza types.
So my point is to make sure that you really have a different algorithm or logic in each specific product. Otherwise you will have added DRY (Don’t Repeat Yourself) in your application. (Unless I am totally missing something here
)
In our example we could say that we originally started our application supporting Cars only (Sedans and Vans), but then our application became popular and we decided to buy two existing databases that had support for Trucks(Pickup and Commercial) and Bikes(Scooter and DirtBike). Then it is safe to say that we need all these concrete objects as each getFeatures() and getSpecs() would contain an specific query targeting that particular data model and RDBMS.
Conclusions
Similar to the Adapter pattern where the main goal was to decouple the client from the actual implementation by giving it a known interface, the Factory Method Pattern also gives us that kind of flexibility. You should use a factory method:
- When you want to hide object creation knowledge from the client.
- When you want the client to always get a known interface. In this case, it will be an abstract object.
- When you want to add multiple implementations transparently in the future without affecting the client(s) API.
- To avoid branching “spaghetti code” when you have multiple variations of an object and you try to solve it by means of a lot of “if/elses” in a single location.
- When you have multiple variations of a particular object and you do not have a default one.
- It is also very good to illustrate how Polymorphism works.
Disadvantages:
- It depends on inheritance, so changes to the superclass can break existing code in subclasses. Inheritance usually requires thorough testing so Joshua Bloch in Effective Java recommends to use Composition over Inheritance.
- Joshua Bloch also recommends to use inheritance only when classes are designed for inheritance. (The factory method is designed for inheritance, so not really a disadvantage).
- This pattern is only good for a hierarchy of three levels. I have tried solving this with more levels and I had to much more inconveniences than advantages (had to create intermediate empty classes that were not bringing more information). For such situations, you should look into the Builder Pattern.
How to use the Adapter pattern
4The definition of the Adapter design pattern according to GOF (Gang Of Four) in Design Patterns: Elements of Reusable Object-Oriented Software is as follows:
Converts the interface of class into another interface the clients expect. Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces. (p.139)
To illustrate it we are going to start with a code base and then try to integrate it to an “external” code base using the Adapter design pattern.
The adapter pattern comes in two flavors:
- Object Adapter: Uses interfaces to benefit from polymorphism; this flavor is used if your language of implementation is Java.
- Class Adapter: Can be used in languages that support multiple inheritance, this technique can be used if your language of implementation is C++.
In this example we are going to look at the Object adapter implementation.
Note 1: I interpret that “clients” in the definition by Gang of Four above means the calling code. In some instances “client” might also refer to the starting code base.
Note 2: “Interface” in the definition by Gang of Four above means properties and methods of a class. But it can also be a proper Java interface.
Requirements
Conceptually both systems that you are trying to integrate must have a coherent conceptual correspondence.
Implementation
A real life example of adapters I faced is when I have purchased Europe based electronic devices that I later had to use in the US. In order to power them up, or charge them up depending on the device I had to get a Targus Travel AC Power Adapter. Recall that the adapter worked in that case because even though the interfaces were different, the problem domain was the same.
Let’s say that we have a program that works with US based heating devices; its reputation is so good that it has become a market leader, so now we want to go global and sell it in Europe and other parts of the world.
Starting Code Base
Because we are good OO coders, we code to interfaces. Here is our interface for US heating devices:
package adapter;
public interface USHeatingDevice {
public int voltage();
public int frequency();
}
Here is an implementation of our interface:
package adapter;
public class TowerHeater implements USHeatingDevice {
public int voltage() {
return 120;
}
public int frequency() {
return 60;
}
}
Here is what I interpret as the client per Note 1 above:
package adapter;
public class Starter {
public static void main(String[] args){
USHeatingDevice usHeatingDevice = new TowerHeater();
System.out.println(usHeatingDevice.voltage() + " V");
System.out.println(usHeatingDevice.frequency() + " Hz");
}
}
Running the program produces the following output:
120 V
60 Hz
Now we want/need to expand our program to work with foreign heating devices manufactured in Europe, South America, Asia etc. The problem is that their voltage and frequency are not the same, so our program will not work. Imagine that there is a vendor that has already developed an interface that can be hooked into our program so that it can work internationally. The code is illustrated below.
Vendor Code Base
Because the vendor also uses good OO techniques, here is their interface for non US heating devices:
package adapter.vendor;
public interface NonUSHeatingDevice {
public int tension();
public int hertz();
}
Here is their European implementation:
package adapter.vendor;
public class EUTowerHeater implements NonUSHeatingDevice {
public int tension() {
return 230;
}
public int hertz() {
return 50;
}
}
Notice two things here:
- The voltage and frequency have different values.
- The interface methods developed by the vendor have different names.
Problem
In order to use our program using the non US implementation we would have to find all our places where we make calls to voltage() and frequency() and put some sort of if/else logic to support calling tension() and hertz() methods when using the program in Europe.
Solution
Well that could be quite tedious, couldn’t it? Here is where the design pattern comes into place; the goal is to write and adapter that will implement our current existing interface (USHeatingDevice) but in reality will be executing an implementation of (NonUSHeatingDevice) interface. This technique will allow us to keep voltage() and frequency() calls throughout or code and we will only have to make a small change in the calling code, the client.
Note: Some authors state that the adapter pattern allows you to not do any code changes in the “client” once you have created the adapter class see (p.237) of Head First Design Patterns. I completely disagree with that and you will see it in the following snippets.
First let’s create the adpater:
package adapter;
import adapter.vendor.NonUSHeatingDevice;
public class HeaterAdapter implements USHeatingDevice {
private NonUSHeatingDevice europeanHeatingDevice;
public HeaterAdapter(NonUSHeatingDevice europeanHeatingDevice){
this.europeanHeatingDevice = europeanHeatingDevice;
}
public int voltage() {
return europeanHeatingDevice.tension();
}
public int frequency() {
return europeanHeatingDevice.hertz();
}
}
We see as follows:
- The Adapter class implements our known interface (USHeatingDevice), the one we are used to work with (because it will be the one that the client will continue to work with).
- The Adapter class has a data member that is of type that we are adapting to (NonUSHeatingDevice).
- The implemented methods call the matching methods in the non US heating device interface.
As you can see we are dressing up the HeaterAdapter by making it look like a US heater device, but really behaving like a non US heater device.
Now let’s make the changes to the client to work with the HeaterAdapter that we have just created:
package adapter;
import adapter.vendor.EUTowerHeater;
import adapter.vendor.NonUSHeatingDevice;
public class Starter {
public static void main(String[] args){
USHeatingDevice usHeatingDevice = null;
NonUSHeatingDevice euTowerHeater = null;
if(args[0].equals("US")){
usHeatingDevice = new TowerHeater();
}else if(args[0].equals("EU")){
euTowerHeater = new EUTowerHeater();
usHeatingDevice = new HeaterAdapter(euTowerHeater);
}
System.out.println(usHeatingDevice.voltage() + " V");
System.out.println(usHeatingDevice.frequency() + " Hz");
}
}
Notice the changes in the client from the original Starter.java; Pay attention to lines 19 and 20, we go through the adapter to instantiate a USHeatingDevice, which will behave as a non US heating device. As we can see on lines 24 and 25 The rest of the program is still working with the same interface as it was using before the vendor code was integrated into our application.
If we were to run this program with the EU command line argument we would get the result as follows:
230 V
50 Hz
Adapter Pattern as an abstraction layer
Another advantage of this pattern is that many implementations of the adaptee (vendor interface) could be added by the vendor and we would not have to touch a line of code in our HeaterAdapter.java thanks to Polymorphism.
Let’s say that the vendor add implementations of their non US heating device interface for countries such as Jamaica, Libya, and Colombia which have different electric power specification.
package adapter.vendor;
public class JamaicaTowerHeater implements NonUSHeatingDevice {
public int tension() {
return 110;
}
public int hertz() {
return 50;
}
}
The colombian implementation….
package adapter.vendor;
public class ColombianTowerHeater implements NonUSHeatingDevice {
public int tension() {
return 110;
}
public int hertz() {
return 60;
}
}
…and the Libya implementation
package adapter.vendor;
public class LibyaTowerHeater implements NonUSHeatingDevice {
public int tension() {
return 127;
}
public int hertz() {
return 50;
}
}
Let’s see the changes we have to make to the client, without touching the adapter at all.
package adapter;
import adapter.vendor.*;
public class Starter {
public static void main(String[] args) {
if (args.length > 0) {
USHeatingDevice usHeatingDevice = null;
if (args[0].equals("US")) {
usHeatingDevice = new TowerHeater();
} else if (args[0].equals("EU")) {
NonUSHeatingDevice euTowerHeater = new EUTowerHeater();
usHeatingDevice = new HeaterAdapter(euTowerHeater);
} else if (args[0].equals("JM")) {
NonUSHeatingDevice jamaicaTowerHeater = new JamaicaTowerHeater();
usHeatingDevice = new HeaterAdapter(jamaicaTowerHeater);
} else if (args[0].equals("CO")) {
NonUSHeatingDevice colombianTowerHeater = new ColombianTowerHeater();
usHeatingDevice = new HeaterAdapter(colombianTowerHeater);
} else if (args[0].equals("LY")) {
NonUSHeatingDevice libyaTowerHeater = new LibyaTowerHeater();
usHeatingDevice = new HeaterAdapter(libyaTowerHeater);
} else {
System.out.println("You must pass an apppropriate region parameter");
}
System.out.println(usHeatingDevice.voltage() + " V");
System.out.println(usHeatingDevice.frequency() + " Hz");
}
}
}
As you can see supporting new functionality is just as easy as adding the highlighted lines above.
The UML diagram below summarizes our example:
Adding flexibility to the Adapter Pattern
Thanks to Lariza Saenz a colleague from JavaHispano user group for pointing this out in the post comments. Let’s suppose that you are not interested in implementing all the methods of the interface. You could do it as follows:
1. Implement the method in the HeaterAdapter class and throw an UnsupportedOperationException.
2. or create an abstract class AbstractHeaterAdapter.
Let’s illustrate step #2. The AbstractHeaterAdapter class would look as follows:
package adapter;
public abstract class AbstractHeaterAdapter implements USHeatingDevice {
@Override
public int voltage() {
// TODO Auto-generated method stub
return 0;
}
@Override
public int frequency() {
// TODO Auto-generated method stub
return 0;
}
}
The implementation class would looks as follows:
package adapter;
public class Starter2 {
public static void main(String[] args) {
USHeatingDevice usHeatingDevice = new AbstractHeaterAdapter(){
public int voltage() {
return 125;
}
};
System.out.println(usHeatingDevice.voltage());
}
}
A real world example of this technique can be found in the java.awt.event package. Every listener interface (e.g MouseListener) has its correspondent adapter (MouseAdapter). The MouseAdapter is an abstract class that implements the MouseListener interface. So when you want to attached a mouseClicked event to a button you an either do it through a MouseListener or a MouseAdapter. If you do it trhough the MouseListener you will have to implement all the methods defined in the interface (mouseClicked, mousePressed, mouseReleased, mouseEntered). But what happens if you are only interested in one of the methods? Then you would use a MouseAdaper and provide the implementation for the method(s) that you are interested only similar to the example in Starter2.java above.
Bonus: Improving the client
Bladimir Rondon another colleague from the JavaHispano users group has suggested to use a ResourceBundle and reflection to clean up the if/else ugly code in Starter.java . The main advantage of using a resource bundle is as follows:
- You will be able to add implementations and not have to do any client code changes (except for the first time when you add support for the NonUSHeatingDevice).
- You will only have to make entries in the implementation.properties file for each new implementation.
The implementation.properties file will look as follows:
US=adapter.TowerHeater
EU=adapter.vendor.EUTowerHeater
CO=adapter.vendor.ColombianTowerHeater
JM=adapter.vendor.JamaicaTowerHeater
LY=adapter.vendor.LibyaTowerHeater
The Starter.java will look as follows:
package adapter;
import java.util.ResourceBundle;
import adapter.vendor.NonUSHeatingDevice;
public class Starter {
public static void main(String[] args) {
if (args.length > 0) {
ResourceBundle resBun = ResourceBundle.getBundle("implementations");
USHeatingDevice heatingDevice = null;
//If creation of a USHeatingDevice fails, then try to create a NonUSHeatingDevice
try {
heatingDevice = (USHeatingDevice) Class.forName(resBun.getString(args[0])).newInstance();
} catch (Exception e){
NonUSHeatingDevice foreignDevice = null;
try {
foreignDevice = (NonUSHeatingDevice) Class.forName(resBun.getString(args[0])).newInstance();
heatingDevice = new HeaterAdapter(foreignDevice);
} catch (Exception z){
System.out.println("Check your properties file");
}
}
System.out.println(heatingDevice.voltage() + " V");
System.out.println(heatingDevice.frequency() + " Hz");
} else {
System.out.println("You must pass an apppropriate region parameter");
}
}
}
Now you could put a Facade Pattern to hide all the ugly try/catch out the main class into an static method in another class to improve this further.
Conclusions
The adapter pattern can be used in the situations as follows:
- To match methods of a new interface that has similar behavior but different method names.
- To allow one and only one adapter to work with many different implementations of the Adaptee.
- To provide custom behavior for a desired method(s) of the interface without having to implement all methods of the contract.
It is also good for:
- Illustrating the power of Polimorphysm.
- Promoting the good OO technique of coding to interfaces.






