Just_another_developer
Just_another_developer

Reputation: 5977

Design Patterns: Factory vs Factory method vs Abstract Factory

I was reading design patterns from a website

There I read about Factory, Factory method and Abstract factory but they are so confusing, am not clear on the definition. According to definitions

Factory - Creates objects without exposing the instantiation logic to the client and Refers to the newly created object through a common interface. Is a simplified version of Factory Method

Factory Method - Defines an interface for creating objects, but let subclasses to decide which class to instantiate and Refers to the newly created object through a common interface.

Abstract Factory - Offers the interface for creating a family of related objects, without explicitly specifying their classes.

I also looked the other stackoverflow threads regarding Abstract Factory vs Factory Method but the UML diagrams drawn there make my understanding even worse.

Can anyone please tell me

  1. How are these three patterns different from each other?
  2. When to use which?
  3. And also if possible, any java examples related to these patterns?

Upvotes: 269

Views: 141683

Answers (9)

Ravindra babu
Ravindra babu

Reputation: 38950

Q1. How are these three patterns different from each other?

Definition from Wikipedia/Gang of Four ( Design Patterns: Elements of Reusable Object-Oriented Software book)

Factory: Creates objects without exposing the instantiation logic to the client.

Factory Method: Define an interface for creating an object, but let subclasses decide which class to instantiate. The Factory method lets a class defer instantiation it uses to subclasses." (Gang Of Four)

Abstract Factory: Provides an interface for creating families of related objects without specifying their concrete classes.

AbstractFactory pattern uses composition to delegate responsibility of creating object to another class

Factory method design pattern uses inheritance and uses derived class for creation of objects

Q2. When to use which?

Factory: Client just need a class and don't bother about implementer

Factory Method: Client doesn't know what concrete classes it will be required to create the object

AbstactFactory: When your system has to create multiple families of products without exposing the implementation details.

Abstract Factory classes are often implemented with Factory Method.

Q3. And also if possible, any java examples related to these patterns?

Problem statement: Create a Factory of Games by using Factory Methods, which defines the game interface.

Code snippet:

import java.util.HashMap;


/* Product interface as per UML diagram */
interface Game{
    /* createGame is a complex method, which executes a sequence of game steps */
    public void createGame();
}

/* ConcreteProduct implementation as per UML diagram */
class Chess implements Game{
    public Chess(){
        
    }
    public void createGame(){
        System.out.println("---------------------------------------");
        System.out.println("Create Chess game");
        System.out.println("Opponents:2");
        System.out.println("Define 64 blocks");
        System.out.println("Place 16 pieces for White opponent");
        System.out.println("Place 16 pieces for Black opponent");
        System.out.println("Start Chess game");
        System.out.println("---------------------------------------");
    }
}
class Checkers implements Game{
    public Checkers(){
       
    }
    public void createGame(){
        System.out.println("---------------------------------------");
        System.out.println("Create Checkers game");
        System.out.println("Opponents:2 or 3 or 4 or 6");
        System.out.println("For each opponent, place 10 coins");
        System.out.println("Start Checkers game");
        System.out.println("---------------------------------------");
    }
}
class Ludo implements Game{
    public Ludo(){
        
    }
    public void createGame(){
        System.out.println("---------------------------------------");
        System.out.println("Create Ludo game");
        System.out.println("Opponents:2 or 3 or 4");
        System.out.println("For each opponent, place 4 coins");
        System.out.println("Create two dices with numbers from 1-6");
        System.out.println("Start Ludo game");
        System.out.println("---------------------------------------");
    }
}

/* Creator interface as per UML diagram */
interface IGameFactory {
    public Game getGame(String gameName);
}

/* ConcreteCreator implementation as per UML diagram */
class GameFactory implements IGameFactory {
        
     HashMap<String,Game> games = new HashMap<String,Game>();
    /*  
        Since Game Creation is complex process, we don't want to create game using new operator every time.
        Instead we create Game only once and store it in Factory. When client request a specific game, 
        Game object is returned from Factory instead of creating new Game on the fly, which is time consuming
    */
    
    public GameFactory(){
        
        games.put(Chess.class.getName(),new Chess());
        games.put(Checkers.class.getName(),new Checkers());
        games.put(Ludo.class.getName(),new Ludo());        
    }
    public Game getGame(String gameName){
        return games.get(gameName);
    }
}

