The next simpler pattern is the Abstract Factory Pattern. This pattern gives one level of abstraction above the Factory pattern. In the Factory pattern we saw the factory class returns a concrete object. In Abstract Factory Pattern, the abstract factory class returns factories which in turn returns concrete objects for use. The following image might give you the real idea behind this cool pattern.
Click on the image to enlarge it for a clear view
If you see the above picture, the Investment is the abstract factory. It gives us any of the three factories Stocks/Bonds/Mutual Funds based on some condition. Those factories in turn gives us concrete objects. (The objects from Bonds are left out in the picture because there is no space to draw them, and moreover I couldn't remember any good Bond names apart from James Bond)The following code gives you a simple implementation of the above representation.
InvestmentFactory.java - The Abstract factory class.
public class InvestmentFactory
{
public Investment getInvestment(String risk)
{
if(risk.equals("HIGH"))
{
return new StockFundFactory();
}
else if(risk.equals("LOW"))
{
return new MutualFundFactory();
}
else
{
return new BondFactory();
}
}
}
StockFactory.java - A factory class returned by the abstract factory.
public class StockFactory extends Investment
{
public IUnit getUnit(String type)
{
IUnit stock = null;
if(type.equals("LARGE"))
{
stock = new LargeCompanyStock();
}
else if(type.equals("SMALL"))
{
stock = new SmallCompanyStock();
}
else
{
stock = new MidCompanyStock();
}
return stock;
}
}
MutualFundFactory.java - Another factory class.
public class MutualFundFactory extends Investment
{
public IUnit getUnit(String type)
{
IUnit fund= null;
if(type.equals("LARGE"))
{
fund = new LargeCapFund();
}
else if(type.equals("SMALL"))
{
fund = new SmallCapFund();
}
else
{
fund = MidCapFund();
}
return bond;
}
}
In the caller method we can use the following code snippet to get the desired object we need:
InvestmentFactory af = new InvestmentFactory();
Investment inv = af.getInvestment("HIGH");
IUnit unit = inv.getUnit("LARGE");
System.out.println(unit.totalAmount());
In these examples, the parameter which determines the object returned are Strings. I have used this for simplicity. At first this may seem confusing as it is more like the user is determining the exact object returned. But if we imagine the deciding parameter like an object returned from statements like class.forName(...) of System.getProperty(..,..), things might become clear.IUnit unit = inv.getUnit("LARGE");
System.out.println(unit.totalAmount());
A more suitable example can be given using the Java swing UI. There is a method UIManager.getSystemLookAndFeelClassName() which will return the name of the class which specifies the underlying platform's UI class(It may be the UI class for Windows, Mac or Linux). This name can act as the parameter which decides the UI object returned by the abstract factory class. The UI object thus returned itself is a factory(objects of type com.sun.java.swing.plaf.windows.WindowsLookAndFeel or com.sun.java.swing.plaf.gtk.GTKLookAndFeel etc..) from which we can get concrete objects like buttons, check boxes, lists etc.. Hope you understand this example if the previous Investment example is not clear enough.
No comments:
Post a Comment