解讀工廠模式Factory Pattern

工廠類就是一個專門用來建立其它對象的類,工廠類在多態性編程實踐中是很是重要的。它容許動態替換類,修改配置,會使應用程序更加靈活。掌握工廠模式對Web開發是必不可少的。
工廠模式一般用來返回相似接口的不一樣的類,工廠的一種常見用法就是建立多態的提供者。
一般工廠模式有一個關鍵的構造,即通常被命名爲factory的靜態方法。這個靜態方法能夠接受任意數量的參數,而且必須返回一個對象。

Program List:基本的工廠類

01       
02 <?php
03     class Fruit {
04         // 對象從工廠類返回
05     }
06       
07     Class FruitFactory {
08           
09         public static function factory() {
10             // 返回對象的一個新實例
11             return new Fruit();
12         }
13     }
14       
15     // 調用工廠
16     $instance = FruitFactory::factory();
17 ?>

Program List:利用工廠類生產對象

01       
02 <?php
03 class Example
04 {
05     // The parameterized factory method
06     public static function factory($type)
07     {
08         if (include_once 'Drivers/' . $type . '.php') {
09             $classname = 'Driver_' . $type;
10             return new $classname;
11         } else {
12             throw new Exception('Driver not found');
13         }
14     }
15 }
16   
17 // Load a MySQL Driver
18 $mysql = Example::factory('MySQL');
19   
20 // Load an SQLite Driver
21 $sqlite = Example::factory('SQLite');
22 ?>

Program List:一個完整的工廠類

下面的程序定義了一個通用的工廠類,它生產可以保存你全部操做的空對象,你能夠得到一個實例,這些操做都在那個實例中了。
01 <?php
02       
03     /**
04      * Generic Factory class
05      *
06      * This Magic Factory will remember all operations you perform on it,
07      * and apply them to the object it instantiates.
08      *
09      */
10     class FruitFactory {
11         private $history, $class, $constructor_args;
12           
13         /**
14          * Create a factory of given class. Accepts extra arguments to be passed to
15          * class constructor.
16          */
17         function __construct( $class ) {
18             $args = func_get_args();
19             $this->class = $class;
20             $this->constructor_args = array_slice( $args, 1 );
21         }
22           
23         function __call( $method, $args ) {
24             $this->history[] = array(
25                 'action'    => 'call',
26                 'method'    => $method,
27                 'args'      => $args
28             );
29         }
30           
31         function __set( $property, $value ) {
32             $this->history[] = array(
33                 'action'    => 'set',
34                 'property'    => $property,
35                 'value'        => $value
36             );
37         }
38           
39         /**
40          * Creates an instance and performs all operations that were done on this MagicFactory
41          */
42         function instance() {
43             # use Reflection to create a new instance, using the $args 
44             $reflection_object = new ReflectionClass( $this->class ); 
45             $object = $reflection_object->newInstanceArgs( $this->constructor_args ); 
46               
47             # Alternative method that doesn't use ReflectionClass, but doesn't support variable
48             # number of constructor parameters.
49             //$object = new $this->class();
50               
51             # Repeat all remembered operations, apply to new object.
52             foreach( $this->history as $item ) {
53                 if( $item['action'] == 'call' ) {
54                     call_user_func_array( array( $object, $item['method'] ), $item['args'] );
55                 }
56                 if( $item['action'] == 'set' ) {
57                     $object->{$item['property']} = $item['value'];
58                 }
59             }
60               
61             # Done
62             return $object;
63         }
64     }
65       
66     class Fruit {
67         private $name, $color;
68         public $price;
69           
70         function __construct( $name, $color ) {
71             $this->name = $name;
72             $this->color = $color;
73         }
74           
75         function setName( $name ) {
76             $this->name = $name;
77         }
78           
79         function introduce() {
80             print "Hello, this is an {$this->name} {$this->sirname}, its price is {$this->price} RMB.";
81         }
82     }
83       
84     # Setup a factory
85     $fruit_factory = new FruitFactory('Fruit', 'Apple', 'Gonn');
86     $fruit_factory->setName('Apple');
87     $fruit_factory->price = 2;
88       
89     # Get an instance
90     $apple = $fruit_factory->instance();
91     $apple->introduce();
92   
93 ?>
程序運行結果:
1 Hello, this is an Apple , its price is 2 RMB.
工廠模式主要是爲建立對象提供過渡接口,以便將建立對象的具體過程屏蔽隔離起來,達到提升靈活性的目的。
工廠模式能夠分爲三類:
  • 簡單工廠模式(Simple Factory)
  • 工廠方法模式(Factory Method)
  • 抽象工廠模式(Abstract Factory)
這三種模式從上到下逐步抽象,而且更具通常性。
簡單工廠模式又稱靜態工廠方法模式。重命名上就能夠看出這個模式必定很簡單。它存在的目的很簡單:定義一個用於建立對象的接口。工廠方法模式去掉了簡單工廠模式中工廠方法的靜態屬性,使得它能夠被子類繼承。這樣在簡單工廠模式裏集中在工廠方法上的壓力能夠由工廠方法模式裏不一樣的工廠子類來分擔。
工廠方法模式彷彿已經很完美的對對象的建立進行了包裝,使得客戶程序中僅僅處理抽象產品角色提供的接口。那咱們是否必定要在代碼中遍及工廠呢?大可沒必要。也許在下面狀況下你能夠考慮使用工廠方法模式:
  • 當客戶程序不須要知道要使用對象的建立過程。
  • 客戶程序使用的對象存在變更的可能,或者根本就不知道使用哪個具體的對象。
相關文章
相關標籤/搜索