定義:
抽象工廠模式:提供一個建立一系列相關或互相依賴對象的接口,而無需指定他們的具體類。抽象工廠模式主要解決涉及到多個産品系列的問題。
代碼執行個體:
先回顧上一篇中工廠方法模式的例子,該示例以 BloggsCal 和 MegaCal 兩種格式管理編碼。如果增加更多的編碼格式,這種類結構會橫向增長,但如何為不同類型的 PIM 對象加入編碼器,使類結構“縱向”增長呢?
這裡将會用到三個相似的類層次結構,分别是預約(Appt)、待辦事項(Ttd)以及聯系人(Contact)。
1、建立Appt 抽象類
/**
* Appt 抽象類
* Class ApptEncoder
*/
abstract class ApptEncoder
{
abstract public function encode();
}
2、建立Ttd 抽象類
/**
* Ttd 抽象類
* Class TtdEncoder
*/
abstract class TtdEncoder
{
abstract public function encode();
}
3、建立Contact 抽象類
/**
* Contact 抽象類
* Class ContactEncoder
*/
abstract class ContactEncoder
{
abstract public function encode();
}
4、建立BloggsCal Appt 格式處理類
/**
* BloggsCal Appt 格式處理類
* Class BloggsApptEncoder
*/
class BloggsApptEncoder extends ApptEncoder
{
public function encode()
{
// TODO: Implement encode() method.
return "Appointment data encoded in BloggsCal format\n";
}
}
5、建立BloggsCal Ttd 格式處理類
/**
* BloggsCal Ttd 格式處理類
* Class BloggsTtdEncoder
*/
class BloggsTtdEncoder extends TtdEncoder
{
public function encode()
{
// TODO: Implement encode() method.
return "Ttd data encoded in BloggsCal format\n";
}
}
6、建立BloggsCal Contact 格式處理類
/**
* BloggsCal Contact 格式處理類
* Class BloggsContactEncoder
*/
class BloggsContactEncoder extends ContactEncoder
{
public function encode()
{
// TODO: Implement encode() method.
return "Contact data encoded in BloggsCal format\n";
}
}
7、建立MegaCal Appt 格式處理類
/**
* MegaCal Appt 格式處理類
* Class MegaApptEncoder
*/
class MegaApptEncoder extends ApptEncoder
{
public function encode()
{
// TODO: Implement encode() method.
return "Appointment data encoded in MegaCal format\n";
}
}
8、建立MegaCal Ttd 格式處理類
/**
* MegaCal Ttd 格式處理類
* Class MegaTtdEncoder
*/
class MegaTtdEncoder extends TtdEncoder
{
public function encode()
{
// TODO: Implement encode() method.
return "Ttd data encoded in MegaCal format\n";
}
}
9、建立MegaCal Contact 格式處理類
/**
* MegaCal Contact 格式處理類
* Class MegaContactEncoder
*/
class MegaContactEncoder extends ContactEncoder
{
public function encode()
{
// TODO: Implement encode() method.
return "Contact data encoded in MegaCal format\n";
}
}
10、建立BloggsCal 工廠類
/**
* BloggsCal 工廠類
* Class BloggsCommsManager
*/
class BloggsCommsManager extends CommsManager
{
public function getHeaderText()
{
// TODO: Implement getHeaderText() method.
return "BloggsCal header\n";
}
public function getApptEncoder()
{
// TODO: Implement getApptEncoder() method.
return new BloggsApptEncoder();
}
public function getTtdEncoder()
{
// TODO: Implement getTtdEncoder() method.
return new BloggsTtdEncoder();
}
public function getContractEncoder()
{
// TODO: Implement getContractEncoder() method.
return new BloggsContactEncoder();
}
public function getFooterText()
{
// TODO: Implement getFooterText() method.
return "BloggsCal footer\n";
}
}
11、建立MegaCal 工廠類
/**
* MegaCal 工廠類
* Class MegaCommsManager
*/
class MegaCommsManager extends CommsManager
{
public function getHeaderText()
{
// TODO: Implement getHeaderText() method.
return "MegaCal header\n";
}
public function getApptEncoder()
{
// TODO: Implement getApptEncoder() method.
return new MegaApptEncoder();
}
public function getTtdEncoder()
{
// TODO: Implement getTtdEncoder() method.
return new MegaTtdEncoder();
}
public function getContractEncoder()
{
// TODO: Implement getContractEncoder() method.
return new MegaContactEncoder();
}
public function getFooterText()
{
// TODO: Implement getFooterText() method.
return "MegaCal footer\n";
}
}
12、調用
$mgr = new BloggsCommsManager();
print $mgr->getHeaderText();
print $mgr->getApptEncoder()->encode();
print $mgr->getTtdEncoder()->encode();
print $mgr->getContractEncoder()->encode();
print $mgr->getFooterText();
$mega = new MegaCommsManager();
print $mega->getHeaderText();
print $mega->getApptEncoder()->encode();
print $mega->getTtdEncoder()->encode();
print $mega->getContractEncoder()->encode();
print $mega->getFooterText();
13、結果
BloggsCal header
Appointment data encoded in BloggsCal format
Ttd data encoded in BloggsCal format
Contact data encoded in BloggsCal format
BloggsCal footer
MegaCal header
Appointment data encoded in MegaCal format
Ttd data encoded in MegaCal format
Contact data encoded in MegaCal format
MegaCal footer
總結:
1、解除了系統與實作細節間的耦合。我們可以在示例程式中添加或移除任何數量的編碼類型,而不會對系統造成任何影響。
2、我們組合了系統中功能相關的元素。是以,BloggsCommsManager 可以確定隻使用與 BloggsCal 格式相關的類。
3、添加新産品會非常痛苦,這是因為我們不僅需要建立新産品的實作類,還需要修改抽象建立者及其所有的實作類來支援這個新産品。