Abstract Factory Pattern Example With C#

Abstract factory pattern is to “provide an interface for creating families of related or dependent objects without specifying their concrete classes.”

For example a drawing & printing machine can process Low and High Resolution. Both have its own resolution drivers. Those drivers referred to concrete class with draw / print function. However the client implementation code asks the factory object class (not the concrete class) for a driver instance with provides information about resolution required. So this factory object return instance of concrete class.
The factory object implements an abstract class. It can instantiates a concrete class and return to client with casted to factory’s parent which is abstract Resolution driver.
The client uses the resolution driver as abstract without being aware about their concrete implementation.

Benefit of using factory pattern is in client code implementation, new resolution can be added with just providing that new resolution info as argument. So no change in client code.

Step by step example creating abstract factory pattern:

  1. Create Display & Print driver abstract classes
    abstract class DisplayDriver
        {
            abstract public void draw();
        }
    
    abstract class PrintDriver
    {
    	abstract public void doprint();
    }
    
  2. Create low & high resolution concrete classes that extend / inherit related abstract class above
    class LowDisplayDriver : DisplayDriver
        {
            public override void draw()
            {
                Console.WriteLine("Low display driver draw");
            }
        }
    
        class LowPrintDriver : PrintDriver
        {
            public override void doprint()
            {
                Console.WriteLine("Low printer driver doprint");
            }
        }
    
        class HighDisplayDriver : DisplayDriver
        {
            public override void draw()
            {
                Console.WriteLine("High display driver draw");
            }
        }
    
        class HighPrintDriver : PrintDriver
        {
            public override void doprint()
            {
                Console.WriteLine("High printer driver doprint");
            }
        }
    
    

    Those are codes to create concrete class of Low & High resolution drivers.

  3. Create an interface of factory class
      interface ResFactory
        {
            DisplayDriver  getDispDrvr();
            PrintDriver  getPrtDrvr();
        }
    

    Above interface will be implemented by factory classes.

  4. Create low & high resolution factory classes that implement ResFactory interface
    class LowResFact : ResFactory
    {
    	public DisplayDriver getDispDrvr()
    	{
    		return new LowDisplayDriver();
    	}
    
    	public PrintDriver getPrtDrvr()
    	{
    		return new LowPrintDriver();
    	}
    }
    
    class HighResFact : ResFactory 
    {
    
    	public DisplayDriver getDispDrvr()
    	{
    		return new HighDisplayDriver();
    	}
    
    	public PrintDriver  getPrtDrvr()
    	{
    		return new HighPrintDriver();
    	}
    }
    

    Those are Factory object returning concrete class instance and they implement ResFactory interface. LowResFact is factory to return LowDisplayDriver / LowPrintDriver class instance, low res driver concrete object. Same with HighResFact but this return high res drivers instance.

  5. Create controller class to encapsulate implementation
    class ApControl
    {
    	private ResFactory iResFact;
    	public ApControl(string resolution)
    	{
    		switch (resolution)
    		{
    			case "low":
    				iResFact = new LowResFact();
    				break;
    			case "high":
    				iResFact = new HighResFact();
    				break;
    		}
    	}
    
    	public void doDraw()
    	{
    		DisplayDriver disp_drv = iResFact.getDispDrvr();
    		disp_drv.draw();
    		
    	}
    
    	public void doPrint()
    	{
    		PrintDriver prnt_drv = iResFact.getPrtDrvr();
    		prnt_drv.doprint();
    	}
    }
    

    This ApControl class has resolution string argument and then based on argument value it chooses suitable factory object. Two functions doDraw() & doPrint() contains common interface function, getDispDrvr() and getPrtDrvr(). In code point of view, both doDraw & doPrint dont know which factory object is used because it casted to abstract resolution object.

  6. Write client implementation example
    ApControl ap_ctrl = new ApControl("low");
    ap_ctrl.doDraw();
    ap_ctrl.doPrint();
    

    That’s it. Try & run it. If you want to process high res then change to ApControl ap_ctrl = new ApControl("high"); .....

How about if there is new requirement of ‘Medium’ resolution ?

Well, we have to create ‘Medium’ concrete classes i.e MediumDisplayDriver that inherit DisplayDriver abstract and MediumPrintDriver that inherit PrintDriver abstract since we want to have Display & Print functionallity. After that, we have to create ‘Medium’ factory class i.e MediumResFact that implement a ResFactory interface. Also we have to add ‘medium’ switch case inside controller ‘ApControl’ class constructor.

It seems many changes in factory & concrete class but the benefit of factory pattern is in client implementation code. We can write ApControl ap_ctrl = new ApControl("medium"); .... in client implementation to process medium resolution. The change in client code is almost none, just provides argument value.

Regards,
Agung Gugiaji

Advertisements

One response to “Abstract Factory Pattern Example With C#

  1. Pingback: Design Patterns: Factory Method, Abstract Factory, and Singleton | Rodan Sotto's Tech Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s