public class NonStaticFactoryDemo{
    public static void main(String args[]){
        if ( args.length < 1){
            System.out.println("Usage: java FactoryDemo gameName");
            return;
        }
     
        GameFactory factory = new GameFactory();
        Game game = factory.getGame(args[0]);
        if ( game != null ){                    
            game.createGame();
            System.out.println("Game="+game.getClass().getName());
        }else{
            System.out.println(args[0]+  " Game does not exists in factory");
        }           
    }
}

output:

java NonStaticFactoryDemo Chess
---------------------------------------
Create Chess game
Opponents:2
Define 64 blocks
Place 16 pieces for White opponent
Place 16 pieces for Black opponent
Start Chess game
---------------------------------------
Game=Chess

This example shows a Factory class by implementing a FactoryMethod.

  1. Game is the interface for all type of games. It defines complex method: createGame()

  2. Chess, Ludo, Checkers are different variants of games, which provide implementation to createGame()

  3. public Game getGame(String gameName) is FactoryMethod in IGameFactory class

  4. GameFactory pre-creates different type of games in constructor. It implements IGameFactory factory method.

  5. game Name is passed as command line argument to NotStaticFactoryDemo

  6. getGame in GameFactory accepts a game name and returns corresponding Game object.

Upvotes: 32

user2138149
user2138149

Reputation: 17416

None of the answers really explain the Abstract Factory particularly well - probably because the concept is abstract and this is less frequently used in practice.

An easy to understand example arrises from considering the following situation.

You have a system, which interfaces with another system. I will use the example given in Design Patterns Explained by Shalloway and Trott, P194, because this situation is so rare I can't think of a better one. In their book, they give the example of having different combinations of local hardware resources. They use, as examples:

  • System with high resoltion display and print driver
  • System with low resolution display and print driver

There are 2 options for one variable thing (print driver, display driver), and 2 options for the other variable thing (high resolution, low resolution). We want to couple these together in such a way that we have a HighResolutionFactory and a LowResolutionFactory which produce for us both a print driver and display driver of the correct type.

This then is the Abstract Factory pattern:

class ResourceFactory
{
    virtual AbstractPrintDriver getPrintDriver() = 0;

    virtual AbstractDisplayDriver getDisplayDriver() = 0;
};

class LowResFactory : public ResourceFactory
{
    AbstractPrintDriver getPrintDriver() override
    {
        return LowResPrintDriver;
    }

    AbstractDisplayDriver getDisplayDriver() override
    {
        return LowResDisplayDriver;
    }
};

class HighResFactory : public ResourceFactory
{
    AbstractPrintDriver getPrintDriver() override
    {
        return HighResPrintDriver;
    }

    AbstractDisplayDriver getDisplayDriver() override
    {
        return HighResDisplayDriver;
    }
};

I won't detail both the print driver and display driver hierachies, just one will suffice to demonstrate.

class AbstractDisplayDriver
{
    virtual void draw() = 0;
};

class HighResDisplayDriver : public AbstractDisplayDriver
{
    void draw() override
    {
        // do hardware accelerated high res drawing
    }
};

class LowResDisplayDriver : public AbstractDisplayDriver
{
    void draw() override
    {
        // do software drawing, low resolution
    }
};

Why it works:

We could have solved this problem with a bunch of if statements:

const resource_type = LOW_RESOLUTION;

if(resource_type == LOW_RESOLUTION)
{
    drawLowResolution();
    printLowResolution();
}
else if(resource_type == HIGH_RESOLUTION)
{
    drawHighResolution();
    printHighResolution();
}

Instead of this we now can do:

    auto factory = HighResFactory;
    auto printDriver = factory.getPrintDriver();
    printDriver.print();
    auto displayDriver = factory.getDisplayDriver();
    displayDriver.draw();

Essentially - We have abstracted away the runtime logic into the v-table for our classes.

My opinion on this pattern is that it isn't actually very useful. It couples together some things which need not be coupled together. The point of design patterns is usally to reduce coupling, not increase it, therefore in some ways this pattern is really an anti-pattern, but it might be useful in some contexts.

If you get to a stage where you are seriously considering implementing this, you might consider some alternative designs. Perhaps you could write a factory which returns factories, which themselves return the objects you eventually want. I imagine this would be more flexible, and would not have the same coupling issues.

Addendum: The example from Gang of Four is similarly coupled. They have a MotifFactory and a PMFactory. These then produce PMWindow, PMScrollBar and MotifWindow, MotifScrollBar respectively. This is a somewhat dated text now and so it might be hard to understand the context. I recall reading this chapter and the I understood little from the example beyond having two implementations of a factory base class which return different families of objects.

Upvotes: 1

Ravi K
Ravi K

Reputation: 1016

