Abstract factory 

Introduction: The final goal of the abstract factory pattern is to provide an interface for creating families of related or dependent objects without specifying their concrete classes. This pattern allows the creation of objects to be independent of the main system, promoting loose coupling and enhancing the flexibility to change the system’s behavior by switching between different families of objects.

Elements of Abstract Factory Pattern:

  1. Abstract Product:

    • This represents the interface for a family of related products. It declares the methods that the concrete products must implement.
  2. Concrete Product:

    • These are the various implementations of the abstract products. Each concrete product corresponds to a specific variation or family of related products.
  3. Abstract Factory:

    • This declares an interface for creating the abstract products. It provides a method for each type of product the factory can produce.
  4. Concrete Factory:

    • These are the implementations of the abstract factory interface. Each concrete factory is responsible for creating a family of related products.

Suppose we have a system that needs to create and work with different types of products, such as electronic products and clothing products.

    • In the system, we use the abstract factory pattern to achieve the goal of creating families of products without specifying their concrete classes.
    • The abstract product interface defines the methods that the concrete products must implement, ensuring that all products within a family adhere to a common interface.
    • The concrete products represent specific implementations of the abstract products, such as ElectronicsProduct and ClothingProduct, each belonging to a specific family of products.
    • The abstract factory interface declares methods for creating the abstract products. Each concrete factory provides the implementation for creating a family of related products, maintaining consistency and encapsulating the product creation process.
    • By utilizing the concrete factories, the system can create families of products without being tightly coupled to their specific implementations, thus achieving the goal of flexibility and interchangeability.

Result:

    • As a result of using the abstract factory pattern, the system achieves loose coupling between the client and the products, allowing for easy interchangeability of product families.

Here’s an example implementation of the Abstract Factory pattern in Java:

// Abstract Product

public abstract class Product {

    public abstract void display();

}

// Concrete Electronics Product

public class ElectronicsProduct extends Product {

    @Override

    public void display() {

        System.out.println(“This is an electronics product.”);

    }

}

// Concrete Clothing Product

public class ClothingProduct extends Product {

    @Override

    public void display() {

        System.out.println(“This is a clothing product.”);

    }

}

// Abstract Factory

public abstract class ProductFactory {

    public abstract Product createProduct();

}

// Electronics Product Factory

public class ElectronicsProductFactory extends ProductFactory {

    @Override

    public Product createProduct() {

        return new ElectronicsProduct();

    }

}

// Clothing Product Factory

public class ClothingProductFactory extends ProductFactory {

    @Override

    public Product createProduct() {

        return new ClothingProduct();

    }

}

// Client Code

public class Client {

    private ProductFactory factory;

    public Client(ProductFactory factory) {

        this.factory = factory;

    }

    public void displayProduct() {

        Product product = factory.createProduct();

        product.display();

    }

}

// Usage

public class Program {

    public static void main(String[] args) {

        ProductFactory electronicsFactory = new ElectronicsProductFactory();

        Client electronicsClient = new Client(electronicsFactory);

        electronicsClient.displayProduct();


//Notice the same process here but with different argument and result

        ProductFactory clothingFactory = new ClothingProductFactory();

        Client clothingClient = new Client(clothingFactory);

        clothingClient.displayProduct();

    }

}

 

And here’s an equivalent example in Python:

# Abstract Product

class Product:

    def display(self):

        pass

# Concrete Electronics Product

class ElectronicsProduct(Product):

    def display(self):

        print(“This is an electronics product.”)

# Concrete Clothing Product

class ClothingProduct(Product):

    def display(self):

        print(“This is a clothing product.”)

# Abstract Factory

class ProductFactory:

    def create_product(self):

        pass

# Electronics Product Factory

class ElectronicsProductFactory(ProductFactory):

    def create_product(self):

        return ElectronicsProduct()

# Clothing Product Factory

class ClothingProductFactory(ProductFactory):

    def create_product(self):

        return ClothingProduct()

# Client code

class Client:

    def __init__(self, factory):

        self._factory = factory

    def display_product(self):

        product = self._factory.create_product()

        product.display()

# Usage

if __name__ == “__main__”:

    electronics_factory = ElectronicsProductFactory()

    electronics_client = Client(electronics_factory)

    electronics_client.display_product()

    clothing_factory = ClothingProductFactory()

    clothing_client = Client(clothing_factory)

    clothing_client.display_product()

 

In both examples, we have an abstract product class (`Product`) and its concrete implementations (`ElectronicsProduct` and `ClothingProduct`). We also have an abstract factory class (`ProductFactory`) and its concrete implementations (`ElectronicsProductFactory` and `ClothingProductFactory`). The client code (`Client`) uses the factory to create the product objects (different in type) and display their information by using the same client code.

Using the Abstract Factory pattern, we can easily add new product categories and their corresponding factories without modifying the client code. This flexibility allows us to extend the application’s functionality in different environment and support new business requirements without introducing breaking changes.

Leave a Reply

Your email address will not be published. Required fields are marked *