PHP設(shè)計(jì)模式之工廠模式(Factory Pattern)的講解
面向?qū)ο缶幊讨?,工廠模式是我們最常用的實(shí)例化對(duì)象模式,工廠類就是一個(gè)專門用來(lái)創(chuàng)建其它對(duì)象的類,工廠類在多態(tài)性編程實(shí)踐中是非常重要的。它允許動(dòng)態(tài)替換類,修改配置,會(huì)使應(yīng)用程序更加靈活。掌握工廠模式對(duì)Web開發(fā)是必不可少的,它會(huì)給你的系統(tǒng)帶來(lái)更大的可擴(kuò)展性和盡量少的修改量。
工廠模式通常用來(lái)返回類似接口的不同的類,工廠的一種常見(jiàn)用法就是創(chuàng)建多態(tài)的提供者。
通常工廠模式有一個(gè)關(guān)鍵的構(gòu)造,即一般被命名為factory的靜態(tài)方法。這個(gè)靜態(tài)方法可以接受任意數(shù)量的參數(shù),并且必須返回一個(gè)對(duì)象。
一個(gè)非常貼近生活的例子來(lái)告訴你什么是工廠模式
但是工廠模式真的是個(gè)累贅嗎?其實(shí)并不是!他能夠作為一種設(shè)計(jì)模式流傳至今,一定是有他的道理的!只不過(guò)我們看到的例子只能說(shuō)明工廠模式是什么,并不能很好說(shuō)明工廠模式的優(yōu)點(diǎn),所以我們學(xué)會(huì)后并不知道為什么要使用工廠模式,以及什么時(shí)候應(yīng)該去使用工廠模式!
其實(shí)工廠模式在我們的現(xiàn)實(shí)生活中非常常見(jiàn),下面我舉個(gè)生活中的例子,大家應(yīng)該就能明白工廠模式的用處在哪里了!
麥當(dāng)勞大家都吃過(guò)吧?我們?nèi)c(diǎn)餐的時(shí)候,我們可以點(diǎn)一個(gè)漢堡,一杯可樂(lè),一個(gè)薯?xiàng)l。我們還可以點(diǎn)一杯可樂(lè),一個(gè)薯?xiàng)l。點(diǎn)完之后點(diǎn)餐員會(huì)問(wèn)我們一句還要?jiǎng)e的嗎?你說(shuō)不要了! 然后你的這一份餐就點(diǎn)完了,可以給錢了。咦,我們發(fā)現(xiàn)這是一個(gè)建造者模式(Builder Pattern)??!
(ps:這確實(shí)是突然發(fā)現(xiàn)的,之前寫建造者模式那篇文章的時(shí)候并沒(méi)有想到這個(gè)例子)
基本的工廠類:
<?php class Fruit { // 對(duì)象從工廠類返回 } Class FruitFactory { public static function factory() { // 返回對(duì)象的一個(gè)新實(shí)例 return new Fruit(); } } // 調(diào)用工廠 $instance = FruitFactory::factory(); ?>
利用工廠類生產(chǎn)對(duì)象:
<?php class Example { // The parameterized factory method public static function factory($type) { if (include_once 'Drivers/' . $type . '.php') { $classname = 'Driver_' . $type; return new $classname; } else { throw new Exception('Driver not found'); } } } // Load a MySQL Driver $mysql = Example::factory('MySQL'); // Load an SQLite Driver $sqlite = Example::factory('SQLite'); ?>
一個(gè)完整的工廠類:
下面的程序定義了一個(gè)通用的工廠類,它生產(chǎn)能夠保存你所有操作的空對(duì)象,你可以獲得一個(gè)實(shí)例,這些操作都在那個(gè)實(shí)例中了。
<?php /** * Generic Factory class * This Factory will remember all operations you perform on it, * and apply them to the object it instantiates. */ class FruitFactory { private $history, $class, $constructor_args; /** * Create a factory of given class. Accepts extra arguments to be passed to * class constructor. */ function __construct( $class ) { $args = func_get_args(); $this->class = $class; $this->constructor_args = array_slice( $args, 1 ); } function __call( $method, $args ) { $this->history[] = array( 'action' => 'call', 'method' => $method, 'args' => $args ); } function __set( $property, $value ) { $this->history[] = array( 'action' => 'set', 'property' => $property, 'value' => $value ); } /** * Creates an instance and performs all operations that were done on this MagicFactory */ function instance() { # use Reflection to create a new instance, using the $args $reflection_object = new ReflectionClass( $this->class ); $object = $reflection_object->newInstanceArgs( $this->constructor_args ); # Alternative method that doesn't use ReflectionClass, but doesn't support variable # number of constructor parameters. //$object = new $this->class(); # Repeat all remembered operations, apply to new object. foreach( $this->history as $item ) { if( $item['action'] == 'call' ) { call_user_func_array( array( $object, $item['method'] ), $item['args'] ); } if( $item['action'] == 'set' ) { $object->{$item['property']} = $item['value']; } } # Done return $object; } } class Fruit { private $name, $color; public $price; function __construct( $name, $color ) { $this->name = $name; $this->color = $color; } function setName( $name ) { $this->name = $name; } function introduce() { print "Hello, this is an {$this->name} {$this->sirname}, its price is {$this->price} RMB."; } } # Setup a factory $fruit_factory = new FruitFactory('Fruit', 'Apple', 'Gonn'); $fruit_factory->setName('Apple'); $fruit_factory->price = 2; # Get an instance $apple = $fruit_factory->instance(); $apple->introduce(); ?>
工廠模式主要是為創(chuàng)建對(duì)象提供過(guò)渡接口,以便將創(chuàng)建對(duì)象的具體過(guò)程屏蔽隔離起來(lái),達(dá)到提高靈活性的目的。
工廠模式可以分為三類:
- 簡(jiǎn)單工廠模式(Simple Factory)
- 工廠方法模式(Factory Method)
- 抽象工廠模式(Abstract Factory)
這三種模式從上到下逐步抽象,并且更具一般性。
簡(jiǎn)單工廠模式又稱靜態(tài)工廠方法模式;從命名上就可以看出這個(gè)模式一定很簡(jiǎn)單。它存在的目的很簡(jiǎn)單:定義一個(gè)用于創(chuàng)建對(duì)象的接口。
工廠方法模式去掉了簡(jiǎn)單工廠模式中工廠方法的靜態(tài)屬性,使得它可以被子類繼承。這樣在簡(jiǎn)單工廠模式里集中在工廠方法上的壓力可以由工廠方法模式里不同的工廠子類來(lái)分擔(dān)。
工廠方法模式仿佛已經(jīng)很完美的對(duì)對(duì)象的創(chuàng)建進(jìn)行了包裝,使得客戶程序中僅僅處理抽象產(chǎn)品角色提供的接口。那我們是否一定要在代碼中遍布工廠呢?大可不必。也許在下面情況下你可以考慮使用工廠方法模式:
- 當(dāng)客戶程序不需要知道要使用對(duì)象的創(chuàng)建過(guò)程。
- 客戶程序使用的對(duì)象存在變動(dòng)的可能,或者根本就不知道使用哪一個(gè)具體的對(duì)象。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請(qǐng)查看下面相關(guān)鏈接
相關(guān)文章
php時(shí)區(qū)轉(zhuǎn)換轉(zhuǎn)換函數(shù)
godaddy主機(jī)在國(guó)外。把站點(diǎn)建站國(guó)外,顯示時(shí)間時(shí)可能需要時(shí)區(qū)轉(zhuǎn)換,下面是個(gè)方便的工具函數(shù),用于時(shí)區(qū)轉(zhuǎn)換2014-01-01docker?中搭建php環(huán)境經(jīng)驗(yàn)分享
這篇文章主要介紹了docker?中搭建php環(huán)境經(jīng)驗(yàn)分享的相關(guān)資料,需要的朋友可以參考下2023-09-09php解決crontab定時(shí)任務(wù)不能寫入文件問(wèn)題的方法分析
這篇文章主要介紹了php解決crontab定時(shí)任務(wù)不能寫入文件問(wèn)題的方法,結(jié)合實(shí)例形式分析了crontab定時(shí)任務(wù)無(wú)法正常執(zhí)行的原因與解決方法,需要的朋友可以參考下2019-09-09thinkphp autoload 命名空間自定義 namespace
這篇文章主要介紹了thinkphp autoload 命名空間自定義 namespace的相關(guān)資料,需要的朋友可以參考下2015-07-07