2013-02-08 82 views
4

我只是想知道這是否是在PHP中創建對象並實現工廠模式的正確方法。我知道我們有工廠方法模式和抽象工廠模式,但是我們有如下模式: http://noondreams.com/shared/data/pages/images/Factory.png什麼是實施工廠模式的正確方法?

class Factory 
{ 
public function make($format) 
{ 
    switch($format) 
    { 
     case Source::Assocs: 
      return new \Source\Formats\Assocs(); 
     case Source::XML 
      return new \Source\Formats\XML(); 
     //Some other formats 
    } 
} 
} 
+1

雖然我會使用像'\來源\格式靜態函數::創建($格式)',你的代碼看起來不錯。那有什麼不對? – hek2mgl 2013-02-08 21:27:56

+1

這是一個反模式:long switch-statement和一個知道它的所有子類的父類 – 2013-02-08 21:28:03

+1

@fab這不是一個通用工廠,但它是可以的。我看到沒有'反模式' – hek2mgl 2013-02-08 21:29:13

回答

6

不,這不是一個真正的工廠模式。工廠模式會看起來更象這樣:

<?php 
abstract class File 
{ 
    public static function createFromFile($filename) 
    { 
     $extension = /* get file extension */; 

     switch ($extension) 
     { 
      case 'xml': 
       return new XmlFile($filename); 
       break; 
      case 'php': 
       return new PhpFile($filename); 
       break; 
     } 

     throw new \InvalidArgumentException(); 
    } 
} 

class XmlFile extends File 
{ 

} 

class PhpFile extends File 
{ 

} 

通知抽象類是如何創建它擴展,而不必擔心各類它可能會返回用戶的具體類的實例。

注意:在真實場景中,您不會使用switch語句,但可能會反射或各種其他技術,因爲抽象類不會知道它的所有子類。

這看起來更像是這樣的:

<?php 
abstract class File 
{ 
    public static function createFromFile($filename) 
    { 
     $extension = /* get file extension */; 
     $extension = ucfirst($extension); 

     $reflection = new ReflectionClass($extension . 'File'); 
     return $reflection->newInstanceArgs(array($filename)); 
    } 
} 

class XmlFile extends File 
{ 

} 

class PhpFile extends File 
{ 

} 
+0

我的代碼與你的主要區別是什麼?雖然在你們看來,超級大師知道子類 – 2013-02-08 22:21:19

+1

@MohammadRahmani 1)就像它在你們那裏一樣。 2)僅在第一個例子中,我後來澄清說這僅僅是爲了演示,真實場景會有所不同。 3)工廠是子類擴展的抽象類。如果返回的對象與創建對象的類型不同,工廠模式就沒有意義。 – 2013-02-08 22:55:14

+0

但我認爲你讓超類知道子類,這是一個反模式 – 2013-02-08 23:29:56