Click here to Skip to main content
Click here to Skip to main content
Go to top

Factory Method Pattern vs. Abstract Factory Pattern

, 28 Jan 2014
Rate this:
Please Sign up or sign in to vote.
In this article we will learn difference between Factory Method Pattern and Abstract Factory Pattern.

Introduction

Design patterns are reusable and documented solutions for commonly occurring problems in software programming or development.

In one of my previous article about Factory Pattern I spoke about what are different flavors of Factory pattern and how to choose between them. But I think there are some confusion with regards to Factory Method Pattern and Abstract Factory. So we will work on it.

Who should read this article?

If you have confusion understanding the difference between Factory Method Pattern and Abstract Factory Pattern you are at right place.

What these two are? 

  • First of all both of them falls under Creational category and it means it will solves the problem pertaining to object creation.
  • Factory Method and abstract factory pattern all are about creating objects.

In this article I would like to emphasize on one more terminology that is Simple Factory.

1. Simple Factory and Factory Method

For our discussion let’s have a small problem statement.

Class structure

public interface ICustomer 
{        
    void AddPoints();
    void AddDiscount();
}

public class GoldCustomer : ICustomer
{
    public void AddPoints()
    {
        Console.WriteLine("Gold Customer - Points Added");
    }

    public void AddDiscount()
    {
        Console.WriteLine("Gold Customer - Discount Added");
    }

    public void GoldOperation()
    {
        Console.WriteLine("Operation specific to Gold Customer");
    }
}

public class SilverCustomer : ICustomer
{
    public void AddPoints()
    {
        Console.WriteLine("Silver Customer -  Points Added");
    }

    public void AddDiscount()
    {
        Console.WriteLine("Silver Customer - Discount Added");
    }

    public void SilverOperation()
    {
        Console.WriteLine("Operation specific to Silver Customer");
    }
}

Problem Statement

Client want to create Customer Object (either Gold or Silverbased on requirement).

Simple Factory

This is one of the pattern not born from GOF and most of the peopleconsiders this as the default Factory method pattern.

Here, we will just take out object creation process out of the client code and put into some other class. Look at the code demonstration.

class CustomerFactory
{
    public static ICustomer GetCustomer(int i)
    {       
        switch (i)
        {
            case 1:
                GoldCustomer goldCustomer = new GoldCustomer();
                goldCustomer.GoldOperation();
                goldCustomer.AddPoints();
                goldCustomer.AddDiscount();
                return goldCustomer;               
            case 2:
                SilverCustomer silverCustomer = new SilverCustomer();
                silverCustomer.SilverOperation();
                silverCustomer.AddPoints();
                silverCustomer.AddDiscount();
                return silverCustomer;
            default: return null;
        }      
    }
}

//Client Code
ICustomer c = CustomerFactory.GetCustomer(someIntegerValue);

Factory Method Pattern

In this pattern we define an interface which will expose a method which will create objects for us. Return type of that method is never be a concrete type rather it will be some interface (or may be an abstract class)

public abstract class BaseCustomerFactory
{
    public ICustomer GetCustomer()
    {
        ICustomer myCust = this.CreateCustomer();
        myCust.AddPoints();
        myCust.AddDiscount();
        return myCust;
    }
    public abstract ICustomer CreateCustomer();
}

public class GoldCustomerFactory : BaseCustomerFactory
{
    public override ICustomer CreateCustomer()
    {
        GoldCustomer objCust = new GoldCustomer();
        objCust.GoldOperation();
        return objCust;
    }
}
public class SilverCustomerFactory : BaseCustomerFactory
{
    public override ICustomer CreateCustomer()
    {
        SilverCustomer objCust = new SilverCustomer();
        objCust.SilverOperation();
        return objCust;
    }
}
//Client Code
BaseCustomerFactory c = new GoldCustomerFactory();// Or new SilverCustomerFactory();
ICustomer objCust = c.GetCustomer();

Note:- To understand when to use Simple Factory and when to use Factory Method Pattern click here.

2. Abstract Factory Pattern

In Abstract Factory we define an interface which will create families of related or dependent objects. In simple words, interface will expose multiple methods each of which will create some object. Again, here method return types will be generic interfaces. All this objects will together become the part of some important functionality.

Question – If every factory is going to create multiple objects and all those objects will be related to each other (means they will use each other) how this relating happens and who does that?

Answer –
  • There will be an intermediary class which will have composition relationship with our interface.
  • This class will do all the work, using all the objects got from interface methods.
  • This will be the class with which client will interact.

Let’s talk about a scenario.
We want to build desktop machine. Let see what will be the best design for that,

