Abstract Factory Pattern in Java

What is Abstract Factory Pattern?

Abstract factory pattern is a creational design pattern. It adds another layer to the factory method pattern. This pattern includes a generic interface to create families of objects. This pattern is useful when a client object wants an object instance from a group of related or dependent classes without any knowledge of the objects creation process.

The GoF definition:

‘Provide an interface for creating families of related or dependent objects without specifying their concrete classes.’

The Abstract Factory Interface fulfills the abstraction for the scenario. Concrete factory classes implement the abstract factory interface. The client calls the abstract factory and specifies which concrete object it requires. The client doesn’t know how abstract factory creates the concrete object or internal implementations of each factory classes.

When to use Abstract Factory Pattern

  • there are number of products fall into families
  • the families of products need to stay together, but only one subset of families can be used at a particular time
  • the internal implementation is hidden and needs to expose via an interface
  • the client does not need internal implementations and details of object creations
  • the system needs more modularity and abstraction to separate the functionalitiesStandard Class Diagram

    Standard Class Diagram

    Abstract Factory pattern in Java
    Abstract Factory pattern in Java

    Abstract Factory Pattern Class Definitions

    • AbstractFactory: This is the super-class of all the factories in the pattern implementation. This provides a suitable interface to create a group of similar type of objects or family of products. This is the base for all the concrete factory classes and includes standard functionalities inherited by concrete factories. It contains the interfaces to create the final concrete objects
    • ConcreteFactory (X/Y): These classes inherit from AbstractFactory super-class and contains the concrete implementations to create different concrete products. Systems can have as many factories depending on the requirement. This concrete factory will provide the clients specific, concrete object.
    • AbstractProduct (A/B): These are the interfaces or abstract classes for the concrete products in the pattern. One base type exists for each concrete product class.
    • Product: This is the final concrete product class. This contains all the differentiation required by the client. This extends the AbstractProduct type. The system can have several products grouped by families.
    • Client: This is the system class, which calls the required functions. The client uses only the interfaces provides by the AbstractFactory and AbstractProduct classes to indicate the requirements

     Problem

    There are situations in systems where we need to gather same quality objects together. However, they will complicate the system if not managed properly. It’s difficult to instantiate and apply methods to concrete objects individually when there are families of related and dependent products. The application should be independent of its individual object creation. Most of the time complex and heavy classes should not worry about all of its related object creation procedures. Creating concrete inner objects directly will lead to inflexibility in the system. It prevents the independent behaviour for future modifications, stops the class from reusing, and make the testing difficult. In addition, it limits the code extensibility, which is essential in maintaining the group of products.

    Solution

    Abstract factory pattern provides a good modular solution for above problem. Dedicated factories handle each group of products. Factories are descending from the abstract factory super-class. This abstract factory encapsulates the concrete product creation process through the concrete factories. Abstract factory represents the highest-level abstraction in the scenario. Concrete factory classes gather the factory methods to create the concrete products. Normally, there will be a single instance of a concrete factory class at run-time

    Applicability of Abstract Factory Design Pattern

    When an application consists of related objects, that is several families of products and there are needs of using them together when required. In addition, it’s necessary that the client should not be aware of each concrete product creation. Therefore, objects reside encapsulated and are accessed via interfaces. Factories provide the support to manage the groups of similar products and construct the concrete objects.

    Example: Abstract Factory Pattern

    Let’s think about a cake shop. The cake shop sells cakes with various flavours and ingredients. Customers love to have different varieties of cakes with sophisticated toppings and decorations. Therefore, we will build a cake factory to make several different cakes.

    For the ease of reference, let us assume that the cake factory produces two main types of cakes: Chocolate Cake and Cheese Cake. The factory produces two variations for the cake as ‘Frosting’ and ‘No Bake’. ‘Frosting’ adds the desired frosting flavour for both chocolate cake and cheesecake while ‘No Bake’ provides the simple refrigerating options for both cake types. In this example, there is vanilla cream frosting for chocolate cakes and banana pudding frosting for cheesecakes. No bake option provides chocolate fudge cake and Philadelphia cheesecake for two types.

    Now we have to convert this to the programming world scenario. We can see several related families and dependencies in this scenario. It will be difficult for a client program to call each object type and construct inner objects individually. Therefore, it is best to apply abstract factory pattern for the example. So that the client does not need to worry about the exhausting object creation.

    We can identify classes and interfaces for the example as below:

    • AbstractCakeFactory: This is the abstract factory for the rest of the sub-factories. This base class provides interfaces to get concrete products using the concrete factories.
    • ChocolateCakeFactory / CheeseCakeFactory:

    These are the two sub-classes under the super AbstractCakeFactory class. These are named as factories because those produces several varieties of products based on different attributes. Hence, ChocolateCakeFactory and CheeseCakeFactory provide the factory methods to create specialized cakes for the cake shop.

    • IFrosting / INoBake Interfaces

    These are the abstract product representations of concrete products. Both factories can have products with these options.

    • VanillaCreamChocolateCake / BananaPuddingCheeseCake

    These are the frosting cake types from the cake factory, which implements the IFrosting interface. VanillaCreamChocolateCake is one of the concrete products from the ChocolateCakeFactory and BananaPuddingCheeseCake is one of the concrete products from the CheeseCakeFactory.

    • ChocolateFudgeCake / PhiladelphiaCheeseCake

    These are the concrete products from two factories which implements the INoBake interface.

     How to Implement Abstract Factory Pattern?

    1. Identify each related concrete products in the system and categorize them to follow a common interface.
    2. Create abstract interfaces for all distinct product types
    3. Make sure all concrete products implement each relevant abstract product type
    4. Create the base interface ‘AbstractFactory’ with methods to create product families. Methods should return abstract product types identified by interfaces and declared earlier
    5. Implement ‘ConcreteFactory’ classes. These will return the concrete products for declaring factory type. Concrete factories should implement the ‘AbstractFactory’ interface
    6. The client uses only the ‘AbstractFactory’ and the concrete factories to get the products.