Factory - Separate Factory class to create complex object.

Ex: FruitFactory class to create object of Fruit

class FruitFactory{

public static Fruit getFruit(){...}

}

Factory Method - Instead of whole separate class for factory, just add one method in that class itself as a factory.

Ex:

Calendar.getInstance() (Java's Calendar)

Abstract Factory - Factory of Factories

Ex: Lets say we want to build factory for computer parts. So there are several types of computers like Laptop, Desktop, Server.

So for each compter type we need factory. So we create one highlevel factory of factories like below

ComputerTypeAbstractFactory.getComputerPartFactory(String computerType) ---> This will return PartFactory which can be one of these ServerPartFactory, LaptopPartFactory, DesktopPartFactory.

Now these 3 itself are again factories. (You will be dealing with PartFactory itself, but under the hood, there will be separate implementation based on what you provided in abstract factory)

  Interface-> PartFactory. getComputerPart(String s), 
Implementations -> ServerPartFactory, LaptopPartFactory, DesktopPartFactory.

Usage:
new ComputerTypeAbstractFactory().getFactory(“Laptop”).getComputerPart(“RAM”)

EDIT: edited to provide exact interfaces for Abstract Factory as per the objections in comments.

Upvotes: 22

Anders Johansen
Anders Johansen

Reputation: 10475

All three Factory types do the same thing: They are a "smart constructor".

Let's say you want to be able to create two kinds of Fruit: Apple and Orange.

Factory

Factory is "fixed", in that you have just one implementation with no subclassing. In this case, you will have a class like this:
class FruitFactory {

  public Apple makeApple() {
    // Code for creating an Apple here.
  }

  public Orange makeOrange() {
    // Code for creating an orange here.
  }

}

Use case: Constructing an Apple or an Orange is a bit too complex to handle in the constructor for either.

Factory Method

Factory method is generally used when you have some generic processing in a class, but want to vary which kind of fruit you actually use. So:
abstract class FruitPicker {

  protected abstract Fruit makeFruit();

  public void pickFruit() {
    private final Fruit f = makeFruit(); // The fruit we will work on..
    <bla bla bla>
  }
}

...then you can reuse the common functionality in FruitPicker.pickFruit() by implementing a factory method in subclasses:

class OrangePicker extends FruitPicker {

  @Override
  protected Fruit makeFruit() {
    return new Orange();
  }
}

Abstract Factory

Abstract factory is normally used for things like dependency injection/strategy, when you want to be able to create a whole family of objects that need to be of "the same kind", and have some common base classes. Here's a vaguely fruit-related example. The use case here is that we want to make sure that we don't accidentally use an OrangePicker on an Apple. As long as we get our Fruit and Picker from the same factory, they will match.
interface PlantFactory {
  
  Plant makePlant();

  Picker makePicker(); 

}

public class AppleFactory implements PlantFactory {
  Plant makePlant() {
    return new Apple();
  }

  Picker makePicker() {
    return new ApplePicker();
  }
}

public class OrangeFactory implements PlantFactory {
  Plant makePlant() {
    return new Orange();
  }

  Picker makePicker() {
    return new OrangePicker();
  }
}

Upvotes: 384

Siddharth
Siddharth

Reputation: 9584

Every design pattern strives to help ensure that written, working code is not touched. We all know that once we touch working code, there are defects in existing working flows, and a lot more testing needs to get done to ensure that we did not break anything.

A factory pattern creates objects based on input criteria, thus ensuring that you dont need to write code like:

 if (this) {
     create this kind of object 
 } else { 
     that kind of object 
 }

A good example of this is a travel website. A travel website can only provide travel (flight, train, bus) or / and provide hotels or / and provide tourist attraction packages. Now, when a user selects next, the website needs to decide what objects it needs to create. Should it only create the travel or hotel object too.

Now, if you envision adding another website to your portfolio, and you believe that the same core be used, for example, a carpooling website, which now searches for cab's and makes payments online, you can use a abstract factory at your core. This way you can just snap in one more factory of cabs and carpools.

Both factories have nothing to do with each other, so it's a good design to keep them in different factories.

Hope this is clear now. Study the website again keeping this example in mind, hopefully it will help. And I really hope I have represented the patterns correctly :).

Upvotes: 12

Hamed Naeemaei
Hamed Naeemaei

Reputation: 9756

Based this images from Design Patterns in C#, 2nd Edition by Vaskaran Sarcar book:

1. Simple Factory Pattern

Creates objects without exposing the instantiation logic to the client.

