Showing posts with label Abstract Factory. Show all posts
Showing posts with label Abstract Factory. Show all posts

Sunday, 29 September 2013

Abstract Factory Design Pattern - KeyPoints

Master Java Design Patterns!

Subscribe to Ram N Java for in-depth software architecture tutorials, design pattern breakdowns, and clean code guides!

SUBSCRIBE NOW

What is the Abstract Factory Pattern?

The Abstract Factory Design Pattern is a creational design pattern often referred to as a "Factory of Factories". It provides an interface for creating families of related or dependent objects without specifying their concrete classes.

Instead of creating objects directly using concrete constructors, client code requests objects from an abstract factory interface, ensuring that related objects (such as UI buttons and scrollbars for a specific OS) are always created together consistently.

Essential Key Points to Remember

  • Family of Products: Abstract Factory focuses on creating entire families of related products rather than single individual instances.
  • Loose Coupling: The client program is completely decoupled from concrete implementation classes. It interacts solely through abstract interfaces.
  • Open/Closed Principle: You can introduce new variants of product families into your application without breaking existing client code.
  • Single Responsibility Principle: The object creation logic is centralized in dedicated factory classes, simplifying maintenance and testing.
  • Consistency Across Products: Guarantees that products created within the same family are compatible with each other.

When Should You Use It?

The Abstract Factory pattern is ideal when:

  • A system must be independent of how its products are created, composed, and represented.
  • A system needs to be configured with one of multiple families of products (e.g., cross-platform UI themes, multi-cloud storage adapters).
  • A family of related product objects is designed to be used together, and you need to enforce this constraint at runtime.

Watch More Related Design Pattern Tutorials


Click here to watch in Youtube : https://www.youtube.com/watch?v=oQflDHmSACg

Click the below Image to Enlarge