Class Diagram for the Cake Factory Example

 

Abstract Factory pattern in Java
Abstract Factory example

Sequence Diagram

 

Abstract Factory pattern in Java
Abstract Factory pattern Sequence Diagram

Code Samples for Cake Factory Example

IFrosting.java

INoBakeCake.java

AbstractCakeFactory.java

ChocolateCakeFactory.java

CheeseCakeFactory.java

VanillaPuddingChocolateCake.java

ChocolateFudgeCake.java

BananaPuddingCheeseCake.java

PhiladelphiaCheeseCake.java

Clinet.java

Advantages

  • Enabled error-free management of families of related products
  • Concrete factories work independently of each other, enabling easy product family exchange and handling at run-time
  • Improves consistency among related products
  • Many objects can be added or changed dynamically during the run-time
  • Divides the responsibilities among multiple concrete factory classes
  • Can add more products to families and concrete factories will take care about those product creations
  • Enforce encapsulation and modularization through concrete factories and abstract interfaces
  • The client program is independent of the internal object construction mechanism
  • Abstract factory avoids long conditional logic as in factory pattern

Disadvantages

  • Additional classes increase the code complexity
  • Several layers of abstraction make the system heavy
  • It’s hard to add new families of products because it takes lots of effort to implement all interface methods in the existing system and incorporate new concrete products.

Difference between Factory Method and Abstract Factory

  • The main difference is that the factory method is a single method and an abstract factory is a separate java object
  • Factory method relies on inheritance since sub-classes overrides it and the abstract factory can only sub-types due to its abstractions and contain factory methods.
  • Abstract factory is a composition of several other factories which are responsible for creating their own concrete products

As discussed in the article, abstract factory pattern contains a base interface for creating products. Concrete factories do the heavy work and pattern helps to manage effectively a large quality of the similar object as product families.

 

Leave a Reply