Java Abstract Factory Design Pattern Example
1. Introduction
In this article, we will depict Java Abstract Factory Design Pattern in detail. The Abstract configuration design, as its name proposes, is by all accounts an abstract class based method to allow creation of object factories with a template class that guides the development. Abstract Factory design pattern is specifically useful to build a class that explains how the underlying factory classes should work. The abstract factory pattern defines a specific set of methods that the object provider factories need to implement. This structure design in Java is a kind of Creational design pattern example and it is utilized to make objects, like the Factory configuration design, which is likewise a Creational configuration pattern. In straightforward words, Abstract factory design pattern is a creational configuration design it implies its takes care of the issue identified with formation of question.
In java, Constructors are utilized to make question and can utilize the expected parameters to make objects. Issue starts at whatever point a question can likewise be made with numerous parameters, some of which might be obligatory and others discretionary. For comprehension, consider a class used to make Juice, we currently require various things, for example, water, natural product, blender, ice, straw to make Juice. Most are necessary yet some of them are discretionary, for example, ice, straw, and so on. Be that as it may, on the off chance that we have over-burden constructor for various sort of juice, there would be more than one constructor and even most exceedingly awful they will acknowledge a great deal of parameter. Abstract factor design pattern improves coherence as well as lessens the danger of blunder by unequivocally adding flavors and attempting to make the question open once it has been completely made.
In java, Constructors are utilized to make question and can utilize the expected parameters to make objects. Issue starts at whatever point a question can likewise be made with numerous parameters, some of which might be obligatory and others discretionary. For comprehension, consider a class used to make Juice, we currently require various things, for example, water, natural product, blender, ice, straw to make Juice. Most are necessary yet some of them are discretionary, for example, ice, straw, and so on. Be that as it may, on the off chance that we have over-burden constructor for various sort of juice, there would be more than one constructor and even most exceedingly awful they will acknowledge a great deal of parameter. Abstract factor design pattern improves coherence as well as lessens the danger of blunder by unequivocally adding flavors and attempting to make the question open once it has been completely made.
2. Java Design Patterns
There are numerous design patterns defined in Java to serve the purpose of an organized development. Below are a bunch of major pattern explained for your understanding. As we proceed in the article, we will understand the Java Abstract Factory design in detail with example.
2.1 Creational Pattern
In object creation, creational design patterns takes place. They render the creation process much more efficient and creative. Creative patterns in particular can deliver a wide range of choices as to which objects are produced, how all these objects are produced and how they are initialised. This pattern can sometimes be labelled into either class and even object creation patterns. Although class-creation patterns effectively use inheritance in the installation process, where object-creation patterns effectively use high – level delegation to get all the job done properly. The creational design patterns are also split into six different design pattern types
2.2 Structural Pattern
Structural pattern design characterises seven different types of design patterns. Structural design patterns are design patterns which optimise design by identifying a quick and easy way of conveying relationships between the objects. Such design patterns focus heavily upon how classes and objects could be linked to form larger frameworks. The structural design patterns try to simplify or promote the structure by understanding the difference between the structural elements.
2.3 Behavioural Pattern
These design patterns actually relate to the class-to-object communication. Behavioural design patterns are some patterns which affect communication between objects most specifically. This pattern characterises eleven different pattern classifications for interaction among objects. These design patterns are being used to deal with object algorithms, relationships and responsibilities.
In this article we will explore one of the commonly used Creational design pattern–the Abstract Factory design pattern. This article describes the idea of the Abstract factory design pattern with a real – life example to give you a complete understanding of how well the Abstract factory design pattern allows software developers to provide a better object creation technique. The following section develops this pattern to analyse every portion of the Abstract Factory design pattern. Furthermore, we will implement the Abstract Factory design pattern into Java program.
3. Abstract Factory Design Pattern – Real Life Example
Before we get into the technicalities of the Abstract Factory Design Pattern, let us try and understand the application of the pattern in real life. This will help you imagine and visualize as to how this pattern makes the object creation streamlined.
The above image cleverly examples how the object creation task is delegated via an abstract layer class at the factory level. Here, the chief chef is the abstract layer between the actual chefs and the menu for items. There are a bunch of items that can be ordered – which is similar to a bunch of objects that can be created. Once the implementing or application class needs a relevant object, it will always create an object of the Abstract Class and initialize it with the respective class. In this manner, maintaining a type strict list of objects in a generic collection becomes simpler. In addition to that, the methods being exposed by every class underneath the abstract layer will have a similar signature.
This reduces the reason for worry for the developer of the application. In this manner, this abstract class basically plays the role of abstract the underlying classes and forcing them to provide methods as per the abstract factory class that they extend. This helps in systematic creation of objects and henceforth better memory management.
In the above flow, ordering of an item depicts the creation of object, the chef plays the role of an abstract factory class and the outsourced chefs are the depiction of actual object factories. These factories create the objects as per the guidelines set by the abstract factory – The chef in the picture and deliver the output or the created object to the end user – the application.
4. Abstract Factory Design Pattern – Example
Now that we have an understanding of how the abstract factory design pattern works, let us get our hands dirty with the code. We will try to map the above real world scenario into code now. As you must have understood, the Head chef in the above image is the abstract factory class for us. The outsourcing chefs are the ones who actually provide the factories for object creation.
The underlying object factories will all extend the abstract object factory. These object factories will in turn create objects. Hence, let us begin our code by creating the abstract object class and the sub classes for the objects before these factories.
AbstractFood.java
package com.javacodegeeks.abk; public abstract class AbstractFood { public abstract String getItemName(); public abstract boolean isDelivered(); public abstract int getQuantity(); }
The above abstract factory class provides two different methods that the inheriting factory classes will implement. Let us now create three different factory classes that will take the order and create relevant objects.
ItalianFood.java
package com.javacodegeeks.abk; public class ItalianFood extends AbstractFood { String itemName; int quantity; boolean delivered; public String getItemName() { return itemName; } public void setItemName(String itemName) { this.itemName = itemName; } public int getQuantity() { return quantity; } public void setQuantity(int quantity) { this.quantity = quantity; } public boolean isDelivered() { return delivered; } public void setDelivered(boolean delivered) { this.delivered = delivered; } }
ChineseFood.java
package com.javacodegeeks.abk; public class ChineseFood extends AbstractFood { String itemName; int quantity; boolean delivered; public String getItemName() { return itemName; } public void setItemName(String itemName) { this.itemName = itemName; } public int getQuantity() { return quantity; } public void setQuantity(int quantity) { this.quantity = quantity; } public boolean isDelivered() { return delivered; } public void setDelivered(boolean delivered) { this.delivered = delivered; } }
MexicanFood.java
package com.javacodegeeks.abk; public class MexicanFood extends AbstractFood { String itemName; int quantity; boolean delivered; public String getItemName() { return itemName; } public void setItemName(String itemName) { this.itemName = itemName; } public int getQuantity() { return quantity; } public void setQuantity(int quantity) { this.quantity = quantity; } public boolean isDelivered() { return delivered; } public void setDelivered(boolean delivered) { this.delivered = delivered; } }
The above three classes are the sub classes that will be used for creation of Food objects. Now, each of these classes will have a factory class to provide the objects. This is as per the Factory design pattern. The factory classes will be as shown below.
AbstractFoodFactory.java
package com.javacodegeeks.abk; public abstract class AbstractFoodFactory { public abstract AbstractFoodFactory placeOrder(String itemName, int quantity) ; }
ItalianFoodFactory.java
package com.javacodegeeks.abk; public class ItalianFoodFactory extends AbstractFoodFactory { @Override public AbstractFood placeOrder(String itemName, int quantity) { return new ItalianFood(itemName,quantity); } }
ChineseFoodFactory.java
package com.javacodegeeks.abk; public class ChineseFoodFactory extends AbstractFoodFactory { @Override public AbstractFood placeOrder(String itemName, int quantity) { return new ChineseFood(itemName,quantity); } }
MexicanFoodFactory.java
package com.javacodegeeks.abk; public class MexicanFoodFactory extends AbstractFoodFactory { @Override public AbstractFood placeOrder(String itemName, int quantity) { return new MexicanFood(itemName,quantity); } }
As it can be seen, the AbstractFoodFactory
class sits at the top of the other factories and provides a common layer of factory for the consumer class that will be created. The consumer class will define a method that will take any underlying object factory as input. This factory object will in turn return the respective object. The consumer class example is shown below.
ConsumerClass.java
package com.javacodegeeks.abk; public class ConsumerClass { public AbstractFood placeOrder(String itemName,int quantity,String itemType) { AbstractFoodFactory a = null; if(itemType.equals("italian")) { a = new ItalianFoodFactory(); }else if(itemType.equals("mexican")) { a = new MexicanFoodFactory(); }else if(itemType.equals("chinese")) { a = new ItalianFoodFactory(); } if(a!=null) { return a.placeOrder(itemName, quantity); }else { return null; } } }
This consumer class finally takes care of the creation of object as needed. This consumer class acts as the main chef or the person who takes the order and delegates to the respective chefs(the factory class herein). Below is the UML diagram of how these classes have been connected.
Further, we create an application class that will utilise this consumer class and work on it. The application class will practically place an order containing different cuisines thereby ordering objects of different classes created above. The application class is as shown below.
MenuApplication.java
package com.javacodegeeks.abk; import java.util.ArrayList; public class MenuApplication { ArrayList order; public static void main(String[] args) { MenuApplication m = new MenuApplication(); m.createOrder(); } public boolean createOrder() { boolean orderCreated = false; ConsumerClass c = new ConsumerClass(); order = new ArrayList(); order.add(c.placeOrder("Lazagne", 2, "italian")); order.add(c.placeOrder("Taco", 3, "mexican")); order.add(c.placeOrder("Noodles", 1, "chinese")); System.out.println(order); return orderCreated; } }
The above code create an order of three different food items. The order content is then printed to make sure that the factory has generated the objects using the right factory. The output of the above code is as shown below:
[com.javacodegeeks.abk.ItalianFood@33909752, com.javacodegeeks.abk.MexicanFood@55f96302, com.javacodegeeks.abk.ItalianFood@3d4eac69]
As it can be seen, one object of each object class is created by using the same class object and same function. In this manner, an abstract layer can be used for the process of creating objects of underlying classes. This helps is restricting the exposure of object creation process and simplifies the object creation job for the developer. Such a design pattern can be largely used in scenarios like a restaurant, a production unit, snacks unit and others.
5. Benefits of using Abstract Factory Design Pattern
The abstract factory design pattern has been primarily created to tackle the problem of different signatures for initialization of each object type. The benefits of using this design pattern include but are not limited to the ones listed below.
- Uniform object creation methods
- Uniformity in object management
- Reduced exposure of underlying base code
- Abstraction of the object creation methodology
- Easier development process due to abstraction at object creation layer
Despite the above benefits, just like the other design patterns, there are occasions where using the Abstract Factory Design pattern does not really make sense. These scenarios have been listed below.
6. Drawbacks of Abstract Factory Design pattern
Abstract Factory design pattern should be carefully used in situations listed below.
- Do not use it when the underlying object factories are not logically connected
- Do not use it when the underlying object factories are meant to serve objects with different purpose
- Do not use it in scenarios where the object factory has widely varying attributes
In addition to the above scenarios, the abstract factory design pattern can also lead to increase in complexity of objects as there will be multiple abstract methods to implement while the sub classes implement only selected methods in the pattern. In such scenarios, it becomes difficult to utilize Abstract Factory design pattern.
7. Conclusion
The Abstract factory design pattern is useful in scenarios where there are a number of object classes of similar nature. These classes require an abstract layer to simplify the creation of objects. Abstract factory design pattern specifically focuses on creation of this abstract layer of class. This article discussed and explained how an abstract factory design pattern is implemented in a real world scenario.
Thank you very much for sharing this, but I wish the example code could have more clarity (The Consumer Class seems to have a mistake and return types in each foodfactories are not being able to be casted, and I am a newby and am confused), or it would be helpful if the source code is shared..
please change the return type of this method.
public abstract AbstractFoodFactory placeOrder(String itemName, int quantity) ;