Article source code: abstractfactory.zip
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.
Diagram

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.