See also:

  • Abstract Factory Design Pattern - Introduction
  • Abstract Factory Design Pattern - Implementation
  • All Design Patterns Links
  • Abstract Factory Design Pattern - Implementation

    Level Up Your Java Skills!

    Subscribe to Ram N Java for hands-on programming guides, real-world architecture patterns, and clean code examples!

    SUBSCRIBE NOW

    Understanding the Architecture

    The Abstract Factory Pattern acts as a "super-factory" or "factory of factories." In this practical implementation, we organize related objects into concrete families based on their environment:

    • Land Animal Family: Produces land animals such as Dog, Cat, and Lion.
    • Sea Animal Family: Produces aquatic animals such as Shark and Octopus.
    • Abstract Animal Factory: The super factory that delegates the creation of the correct concrete factory based on input.

    Complete Java Code Implementation

    Here is the complete source code demonstrating the interfaces, concrete implementations, factory classes, and client execution:

    // 1. Common Product Interface
    interface Animal {
        String speak();
    }
    
    // Concrete Products: Land Animals
    class Dog implements Animal {
        @Override
        public String speak() { return "Bark Bark"; }
    }
    
    class Cat implements Animal {
        @Override
        public String speak() { return "Meow Meow"; }
    }
    
    class Lion implements Animal {
        @Override
        public String speak() { return "Roar"; }
    }
    
    // Concrete Products: Sea Animals
    class Shark implements Animal {
        @Override
        public String speak() { return "Cannot Speak"; }
    }
    
    class Octopus implements Animal {
        @Override
        public String speak() { return "Squawk"; }
    }
    
    // 2. Abstract Factory (Super Factory)
    abstract class AnimalFactory {
        public abstract Animal getAnimal(String animalType);
    
        public static AnimalFactory getAnimalFactory(String factoryType) {
            if ("SEA".equalsIgnoreCase(factoryType)) {
                return new SeaAnimalFactory();
            } else if ("LAND".equalsIgnoreCase(factoryType)) {
                return new LandAnimalFactory();
            }
            return null;
        }
    }
    
    // 3. Concrete Factories
    class LandAnimalFactory extends AnimalFactory {
        @Override
        public Animal getAnimal(String animalType) {
            if ("DOG".equalsIgnoreCase(animalType)) {
                return new Dog();
            } else if ("CAT".equalsIgnoreCase(animalType)) {
                return new Cat();
            } else if ("LION".equalsIgnoreCase(animalType)) {
                return new Lion();
            }
            return null;
        }
    }
    
    class SeaAnimalFactory extends AnimalFactory {
        @Override
        public Animal getAnimal(String animalType) {
            if ("SHARK".equalsIgnoreCase(animalType)) {
                return new Shark();
            } else if ("OCTOPUS".equalsIgnoreCase(animalType)) {
                return new Octopus();
            }
            return null;
        }
    }
    
    // 4. Client / Driver Application
    public class AbstractFactoryPatternDemo {
        public static void main(String[] args) {
            // Fetch Sea Animal Factory
            AnimalFactory seaFactory = AnimalFactory.getAnimalFactory("SEA");
            Animal shark = seaFactory.getAnimal("SHARK");
            System.out.println("Shark says: " + shark.speak());
    
            Animal octopus = seaFactory.getAnimal("OCTOPUS");
            System.out.println("Octopus says: " + octopus.speak());
    
            // Fetch Land Animal Factory
            AnimalFactory landFactory = AnimalFactory.getAnimalFactory("LAND");
            Animal dog = landFactory.getAnimal("DOG");
            System.out.println("Dog says: " + dog.speak());
    
            Animal cat = landFactory.getAnimal("CAT");
            System.out.println("Cat says: " + cat.speak());
    
            Animal lion = landFactory.getAnimal("LION");
            System.out.println("Lion says: " + lion.speak());
        }
    }

    Key Takeaways for Developers

    • Encapsulation: The client application never calls the concrete class constructor directly using new.
    • Extensibility: To add a new environment (e.g., SkyAnimalFactory with Bird), simply create the classes and register them in the super-factory without modifying existing product hierarchies.
    • Consistency: Ensures that related products stay within their defined family domain.

    Watch More Related Design Pattern Tutorials


    Click here to watch in Youtube : https://www.youtube.com/watch?v=Bbjh8atQJz0

    Click the below Image to Enlarge
    Abstract Factory Design Pattern - Implementation - Class Diagram























    Animal.java

    public interface Animal
    {
    public String speak();
    }


    Cat.java

    public class Cat implements Animal
    {

    @Override
    public String speak()
    {
    return "Meow Meow Meow";
    }

    }


    Dog.java

    public class Dog implements Animal
    {

    @Override
    public String speak()
    {
    return "Bark Bark Bark";
    }

    }


    Lion.java

    public class Lion implements Animal
    {

    @Override
    public String speak()
    {
    return "Roar";
    }

    }


    Octopus.java

    public class Octopus implements Animal
    {
    @Override
    public String speak()
    {
    return "SQUAWCK";
    }
    }


    Shark.java

    public class Shark implements Animal
    {
    @Override
    public String speak()
    {
    return "Cannot Speak";
    }
    }


    AnimalFactory.java

    public abstract class AnimalFactory
    {
    public abstract Animal getAnimal( String animalType );
    public static AnimalFactory getAnimalFacory(String factoryType)
    {
    AnimalFactory animalFactory = null ;
    if("sea".equals(factoryType))
    {
    animalFactory = new SeaAnimalFactory();
    }
    else
    {
    animalFactory = new LandAnimalFactory();
    }
    return animalFactory;
    }

    }


    LandAnimalFactory.java

    public class LandAnimalFactory extends AnimalFactory
    {
    public Animal getAnimal( String animalType )
    {
    Animal animal = null;
    if( "dog".equals(animalType) )
    {
    animal = new Dog();
    }
    else if( "cat".equals(animalType) )
    {
    animal = new Cat();
    }
    else if( "lion".equals(animalType) )
    {
    animal = new Lion();
    }
    return animal;
    }
    }


    SeaAnimalFactory.java

    public class SeaAnimalFactory extends AnimalFactory
    {
    public Animal getAnimal( String animalType )
    {
    Animal animal = null;
    if( "shark".equals(animalType) )
    {
    animal = new Shark();
    }
    else if( "octopus".equals(animalType) )
    {
    animal = new Octopus();
    }
    return animal;
    }
    }


    Client.java

    public class Client
    {

    public static void main( String[] args )
    {
    Animal animal = null;
    AnimalFactory animalFactory = null;
    String speakSound = null;

    // Get Factory object by passing the factory type
    animalFactory = AnimalFactory.getAnimalFacory("sea");

    System.out.println("Animal Factory type : " + animalFactory.getClass().getName());
    System.out.println();

    // Get Animal object by passing the animal type
    animal = animalFactory.getAnimal("shark");
    System.out.println("Animal Type : "+animal.getClass().getName());
    speakSound = animal.speak();
    System.out.println("shark speak : "+speakSound);
    System.out.println();

    animal = animalFactory.getAnimal("octopus");
    System.out.println("Animal Type : "+animal.getClass().getName());
    speakSound = animal.speak();
    System.out.println("octopus speak : "+speakSound);

    System.out.println("---------------------------------------------------------");
    // Get Factory by passing the factory type
    animalFactory = AnimalFactory.getAnimalFacory("land");

    System.out.println("Animal Factory type : " + animalFactory.getClass().getName());
    System.out.println();

    // Get Animal object by passing the animal type
    animal = animalFactory.getAnimal("dog");
    System.out.println("Animal Type : "+animal.getClass().getName());
    speakSound = animal.speak();
    System.out.println("dog speak : "+speakSound);
    System.out.println();

    animal = animalFactory.getAnimal("cat");
    System.out.println("Animal Type : "+animal.getClass().getName());
    speakSound = animal.speak();
    System.out.println("cat speak : "+speakSound);

    System.out.println();
    animal = animalFactory.getAnimal("lion");
    System.out.println("Animal Type : "+animal.getClass().getName());
    speakSound = animal.speak();
    System.out.println("lion speak : "+speakSound);

    }
    }


    Output

    Animal Factory type : SeaAnimalFactory

    Animal Type : Shark
    shark speak : Cannot Speak

    Animal Type : Octopus
    octopus speak : SQUAWCK
    ---------------------------------------------------------
    Animal Factory type : LandAnimalFactory

    Animal Type : Dog
    dog speak : Bark Bark Bark

    Animal Type : Cat
    cat speak : Meow Meow Meow

    Animal Type : Lion
    lion speak : Roar

    Abstract Factory Design Pattern - Introduction

    Master Object-Oriented Design!

    Subscribe to Ram N Java for clear explanations, practical software patterns, and beginner-friendly programming lessons!

    SUBSCRIBE NOW

    What is the Abstract Factory Pattern?

    The Abstract Factory Pattern belongs to the Creational Design Pattern family. At its simplest, it is defined as a "Super Factory" or a "Factory of Factories" because it creates and returns other factories.

    When your application needs to produce multiple distinct families of related products without hardcoding the exact concrete classes into the client code, the Abstract Factory pattern provides the perfect abstraction layer.

    Real-World Analogy: Animal Ecosystem

    To understand how this hierarchy functions conceptually, consider dividing animals into two distinct habitats:

    • Land Animals Family: Animals like Dog, Cat, and Lion share land-based behavior and characteristics.
    • Sea Animals Family: Aquatic animals like Shark and Octopus have aquatic life cycles and navigation.
    • Abstract Animal Factory: The master factory that determines whether to supply a LandAnimalFactory or a SeaAnimalFactory based on the client's request.

    Core Benefits of Abstract Factory

    • Isolates Concrete Classes: Client code only knows about the product interfaces, shielding your business logic from implementation changes.
    • Promotes Consistency: Enforces that products created from a single factory family are designed to work harmoniously together.
    • Adheres to Open/Closed Principle: Adding a brand-new factory family (such as AirAnimalFactory) requires no invasive modifications to the existing client execution code.

    Watch More Related Design Pattern Tutorials


    Click here to watch in Youtube : https://www.youtube.com/watch?v=cvqyJvVjxj4

    Click the below Image to Enlarge
    Abstract Factory Design Pattern - Introduction
























    See also:

  • Abstract Factory Design Pattern - Implementation
  • Abstract Factory Design Pattern - key Points
  • All Design Patterns Links
  • Tutorials