Abstract Factory Pattern (AFP) merupakan salah satu jenis Creational
Pattern yang menangani mekanisme penciptaan object secara adaptif Abstract
Factory menyediakan
sebuah interface untuk menciptakan keluarga yang
terkait
atau object yang tergantung tanpa menentukan concrete class mereka.
Abstract
Factory mampu pengenkapsulasian sekelompok factory,
dimana masing-masing factory memiliki “motif” khasnya. AFP menjadi
sentral penentuan factory yang akan diinisialisasi sehingga product yang
diciptakan dapat mewarisi behaviour yang sesuai dengan motif yang dipilih.
Keistimewaan lain adalah product yang diciptakan terbebas dari
pernyataan penciptaan concrete class secara langsung. Hal ini memberikan
keuntungan yaitu AFP dapat mencegah coupling problem yang pasti terjadi
apabila penciptaan object memakai
operator new dalam bahasa OOP.
Rahasia dibalik kemampuan AFP ini terletak pada penyediaan
abstraksi terhadap factory dan product yang dihasilkan. Abstract factory memberikan
sekumpulan abstract method untuk
menciptakan jenis product tertentu yang harus diimplementasikan oleh
concrete factory. Abstract
product memberikan abstraksi pada keluarga product yang
berbeda motif dimana tentunya memiliki cara pengimplementasian yang berbeda
pula. Istilah “motif” dalam paragraf-paragraf sebelumnya diartikan sebagai
suatu theme atau corak khusus yang melekat pada suatu product.
Untuk memperjelas, katakanlah terdapat suatu abstract
factory bernama ToyFactory yang menyediakan fungsi penciptaan beberapa product
(misalnya: createRaceCar() dan createCuteDoll()). Sistem kemudian
menarik turunan ToysFactory karena adanya kebutuhan atas corak khusus tertentu,
yaitu WoodenToyFactory dan ElectricToyFactory; dimana keduanya mampu
menciptakan jenis mainan yang berbeda motif (seperti WoodenRaceCar dan
WoodenCuteDoll, atau ElectricRaceCar dan ElectricCuteDoll). Wooden dan Electric
adalah contoh dari motif yang dimaksudkan.
Keberadaan motif umumnya yang menjadi pemicu pemanfaatan AFP
dalam software design dimana setiap concrete factory mampu menciptakan
berbagai concrete product tetapi dalam kesamaan satu jenis motif. Pada
praktik pemakaian AFP, program client akan menginisialisasi suatu implementasi
dari abstract factory dan kemudian menggunakan interface abstract
product ketika ingin memperoleh atau bekerja dengan object konkrit product.
Contoh Program abstrak Factory :
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");
}
}