工廠類就是一個專門用來創建其它對象的類,工廠類在多態性編程實踐中是非常重要的。它允許動態替換類,修改配置,會使應用程序更加靈活。掌握工廠模式對Web開發是必不可少的。
工廠模式通常用來返回類似接口的不同的類,工廠的一種常見用法就是創建多態的提供者。
通常工廠模式有一個關鍵的構造,即一般被命名為factory的靜態方法。這個靜態方法可以接受任意數量的參數,並且必須返回一個對象。
<?php class Fruit { // 對象從工廠類返回 } Class FruitFactory { public static function factory() { // 返回對象的一個新實例 return new Fruit(); } } // 調用工廠 $instance = FruitFactory::factory(); ?>
<?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'); ?>
下面的程序定義了一個通用的工廠類,它生產能夠保存你所有操作的空對象,你可以獲得一個實例,這些操作都在那個實例中了。
<?php /** * Generic Factory class * * This Magic 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(); ?>
程序運行結果:
Hello, this is an Apple , its price is 2 RMB.
工廠模式主要是為創建對象提供過渡接口,以便將創建對象的具體過程屏蔽隔離起來,達到提高靈活性的目的。
工廠模式可以分為三類:
這三種模式從上到下逐步抽象,並且更具一般性。
簡單工廠模式又稱靜態工廠方法模式。重命名上就可以看出這個模式一定很簡單。它存在的目的很簡單:定義一個用於創建對象的接口。工廠方法模式去掉了簡單工廠模式中工廠方法的靜態屬性,使得它可以被子類繼承。這樣在簡單工廠模式裡集中在工廠方法上的壓力可以由工廠方法模式裡不同的工廠子類來分擔。
工廠方法模式仿佛已經很完美的對對象的創建進行了包裝,使得客戶程序中僅僅處理抽象產品角色提供的接口。那我們是否一定要在代碼中遍布工廠呢?大可不必。也許在下面情況下你可以考慮使用工廠方法模式: