Wednesday, December 18, 2013

Abstract Factory Pattern - Creational design pattern / Abstract Factory tutorial / Abstract Factory example

Abstract Factory Pattern

Its a creational design pattern.  It's extension to factory method. It creates more level of abstraction to factory (factory method) so called Abstract Factory Pattern. This factory is also called as Factory of factories. In this interface is for creating a factory of related objects, without explicitly specifying their classes. Each generated factory object will give the objects as per the Factory pattern.

Example:- We have online books stores which can choose different distributor based on location of the customer (this logic of selecting distributor is in GetDistributor, its a factor method).
We can extend this factory method pattern to the abstract factory pattern by:
  • Adding another product that the factories can produce. In this example, we will add Advertisers that help the bookstores advertise their stores online.
  • Each bookstore can then choose their own distributors and advertisers inside their own GetDistributorand GetAdvertiser method.
ie Here BookStore is factory and advertiser and distributor also factory. (Nesting of factory)


Source: Code Project



 called Abstract factory as nested abstraction.

The benefit of the Abstract Factory pattern is that it allows you to create a groups of products (the distributors and the advertisers) without having to know the actual class of the product being produced.

public enum CustomerLocation { EastCoast, WestCoast }

class Program
{
    static void Main(string[] args)
    {
        IBookStore storeA = new BookStoreA(CustomerLocation.EastCoast);

        Console.WriteLine("Book Store A with a customer from East Coast:");
        ShipBook(storeA);
        Advertise(storeA);

        IBookStore storeB = new BookStoreB(CustomerLocation.WestCoast);
        Console.WriteLine("Book Store B with a customer from West Coast:");
        ShipBook(storeB);
        Advertise(storeB);
    }

    //**** client code that does not need to be changed  ***
    private static void ShipBook(IBookStore s)
    {
        IDistributor d = s.GetDistributor();
        d.ShipBook();
    }

    //**** client code that does not need to be changed  ***
    private static void Advertise(IBookStore s)
    {
        IAdvertiser a = s.GetAdvertiser();
        a.Advertise();
    }
}



//the factory
public interface IBookStore
{
    IDistributor GetDistributor();
    IAdvertiser GetAdvertiser();
}

//concrete factory
public class BookStoreA : IBookStore
{
    private CustomerLocation location;

    public BookStoreA(CustomerLocation location)
    {
        this.location = location;
    }

    IDistributor IBookStore.GetDistributor()
    {
        //internal logic on which distributor to return
        //*** logic can be changed without changing the client code  ****
        switch (location)
        {
            case CustomerLocation.EastCoast:
                return new EastCoastDistributor();
            case CustomerLocation.WestCoast:
                return new WestCoastDistributor();
        }
        return null;
    }

    IAdvertiser IBookStore.GetAdvertiser()
    {
        //internal logic on which distributor to return
        //*** logic can be changed without changing the client code  ****
        switch (location)
        {
            case CustomerLocation.EastCoast:
                return new RedAdvertiser();
            case CustomerLocation.WestCoast:
                return new BlueAdvertiser();
        }
        return null;
    }
}

//concrete factory
public class BookStoreB : IBookStore
{
    private CustomerLocation location;

    public BookStoreB(CustomerLocation location)
    {
        this.location = location;
    }

    IDistributor IBookStore.GetDistributor()
    {
        //internal logic on which distributor to return
        //*** logic can be changed without changing the client code  ****
        switch (location)
        {
            case CustomerLocation.EastCoast:
                return new EastCoastDistributor();
            case CustomerLocation.WestCoast:
                return new WestCoastDistributor();
        }
        return null;
    }

    IAdvertiser IBookStore.GetAdvertiser()
    {
        //internal logic on which distributor to return
        //*** logic can be changed without changing the client code  ****
        switch (location)
        {
            case CustomerLocation.EastCoast:
                return new BlueAdvertiser();
            case CustomerLocation.WestCoast:
                return new RedAdvertiser();
        }
        return null;
    }
}

//the product
public interface IDistributor
{
    void ShipBook();
}

//concrete product
public class EastCoastDistributor : IDistributor
{
    void IDistributor.ShipBook()
    {
        Console.WriteLine("Book shipped by East Coast Distributor");
    }
}

//concrete product
public class WestCoastDistributor : IDistributor
{
    void IDistributor.ShipBook()
    {
        Console.WriteLine("Book shipped by West Coast Distributor");
    }
}

//the product
public interface IAdvertiser
{
    void Advertise();
}

//concrete product
public class RedAdvertiser : IAdvertiser
{
    void IAdvertiser.Advertise()
    {
        Console.WriteLine("Advertised by RedAdvertiser");
    }
}

//concrete product
public class BlueAdvertiser : IAdvertiser
{
    void IAdvertiser.Advertise()
    {
        Console.WriteLine("Advertised by BlueAdvertiser");
    }
}

0 comments:

Post a Comment

About

Powered by Blogger.