35.7. Abstract Factory (GoF) for Families of Related Objects
The JavaPOS implementations will be purchased from manufacturers. For example[5] :
[5] These are fictitious package names.
Now, how to design the NextGen POS application to use the IBM Java drivers if IBM hardware is used, NCR drivers if appropriate, and so forth?Note that there are families of classes (CashDrawer +CoinDispenser +...) that need to be created, and each family implements the same interfaces.For this situation, a commonly used GoF pattern exists: Abstract Factory.
// IBM's drivers
com.ibm.pos.jpos.CashDrawer (implements jpos.CashDrawer)
com.ibm.pos.jpos.CoinDispenser (implements jpos.CoinDispenser)
...
// NCR's drivers
com.ncr.posdrivers.CashDrawer (implements jpos.CashDrawer)
com.ncr.posdrivers.CoinDispenser (implements jpos.CoinDispenser)
...
Abstract Factory Context/Problem How to create families of related classes that implement a common interface?Solution Define a factory interface (the abstract factory). Define a concrete factory class for each family of things to create. Optionally, define a true abstract class that implements the factory interface and provides common services to the concrete factories that extend it. |
Figure 35.15. A basic abstract factory.
[View full size image]
An Abstract Class Abstract Factory
A common variation on Abstract Factory is to create an abstract class factory that is accessed using the Singleton pattern, reads from a system property to decide which of its subclass factories to create, and then returns the appropriate subclass instance. This is used, for example, in the Java libraries with the java.awt.Toolkit class, which is an abstract class abstract factory for creating families of GUI widgets for different operating system and GUI subsystems.The advantage of this approach is that it solves this problem: How does the application know which abstract factory to use? IBMJavaPOSDevicesFactory ? NCRJavaPOSDevicesFactory ?The following refinement solves this problem. Figure 35.16 illustrates the solution.
Figure 35.16. An abstract class abstract factory.
[View full size image]
The expression JavaPOSDevicesFactory.getInstance() will return an instance of IBMJavaPOSDevicesFactory or NCRJavaPOSDevicesFactory, depending on the system property that is read in. Notice that by changing the external system property "jposfactory.classname" (which is the class name as a String) in a properties file, the NextGen system will use a different family of JavaPOS drivers. Protected Variations with respect to a changing factory has been achieved with a data-driven (reading a properties file) and reflective programming design, using the c.newInstance() expression.Interaction with the factory will occur in a Register . By the goal of low representational gap, it is reasonable for the software Register (whose name is suggestive of the overall POS terminal) to hold a reference to devices such as CashDrawer . For example:
cashDrawer = JavaPOSDevicesFactory.getInstance().getNewCashDrawer();
class Register
{
private jpos.CashDrawer cashDrawer;
private jpos.CoinDispenser coinDispenser;
public Register()
{
cashDrawer =
JavaPOSDevicesFactory.getInstance().getNewCashDrawer();
// ...
}
// ...
}