public interface IProcessor 
{
    void PerformOperation();
}
public interface IHardDisk { void StoreData(); }
public interface IMonitor { void DisplayPicture();}

public class ExpensiveProcessor : IProcessor
{
    public void PerformOperation()
    {
        Console.WriteLine("Operation will perform quickly");
    }
}
public class CheapProcessor : IProcessor
{
    public void PerformOperation()
    {
        Console.WriteLine("Operation will perform Slowly");
    }
}

public class ExpensiveHDD : IHardDisk
{
    public void StoreData()
    {
        Console.WriteLine("Data will take less time to store");
    }
}
public class CheapHDD : IHardDisk
{
    public void StoreData()
    {
        Console.WriteLine("Data will take more time to store");
    }
}

public class HighResolutionMonitor : IMonitor
{
    public void DisplayPicture()
    {
        Console.WriteLine("Picture quality is Best");
    }
}
public class LowResolutionMonitor : IMonitor
{
    public void DisplayPicture()
    {
        Console.WriteLine("Picture quality is Average");
    }
}
Factory Code will be as follows
public interface IMachineFactory
{
    IProcessor GetRam();
    IHardDisk GetHardDisk();
    IMonitor GetMonitor();
}

public class HighBudgetMachine : IMachineFactory
{
    public IProcessor GetRam() { return new ExpensiveProcessor(); }
    public IHardDisk GetHardDisk() { return new ExpensiveHDD(); }
    public IMonitor GetMonitor() { return new HighResolutionMonitor(); }
}
public class LowBudgetMachine : IMachineFactory
{
    public IProcessor GetRam() { return new CheapProcessor(); }
    public IHardDisk GetHardDisk() { return new CheapHDD(); }
    public IMonitor GetMonitor() { return new LowResolutionMonitor(); }
}
//Let's say in future...Ram in the LowBudgetMachine is decided to upgrade then
//first make GetRam in LowBudgetMachine Virtual and create new class as follows

public class AverageBudgetMachine : LowBudgetMachine
{
    public override IProcessor GetRam()
    {
        return new ExpensiveProcessor();
    }
}
public class ComputerShop
{
    IMachineFactory category;
    public ComputerShop(IMachineFactory _category)
    {
        category = _category;
    }
    public void AssembleMachine()
    {
        IProcessor processor = category.GetRam();
        IHardDisk hdd = category.GetHardDisk();
        IMonitor monitor = category.GetMonitor();
        //use all three and create machine

        processor.PerformOperation();
        hdd.StoreData();
        monitor.DisplayPicture();
    }
}
//Client Code
IMachineFactory factory = new HighBudgetMachine();// Or new LowBudgetMachine();
ComputerShop shop = new ComputerShop(factory);
shop.AssembleMachine();   

Conclusion

I think now you know what is the difference between Factory Method Pattern and Abstract Factory

Hope all of you enjoyed reading this article. Thank you for the patience.

For technical training related to various topics including ASP.NET, Design Patterns, WCF and MVC contact SukeshMarla@Gmail.com or at www.sukesh-marla.com

For more stuff like this click here. Subscribe to article updates or follow at twitter @SukeshMarla 

 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Marla Sukesh
Technical Lead ShawMan Softwares
India India
Learning is fun but teaching is awesome.
 
Code re-usability is my passion ,Teaching and learning is my hobby, Becoming an successful entrepreneur is my goal.
 

For technical trainings on various topics like WCF, MVC, Business Intelligence, Design Patterns, WPF and UML and many more feel free to contact SukeshMarla@Gmail.com or visit www.justcompile.com or www.sukesh-marla.com

 
http://www.sukesh-marla.com/
https://twitter.com/SukeshMarla
https://www.facebook.com/pages/Blogs-By-Sukesh-Marla/168078149903213?ref=stream
Follow on   Twitter   Google+   LinkedIn

