Search Forum
(57415 Postings)
Search Site/Articles

Archived Articles
712 Articles

C# Books
C# Consultants
What Is C#?
Download Compiler
Code Archive
Archived Articles
Advertise
Contribute
C# Jobs
Beginners Tutorial
C# Contractors
C# Consulting
Links
C# Manual
Contact Us
Legal

GoDiagram for .NET from Northwoods Software www.nwoods.com


              
Printable Version

Creational Pattern - Abstract Factory
By Ashish Jaiman

Context

An abstract factory provides an interface for creating families of related objects without specifying their concrete classes.

Sometimes one wants to construct an instance of one of a suite of classes, deciding between the classes at the time of instantiation. In order to avoid duplicating the decision making everywhere an instance is created, we need a mechanism for creating instances of related classes without necessarily knowing which will be instantiated. Solution

Create an Abstract Factory class to answer instances of concrete classes (usually subclasses). The class of the resultant instance is unknown to the client of the Abstract Factory.

There are two types of Abstract Factory:
- Simple Abstract Factory is an abstract class defining Factory methods to answer instances of concrete subclasses. The choice of which subclass to instantiate is completely defined by which method is used, and is unknown to the client.
- The second form of Abstract Factory is an abstract class defining a common protocol of Factory methods. Concrete subclasses of the abstract factory implement this protocol to answer instances of the appropriate suite of classes. See below for an example, both VB.net and C# implementation

Applicability
- Need to abstract from details of implementation of products -The system shall be independent of how its constituent pieces are created, composed, and represented.
- Need to have multiple families of products - The system shall be configured with one of multiple families of products.
- Need to enforce families of products that must be used together - A family of related product objects is designed to be used together, and you need to enforce this constraint.
- Need to hide product implementations and just present interfaces - You want to provide a class library of products, and you want to reveal just their interfaces, not their implementations.

Characteristics
- An abstract factory is an object maker.
- It typically can produce more than one type of object.
- Each object that it produces is known to the receiver of the created object only by that object's interface, not by the object's actual concrete implementation.
- The different types of objects that the abstract factory can produce are related -- they are from a common family
- An abstract factory isolates concrete classes
- It makes exchanging product families easy
- It promotes consistency among products
- It supports adding new kinds of products and their families.

Example
The Example here has an implementation of an Abstract Factory as an Interface IAVDevice that has methods that can create an Audio object and a Video object. The client Codes against IAVDevice and gets IAudio and IVideo interfaces. Passing "cd" in the command line creates a family of cd objects (Audio and Video) and "dvd" creates a family of dvd objects (Audio and Video). The client doesn't care which object (cd audio video or dvd audio video), IAVDevice interface returns as it codes against IAudio and IVideo interface. C# Implementation

To run the example from console first make the exe and then run it by using csc /out:AbstractFactory.exe AbstractFactory.cs //Creates AbstractFactory
AbstractFactory cd //CD Family
AbstractFactory dvd //DVD Family

using System; 

public interface IAVDevice 
{       
        IAudio GetAudio(); 
        IVideo GetVideo(); 
}               

public interface IVideo 
{       
        string GetPictureQuality(); 
} 

public interface IAudio 
{       
        string GetSoundQuality(); 
} 

class CCd:IAVDevice 
{ 
        public IAudio GetAudio() 
        { 
                return new CCdAudio(); 
        } 
        public IVideo GetVideo() 
        { 
                return new CCdVideo(); 
        }       
} 

class CDvd:IAVDevice 
{ 
        public IAudio GetAudio() 
        { 
                 return new CDvdAudio(); 
        } 
        public IVideo GetVideo() 
        { 
                return new CDvdVideo(); 
        }       
} 

class CCdAudio:IAudio 
{       
        public string GetSoundQuality() 
        { 
                return "CD Audio is better then DVD Audio"; 
        } 
} 

class CCdVideo:IVideo 
{ 
        public string GetPictureQuality() 
        { 
                return "CD video quality is not as good as DVD"; 
        } 
} 

class CDvdAudio:IAudio 
{ 
        public string GetSoundQuality() 
        { 
                 return  "DVD Audio is not as good as CD Audio"; 
        }       
} 

class CDvdVideo:IVideo 
{       
        public string GetPictureQuality() 
        { 
                return "DVD video quality is better then CD"; 
        } 
} 

class CAVMaker 
{       
        public IAVDevice AVMake(string xWhat) 
        { 
                switch (xWhat.ToLower()) 
                { 
                        case "cd": 
                                return new CCd(); 
                        case "dvd": 
                                 return new CDvd(); 
                        default: 
                                return new CCd();                       
                } 
        }                                                                                 
} 

public class AbstractFactory 
{ 
        static void Main(string[] args) 
        { 
                CAVMaker objFactMaker = new CAVMaker(); 
                IAVDevice objFact; 
                IAudio objAudio; 
                IVideo objVideo; 
                string strWhat; 
                strWhat = args[0]; 
                objFact = objFactMaker.AVMake(strWhat); 
                objAudio = objFact.GetAudio(); 
                objVideo = objFact.GetVideo(); 
                Console.WriteLine(objAudio.GetSoundQuality()); 
                Console.WriteLine(objVideo.GetPictureQuality()); 
        } 
} 



VB.Net Implementation 
To run the example from console first make the exe and then run it by using 
vbc /out:AbstractFactory.exe AbstractFactory.vb         'Creates AbstractFactory 
AbstractFactory cd                                      'CD Family 
AbstractFactory dvd                                     'DVD Family 

Imports System 

Public Interface IAVDevice 
    Function GetAudio() As IAudio 
    Function GetVideo() As IVideo 
End Interface 

Public Interface IAudio 
    Function GetSoundQuality() As String 
End Interface 

Public Interface IVideo 
    Function GetPictureQuality() As String 
End Interface 

Class CCd 
    Implements IAVDevice 

    Public Function GetAudio() As IAudio Implements IAVDevice.GetAudio 
        GetAudio = New CCdAudio() 
    End Function 

    Public Function GetVideo() As IVideo Implements IAVDevice.getVideo 
        GetVideo = New CCdVideo() 
    End Function 
End Class 

Class CDvd 
    Implements IAVDevice 

    Public Function GetAudio() As IAudio Implements IAVDevice.GetAudio 
        GetAudio = New CDvdAudio() 
    End Function 

    Public Function GetVideo() As IVideo Implements IAVDevice.GetVideo 
        GetVideo = New CDvdVideo() 
    End Function 
End Class 

Class CCdAudio 
    Implements IAudio 

    Public Function GetSoundQuality() As String Implements IAudio.GetSoundQuality 
        GetSoundQuality = "CD Audio is better then DVD Audio" 
    End Function 
End Class 

Class CCdVideo 
    Implements IVideo 

    Public Function GetPictureQuality() As String Implements IVideo.GetPictureQuality 
        GetPictureQuality = "CD video quality is not as good as DVD" 
    End Function 
End Class 

Class CDvdAudio 
    Implements IAudio 

    Public Function GetSoundQuality() As String Implements IAudio.GetSoundQuality 
        GetSoundQuality = "DVD Audio is not as good as CD Audio" 
    End Function 
End Class 

Class CDvdVideo 
    Implements IVideo 

    Public Function GetPictureQuality() As String Implements IVideo.GetPictureQuality 
        GetPictureQuality = "DVD video quality is better then CD" 
    End Function 
End Class 

Public Class CAVMaker 
    Public Function AVMake(ByVal xWhat As String) As IAVDevice 
        Select Case xWhat.ToLower 
            Case "cd" 
                AVMake = New CCd() 
            Case "dvd" 
                AVMake = New CDvd() 
        End Select 
    End Function 
End Class 

public Class Client 
        Public Shared Sub Main(ByVal CmdArgs() As String) 
                Dim objFactMaker As New CAVMaker() 
                Dim objFact As IAVDevice 
                Dim objAudio As IAudio 
                Dim objVideo As IVideo 
                Dim strWhat as String 
                strWhat = CmdArgs(0) 
                objFact = objFactMaker.AVMake(strWhat) 
                objAudio = objFact.GetAudio 
                objVideo = objFact.getVideo 
                Console.WriteLine(objAudio.GetSoundQuality) 
                Console.WriteLine(objVideo.GetPictureQuality) 
        End sub 
End Class 

Reference: E. Gamma et al., "Design Patterns: Elements of Reusable Object-Oriented Software"

ISBN 0-201-63361-2, Addison Wesley, 1995.