SimpleFactory simpleFactory = new SimpleFactory();
IAnimal dog = simpleFactory.CreateDog(); // Create dog
IAnimal tiger = simpleFactory.CreateTiger(); // Create tiger

enter image description here

2. Factory Method Pattern

Defines an interface for creating objects, but let subclasses to decide which class to instantiate.

AnimalFactory dogFactory = new DogFactory(); 
IAnimal dog = dogFactory.CreateAnimal(); // Create dog

AnimalFactory tigerFactory = new TigerFactory();
IAnimal tiger = tigerFactory.CreateAnimal(); // Create tiger

enter image description here

3. Abstract Factory pattern (factory of factories)

Abstract Factory offers the interface for creating a family of related objects, without explicitly specifying their classes

IAnimalFactory petAnimalFactory = FactoryProvider.GetAnimalFactory("pet");
IDog dog = petAnimalFactory.GetDog(); // Create pet dog
ITiger tiger = petAnimalFactory.GetTiger();  // Create pet tiger

IAnimalFactory wildAnimalFactory = FactoryProvider.GetAnimalFactory("wild");
IDog dog = wildAnimalFactory .GetDog(); // Create wild dog
ITiger tiger = wildAnimalFactory .GetTiger();  // Create wild tiger

enter image description here

Upvotes: 68

G&#233;ry Ogam
G&#233;ry Ogam

Reputation: 8107

Nobody has quoted the original book Design Patterns: Elements of Reusable Object-Oriented Software, which gives the answer in the first two paragraphs of the section “Discussion of Creational Patterns” (emphasis mine):

There are two common ways to parameterize a system by the classes of objects it creates. One way is to subclass the class that creates the objects; this corresponds to using the Factory Method (107) pattern. The main drawback of this approach is that it can require a new subclass just to change the class of the product. Such changes can cascade. For example, when the product creator is itself created by a factory method, then you have to override its creator as well.

The other way to parameterize a system relies more on object composition: Define an object that’s responsible for knowing the class of the product objects, and make it a parameter of the system. This is a key aspect of the Abstract Factory (87), Builder (97), and Prototype (117) patterns. All three involve creating a new “factory object” whose responsibility is to create product objects. Abstract Factory has the factory object producing objects of several classes. Builder has the factory object building a complex product incrementally using a correspondingly complex protocol. Prototype has the factory object building a product by copying a prototype object. In this case, the factory object and the prototype are the same object, because the prototype is responsible for returning the product.

Upvotes: 2

Pavel Sapehin
Pavel Sapehin

Reputation: 1078

For this answer, I refer to the "Gang of Four" book.

There are no "Factory" nor "Simple Factory" nor "Virtual Factory" definitions in the book. Usually when people are talking about "Factory" pattern they may be talking about something that creates a particular object of a class (but not the "builder" pattern); they may or may not refer to the "Factory Method" or "Abstract Factory" patterns. Anyone can implement "Factory" as he won't because it's not a formal term (bear in mind that some people\companies\communities can have their own vocabulary).

The book only contains definitions for "Abstract Factory" and "Factory Method".

Here are definitions from the book and a short explanation of why both can be so confusing. I omit code examples because you can find them in other answers:

Factory Method (GOF): Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.

Abstract Factory (GOF): Provide an interface for creating families of related or dependent objects without specifying their concrete classes.

Source of Confusion: Often, one can call a class that used in "Factory Method" pattern as "Factory". This class is abstract by definition. That's why it easy to call this class "Abstract Factory". But it's just the name of the class; you shouldn't confuse it with "Abstract Factory" pattern (class name != pattern name). The "Abstract Factory" pattern is different - it does not use an abstract class; it defines an interface (not necessarily a programming language interface) for creating parts of a bigger object or objects that are related to each other or must be created in a particular way.

Upvotes: 15

rameshvanka
rameshvanka

Reputation: 49

AbstractProductA, A1 and A2 both implementing the AbstractProductA
AbstractProductB, B1 and B2 both implementing the AbstractProductB

interface Factory {
    AbstractProductA getProductA(); //Factory Method - generate A1/A2
}

Using Factory Method, user can able to create A1 or A2 of AbstractProductA.

interface AbstractFactory {
    AbstractProductA getProductA(); //Factory Method
    AbstractProductB getProductB(); //Factory Method
}

But Abstract Factory having more than 1 factory method ( ex: 2 factory methods), using those factory methods it will create the set of objects/ related objects. Using Abstract Factory, user can able to create A1, B1 objects of AbstractProductA, AbstractProductB

Upvotes: 1

Related Questions