Reference: E. Gamma et al., "Design
Patterns: Elements of Reusable
Object-Oriented Software"
ISBN 0-201-63361-2, Addison Wesley, 1995.
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