Comments and Discussions

 
GeneralMy vote of 5 PinmemberHumayun Kabir Mamun10-Jul-14 1:02 
QuestionNice PinmemberMember 451897618-Jun-14 2:39 
AnswerRe: Nice PinprofessionalMarla Sukesh18-Jun-14 3:46 
QuestionAbstract Factory Pattern Pinmembersasson2418-Mar-14 3:07 
GeneralMy vote of 5 PinprofessionalMihai MOGA14-Feb-14 17:04 
GeneralRe: My vote of 5 PinprofessionalMarla Sukesh20-Feb-14 20:30 
GeneralMy vote of 5 Pinmembermanoj.jsm13-Feb-14 22:06 
GeneralRe: My vote of 5 PinprofessionalMarla Sukesh20-Feb-14 20:30 
GeneralMy vote of 5 PinmemberThatsAlok10-Feb-14 1:50 
GeneralRe: My vote of 5 PinprofessionalMarla Sukesh20-Feb-14 20:30 
QuestionAbstract Factory PinmemberMember 1036688729-Jan-14 19:57 
GeneralVery well explained sukesh PinmemberAkshay S Patel28-Jan-14 23:34 
GeneralRe: Very well explained sukesh PinprofessionalMarla Sukesh29-Jan-14 21:46 
GeneralMy vote of 5 PinmemberChingis Meirman28-Jan-14 5:49 
GeneralRe: My vote of 5 PinprofessionalMarla Sukesh28-Jan-14 6:38 
GeneralMy vote of 3 PinmemberHenning Dieterichs28-Jan-14 2:05 
GeneralRe: My vote of 3 PinprofessionalMarla Sukesh28-Jan-14 5:30 
GeneralRe: My vote of 3 PinmemberSergeyAB30-Jan-14 17:31 
GeneralRe: My vote of 3 PinmemberHenning Dieterichs31-Jan-14 6:39 
QuestionDid u ever tried to compile your code?, or u have just copied this from some other place PinmemberAhmedkapasi27-Jan-14 19:32 
AnswerRe: Did u ever tried to compile your code?, or u have just copied this from some other place PinprofessionalMarla Sukesh27-Jan-14 19:39 
GeneralRe: Did u ever tried to compile your code?, or u have just copied this from some other place PinmemberAhmedkapasi27-Jan-14 19:52 
GeneralRe: Did u ever tried to compile your code?, or u have just copied this from some other place PinprofessionalMarla Sukesh27-Jan-14 22:57 
GeneralRe: Did u ever tried to compile your code?, or u have just copied this from some other place PinprofessionalMarla Sukesh28-Jan-14 5:31 
GeneralMy vote of 5 PinprofessionalSandeep Singh Shekhawat27-Jan-14 17:41 
GeneralMy vote of 3 PinprofessionalPaulo Zemek27-Jan-14 9:01 
QuestionSome problems... PinprofessionalPaulo Zemek27-Jan-14 8:59 
You did a great work explaining the Factory Method pattern and even explaining the wrong use of it, when there's nothing virtual, only a separate method to work as the factory.
 
Yet on the real cases I see some problems:
In the Factory Method Pattern your factory exposes both GetCustomer and CreateCustomer as public. Honestly, I think that users will more naturally call the CreateCustomer method, as this is the one that seems to indicate creation. Such method should be hidden or, even better, only one public abstract method should exist. Why is the GetCustomer() doing those two doSomethingX() calls?
 
And on the Abstract Factory Pattern, you start by "For above problem statement we cannot use Abstract Factory Pattern as solution."
To which problem we can't use it?
 
And your example is a problematic one. You apparently love to use real world examples that don't fit. The GetRam, GetHardDisk and GetMonitor aren't methods that need to exist as a family. They are simply 3 different factories put inside one multi-reponsibility factory. The big example is that your 2 implementations return a new LgMonitor();
 
The abstract factory pattern is useful when the family members have a notion of family. For example, we can have a factory of UI controls. The light theme may create all kinds of control, as long as they fit the light theme. The dark theme, well, it is the same, as long as they are dark. We don't expect to mix controls from a light theme and dark theme together.
 
I can't say the same about HardDisks and RAM and Monitors. As long as it is possible to connect them (and in this case we should see the computer's connections), I can use harddisks from any company with ram from any company and monitors from any company. This is the kind of situation that should avoid inheritance or a class for each combination. Each construction should be isolated.
 
So, using a more real example, the IDbConnection, IDbCommand etc already work as factories, yet we have the DbFactory type, which is capable of creating the connections, commands, parameters etc. It will not try to create SqlConnections and OracleCommands. It is either an entire Oracle family or an entire Sql Server family. And this is the purpose of the abstract factory pattern.
AnswerRe: Some problems... PinprofessionalMarla Sukesh27-Jan-14 15:55 
GeneralMy vote of 3 PinmemberQuentin in SA27-Jan-14 0:04 
GeneralRe: My vote of 3 PinprofessionalMarla Sukesh27-Jan-14 1:04 
QuestionVery nice and selfexplaining article PinmemberAbhijeet_020326-Jan-14 23:50 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140922.1 | Last Updated 28 Jan 2014
Article Copyright 2014 by Marla Sukesh
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid