工廠模式分為簡(jiǎn)單工廠模式,工廠方法模式和抽象工廠模式,它們都屬于設(shè)計(jì)模式中的創(chuàng)建型模式。其主要功能都是幫助我們把對(duì)象的實(shí)例化部分抽取了出來(lái),目的是降低系統(tǒng)中代碼耦合度,并且增強(qiáng)了系統(tǒng)的擴(kuò)展性。本文對(duì)這三種模式進(jìn)行了介紹并且分析它們之間的區(qū)別。
簡(jiǎn)單工廠模式
簡(jiǎn)單工廠模式最大的優(yōu)點(diǎn)在于實(shí)現(xiàn)對(duì)象的創(chuàng)建和對(duì)象的使用分離,將對(duì)象的創(chuàng)建交給專門的工廠類負(fù)責(zé),但是其最大的缺點(diǎn)在于工廠類不夠靈活,增加新的具體產(chǎn)品需要修改工廠類的判斷邏輯代碼,而且產(chǎn)品較多時(shí),工廠方法代碼邏輯將會(huì)非常復(fù)雜。
<?php
//簡(jiǎn)單工廠方法
interface People
{
public function say();
}
class Man implements People
{
public function say()
{
echo 'this is a man ';
}
}
class Women implements People
{
public function say()
{
echo 'this is a women';
}
}
class SimpleFactory
{
public static function create($name)
{
if ($name == 'man') {
return new Man();
} elseif ($name == 'women') {
return new Women();
}
}
}
//具體調(diào)用
$man = SimpleFactory::create('man');
$man->say();
$women = SimpleFactory::create('women');
$women->say();
簡(jiǎn)單工廠模式最大的優(yōu)點(diǎn)在于實(shí)現(xiàn)對(duì)象的創(chuàng)建和對(duì)象的使用分離,將對(duì)象的創(chuàng)建交給專門的工廠類負(fù)責(zé),但是其最大的缺點(diǎn)在于工廠類不夠靈活,增加新的具體產(chǎn)品需要修改工廠類的判斷邏輯代碼,而且產(chǎn)品較多時(shí),工廠方法代碼將會(huì)非常復(fù)雜。
工廠方法模式
此模式中,通過(guò)定義一個(gè)抽象的核心工廠類,并定義創(chuàng)建產(chǎn)品對(duì)象的接口,創(chuàng)建具體產(chǎn)品實(shí)例的工作延遲到其工廠子類去完成。這樣做的好處是核心類只關(guān)注工廠類的接口定義,而具體的產(chǎn)品實(shí)例交給具體的工廠子類去創(chuàng)建。當(dāng)系統(tǒng)需要新增一個(gè)產(chǎn)品是,無(wú)需修改現(xiàn)有系統(tǒng)代碼,只需要添加一個(gè)具體產(chǎn)品類和其對(duì)應(yīng)的工廠子類,使系統(tǒng)的擴(kuò)展性變得很好,符合面向?qū)ο缶幊痰拈_(kāi)閉原則。體代碼如下:
<?php
//工廠方法模式
interface People
{
public function say();
}
class Man implements People
{
public function say()
{
echo 'this is a man';
}
}
class Women implements People
{
public function say()
{
echo 'this is a women';
}
}
//與簡(jiǎn)單工廠模式相比。區(qū)別在于,此處將對(duì)象的創(chuàng)建抽象成一個(gè)接口
interface CreatePeople
{
public function create();
}
class FactoryMan implements CreatePeople
{
public function create()
{
return new Man();
}
}
class FactoryWomen implements CreatePeople
{
public function create()
{
return new Women();
}
}
class Client
{
// 具體生產(chǎn)對(duì)象并執(zhí)行對(duì)象方法測(cè)試
public function test() {
$factory = new FactoryMan();
$man = $factory->create();
$man->say();
$factory = new FactoryWomen();
$man = $factory->create();
$man->say();
}
}
// 執(zhí)行
$demo = new Client();
$demo->test();
工廠方法模式是簡(jiǎn)單工廠模式的進(jìn)一步抽象和推廣。由于使用了面向?qū)ο蟮亩鄳B(tài)性,工廠方法模式保持了簡(jiǎn)單工廠模式的優(yōu)點(diǎn),而且克服了它的缺點(diǎn)。在工廠方法模式中,核心的工廠類不再負(fù)責(zé)所有產(chǎn)品的創(chuàng)建,而是將具體創(chuàng)建工作交給子類去做。這個(gè)核心類僅僅負(fù)責(zé)給出具體工廠必須實(shí)現(xiàn)的接口,而不負(fù)責(zé)產(chǎn)品類被實(shí)例化這種細(xì)節(jié),這使得工廠方法模式可以允許系統(tǒng)在不修改工廠角色的情況下引進(jìn)新產(chǎn)品。
抽象工廠模式
提供一個(gè)創(chuàng)建一系列相關(guān)或相互依賴對(duì)象的接口,而無(wú)須指定它們具體的類。抽象工廠模式又稱為Kit模式,屬于對(duì)象創(chuàng)建型模式。
此模式是對(duì)工廠方法模式的進(jìn)一步擴(kuò)展。在工廠方法模式中,一個(gè)具體的工廠負(fù)責(zé)生產(chǎn)一類具體的產(chǎn)品,即一對(duì)一的關(guān)系,但是,如果需要一個(gè)具體的工廠生產(chǎn)多種產(chǎn)品對(duì)象,那么就需要用到抽象工廠模式了。
<?php
interface TV{
public function open();
public function watch();
}
class HaierTv implements TV
{
public function open()
{
echo "Open Haier TV <br>";
}
public function watch()
{
echo "I'm watching TV <br>";
}
}
interface PC{
public function work();
public function play();
}
class LenovoPc implements PC
{
public function work()
{
echo "I'm working on a Lenovo computer <br>";
}
public function play()
{
echo "Lenovo computers can be used to play games <br>";
}
}
abstract class Factory{
abstract public static function createPc();
abstract public static function createTv();
}
class ProductFactory extends Factory
{
public static function createTV()
{
return new HaierTv();
}
public static function createPc()
{
return new LenovoPc();
}
}
$newTv = ProductFactory::createTV();
$newTv->open();
$newTv->watch();
$newPc = ProductFactory::createPc();
$newPc->work();
$newPc->play();
在上面的Factory抽象類中,定義了兩個(gè)抽象方法,這兩個(gè)抽象方法分別用來(lái)生產(chǎn)不同的產(chǎn)品(即由不同類實(shí)例化的對(duì)象)。
工廠方法模式和抽象工廠模式對(duì)比
通過(guò)以上代碼:我們來(lái)對(duì)比一下工廠方法模式和抽象工廠模式:
- 工廠方法模式中
當(dāng)我需要多生產(chǎn)一種新的產(chǎn)品,比如factoryKid這個(gè)產(chǎn)品,我需要專門再設(shè)一個(gè)factoryKid的工廠,即添加如下代碼:
class Kid implements People{
public function say()
{
echo 'this is a kid';
}
}
class FactoryKid implements CreatePeople
{
public function create()
{
return new Kid();
}
}
- 抽象工廠模式中
同樣當(dāng)我需要多生產(chǎn)一種新的產(chǎn)品,比如生產(chǎn)一個(gè)iphone,此時(shí)我需要修改工廠父類里的接口,并且在具體工廠類ProductFactory這個(gè)工廠里增加一條createPhone生產(chǎn)線(即類里面的方法),所需添加的代碼如下:
interface Phone{
public function work();
public function sms();
}
class IPhone implements Phone
{
public function work()
{
echo "I'm iphone <br>";
}
public function sms()
{
echo "this is an iphone <br>";
}
}
//在原來(lái)的抽象工廠類中添加方法聲明
abstract class Factory{
abstract public static function createPc();
abstract public static function createTv();
abstract public static function createPhone();
}
//在原來(lái)的工廠類里添加一個(gè)方法
class ProductFactory extends Factory
{
public static function createTV()
{
return new HaierTv();
}
public static function createPc()
{
return new LenovoPc();
}
public static function createPhone()
{
return new IPhone();
}
}
從上面的分析可以看出,要生產(chǎn)一個(gè)新的產(chǎn)品,抽象工廠模式并不比工廠方法模式更為便捷,那么抽象工廠模式的好處在哪呢?它優(yōu)點(diǎn)就是在于是增加固定類型產(chǎn)品的不同具體工廠比較方便,比如我要增加一個(gè)生產(chǎn)同樣類型產(chǎn)品的具體工廠Product2Factory,那么就再建一個(gè)Product2Factory類繼承Factory就可以了。
最后的最后,總結(jié)一下工廠方法模式和抽象工廠模式的核心區(qū)別
- 工廠方法模式利用繼承,抽象工廠模式利用組合
- 工廠方法模式產(chǎn)生一個(gè)對(duì)象,抽象工廠模式產(chǎn)生一族對(duì)象
- 工廠方法模式利用子類創(chuàng)造對(duì)象,抽象工廠模式利用接口的實(shí)現(xiàn)創(chuàng)造對(duì)象