The factory pattern can help solve your application issues. For example, developers often must reply to users based on each user’s machine, creating multiple hardware issues. The factory pattern can streamline the process. The concept is simple, but the solutions created with the factory pattern are powerful.
Factory patterns return possible classes in response to requests
The factory pattern often appears in object-oriented designs. It’s an object that can return one of several possible classes in response to a request. The request data is used to determine which one of the possible classes to return. In Java, the class returned should be either the implementation of an interface or the concrete implementation of an abstract class so the calling application can manipulate the returned object. In Figure A, you can see a UML diagram of a simple factory pattern.
|Simple factory pattern UML|
The problem: Communications breakdown
Consider the example of a data collection application where various field devices supply data to the application via TCP/IP sockets. The application was originally written to communicate with one device but was expanded when the company produced a newer version. Unfortunately, this new hardware did not speak the same language as the previous version. Marketing required the application to support both hardware versions, since customers might buy new units and install them in tandem with older units. The factory pattern eased the burden of supporting multiple device types.
Handle versions with the factory pattern
Create an abstract class named DataConnection—an interface will work as well. This allows the application to speak to both versions of the hardware. It’s used to define the signature for different versions of the connection objects. Create a specific connection object for each hardware version that communicates differently with the application. In the example in Figure A, two objects have been defined and named Version1Connection and Version2Connection (see Listing A for sample code). Each concrete class implements the interface defined by the DataConnection object, so program code can manipulate these connections by operating against the interface. Of course, the implementations in Listing A only give enough code to illustrate this concept.
The actual factory pattern is realized in the class named ConnectionFactory. ConnectionFactory returns an object implementing the DataConnection interface when it is provided with the incoming connection IP address. In this case, the ConnectionFactory class looks up the IP address in a database, or by some other means, to determine which version of hardware is requesting communication. Based upon the version of the hardware, the ConnectionFactory returns the appropriate object to the calling code. Listing B shows the actual code for the factory.
Notice the getConnection method has been declared as static. In this particular factory, there’s no benefit to creating an instance of the factory, so the method can be called within the code by referring to the ConnectionFactory class directly. In some designs, it might help to instantiate the factory class so it can retain a cache mechanism for locating information used to determine which class to create.
Since a real factory class is unlikely to implement a simple “if” statement, there are many options to consider for determining the appropriate class. For instance, the IP address in this example could be used to query a database that would return the appropriate version of the hardware at that IP address. Of course, this requires fixed IP addresses for the hardware. Another way to create the appropriate class is to store the actual class name in the database and use the forName and newInstance methods of the Java Class object to instantiate the appropriate class.
You’ve collected the data. Now what?
The factory pattern does an excellent job of solving the multiple hardware issue in this example. Once a connection is established, you must deal with the collected data. In the current solution, each connection object handles the data collected from the connection. However, if you place the collected data into a common set of objects, the application code can deal with the data and leave only the physical connection and language details to the connection objects. This means using a parent class to represent the data collected from the hardware devices. In order for the application to manipulate the data objects, it needs to know how to instantiate the appropriate type of data object. Using the abstract factory pattern, the returned object supplies the appropriate connection and data objects to the application.
The details of the abstract factory pattern are beyond the scope of this article, but the quick explanation is “a factory that returns a group of objects or another factory.” If you’ve ever used the Java AWT classes, you’ve probably used the abstract factory pattern to establish which GUI the application uses for the Windows look and feel.
The factory pattern works for you
The factory pattern allows the application code to operate with a known parent class or interface while the underlying object handles the specifics. The application code can then use the most optimized object for the task at hand without needing to know the details of how that object is created.