Skip to main content

Design Pattern: Factory Method Vs Abstract Factory


What is the difference between Factory Method and Abstract Factory, and when to use which?

First, remember they both belong to Creational Patten, which aims to provide proper way in dealing with object creation.

Then, let's talk about the difference and relationship between them.


Factory Method is a special case of Template Method Pattern, in which base class defines the algorithm skeleton and defers some of the steps involved in the generic algorithm to subclass.  An example of this is how to create a customized view in Android - your create subclass of View and override the onDraw(), which is a Template Method.

public class View() {
     void draw(){
          drawBackground();
          onDraw(canvas);
          drawOthers();
     }
     abstract void onDraw();
 }
public class MyView extends View {
     void onDraw(Canvas canvas) {
          canvas.drawRect(...)
     }
}

In comparison, Factory Method, defers the creation of its aggregated object to subclass - or we can say defer its own instantiation to subclass. In following example, MazeGame depends on its subclass to create Room object and instantiate itself. Factory Method is also called Virtual Constructor, in the sense that base class relies subclass to construct properly.

public class MazeGame {
     public MazeGame() {
        Room room1 = makeRoom();
        Room room2 = makeRoom();
        room1.connect(room2);
        this.addRoom(room1);
        this.addRoom(room2);
}
    abstract protected Room makeRoom();
}

public class MagicMazeGame extends MazeGame {
   @Override
protected Room makeRoom() {return new MagicRoom()};
}

Abstract Factory.  Its definition is "Provide an interface for creating families of related or dependent objects without specifying their concrete classes". Compared with Factory Method, the main difference is Abstract Factory is used to create multiply types of object.

Let's see an example. Car, which is a client, uses the PartFactory to create various parts needed by a Car. There can be different implementation of PartFactory and Client does not care.

   public class Car{
    public Car(PartFactory  partFactory) {       
        mWheel = partFactory->makeWheel();
        Window = partFactory->makeWindow();
        Engine = partFactory->makeEngine();
    }
 }
  public interface PartFactory {
    Room makeWheel();
    Door makeWindow();
    Engine makeEngine();
  }
 public FortPartFacotry implements PartFactory {
   Wheel makeWheel()   {return FordWheel()}
   Window makeWindow() {return FordWindow()};
   Engine makeEngine() {return FordEngine()};
  }
  // to create a Car
  new Car(new FortPartFacotry() )

However, it is OK to still use Factory Method, even we have multiply object to create.  

 public class Car{
    public Car() {
        mWheel = makeWheel();
        Window = makeWindow();
        Engine = makeEngine();
    }
    abstract protected Wheel  makeWheel();
    abstract protected Window makeWindow();
    abstract protected Engine makeEngine();
 }

 public class FordCar extends Car{
   protected Wheel makeWheel()   {return FordWheel()}
   protected Window makeWindow() {return FordWindow()};
   protected Engine makeEngine() {return FordEngine()};
 }

Which is better? Not obvious in this specific case. In the Abstract Factory Patten, all the creation methods are extract in a separate interface. And the composition is used instead of inheritance, which is believed to be a good thing. 

Similar, when there is only one object to create, you are not prohibited from using Abstract Factory  Back to Maze example, 

public class MazeGame {
    public MazeGame(RoomFactory roomFactory) {
        Room room1 = roomFactory.makeRoom();
        Room room2 = roomFactory.makeRoom();
        room1.connect(room2);
        this.addRoom(room1);
        this.addRoom(room2);
    }
 }
public interface RoomFactory {
    Room makeRoom();
}
public class MagicRoomFactory implements RoomFactory {
    @Override
    Room makeRoom() { return new MagicRoom();}
}
new MazeGame(new MagicRoomFactory())

So the real distinction between “Abstract Factory” and “Factory Method” is not the number of the object need to be created but the former uses both composition (b/w client and Factory) and inheritance (b/w abstract Factory and concrete Factory) while the later uses only inheritance.

What is the conclusion then? Well, no actual one. However, once you comprehend what we talked here, you should be able to make informed decision between those two. 

Comments

Popular posts from this blog

Understand Container - Index Page

This is an index page to a series of 8 articles on container implementation. OCI Specification Linux Namespaces Linux Cgroup Linux Capability Mount and Jail User and Root Network and Hook Network and CNI
Update:
This page has a very good page view after being created. Then I was thinking if anyone would be interested in a more polished, extended, and easier to read version.
So I started a book called "understand container". Let me know if you will be interested in the work by subscribing here and I'll send the first draft version which will include all the 8 articles here. The free subscription will end at 31th, Oct, 2018.

* Remember to click "Share email with author (optional)", so that I can send the book to your email directly. 

Cheers,


Android Camera2 API Explained

Compared with the old camera API, the Camera2 API introduced in the L is a lot more complex: more than ten classes are involved, calls (almost always) are asynchronized, plus lots of capture controls and meta data that you feel confused about.

Understand Container: OCI Specification

OCI is the industry collaborated effort to define an open containers specifications regarding container format and runtime - that is the official tone and is true. The history of how it comes to where it stands today from the initial disagreement is a very interesting story or case study regarding open source business model and competition.

But past is past, nowadays, OCI is non-argumentable THE container standard, IMO, as we'll see later in the article it is adopted by most of the mainstream container implementation, including docker, and container orchestration system, such as kubernetes, Plus, it is particularly helpful to anyone trying to understand how the containers works internally. Open source code are awesome but it is double awesome with high quality documentation!