2015-01-05 176 views
0

我正在閱讀有關可用的不同模式。目前我在抽象工廠模式,我認爲我對它有很好的把握。我的資源,除了維基百科: http://www.tutorialspoint.com/design_pattern/abstract_factory_pattern.htm http://www.oodesign.com/abstract-factory-pattern.html https://github.com/domnikl/DesignPatternsPHP/tree/master/Creational/AbstractFactoryPHP抽象工廠模式實現

我使用蘋果公司和它的產品做一個樣品Abstract Factory模式的一個例子。我明白代碼重複是不好的設計,因此我寫這個的原因。我的代碼到目前爲止是:

abstract class AbstractAppleFactory { 
    abstract public function createiPod($capacity, $type, $color, $engraving); 
    abstract public function createiPhone($capacity, $type, $color, $antenna); 
    abstract public function createComputer($type, $HDCapacity, $CPU, $ram); 
} 

class iPodFactory extends AbstractAppleFactory { 
    public function createiPod($capacity, $type, $color, $engraving) { 
     $class = 'iPod' . $type; 

     return new $class($capacity, $color, $engraving); 
    } 

    public function createiPhone($capacity, $type, $color, $antenna){ /* no implementation necessary */} 
    public function createComputer($type, $HDCapacity, $CPU, $ram){ /* no implementation necessary */} 
} 

interface iPlayer { 
    public function play(); 
    public function stop(); 
    public function fastForward(); 
    public function rewind(); 
} 

abstract class iPod implements iPlayer { 
    protected $capacity; 
    protected $color; 
    protected $engraving; 

    public function __construct($capacity, $color, $engraving = null) { 
     $this->capacity = $capacity; 
     $this->color = $color; 
     $this->engraving = $engraving; 
    } 
} 

class iPodClassic extends iPod { 
    public function play() {/* implementation goes here */} 
    public function stop() {/* implementation goes here */} 
    public function fastForward() {/* implementation goes here */} 
    public function rewind() {/* implementation goes here */} 
} 
class iPodShuffle extends iPod { 
    public function play() {/* implementation goes here */} 
    public function stop() {/* implementation goes here */} 
    public function fastForward() {/* implementation goes here */} 
    public function rewind() {/* implementation goes here */} 
} 

等等。有太多的代碼放在這裏。我知道在目錄和命名空間中組織更好。這不是我現在正在學習的東西。我正在學習模式和麪向對象的概念。

有問題的部分是:

class iPodFactory extends AbstractAppleFactory { 
    public function createiPod($capacity, $type, $color, $engraving) { 
     $class = 'iPod' . $type; 

     return new $class($capacity, $color, $engraving); 
    } 

    public function createiPhone($capacity, $type, $color, $antenna){ /* no implementation necessary */} 
    public function createComputer($type, $HDCapacity, $CPU, $ram){ /* no implementation necessary */} 
} 

由於繼承/抽象我被迫實施無關二廠不必要的方法。 createiPhone()createComputer()。我在做抽象工廠模式嗎?再次,「代碼重複是糟糕的設計!」還有什麼更好的辦法呢?

+0

您是否必須堅持整個項目的一種模式?我個人根據需要使用設計模式。你有沒有考慮過使用依賴注入來將你的iPhone對象注入到任何類中,這樣你就可以使用它的方法了? – Joao

+0

這只是一個練習。 –

回答

3

我想你犯了一個重大錯誤。抽象工廠的目的是爲創建產品族創建一個抽象,以便您可以輕鬆地將其更改爲不同的家族。 f1。 Apple => Samsung :)

interface ComputerAbstractFactory { 
    /** 
    * @return Tablet 
    */ 
    function createTablet(); 
    /** 
    * @return Phone 
    */ 
    function createPhone(); 
    /** 
    * @return Computer 
    */ 
    function createComputer(); 
} 

class AppleComputerFactory implements ComputerAbstractFactory {} 

class SamsungComputerFactory implements ComputerAbstractFactory {} 

class IPad implements Tablet {} 

class GalaxyTab implements Tablet {} 

... 

當您要在兩家公司之間切換時,使用抽象工廠模式很有意義。 你的代碼應該只取決於抽象(實體原則)ComputerAbstractFactory,平板電腦,電話,計算機。 如果你決定(某些配置開關FE)這樣一來,其製造商應使用它的足夠多,你注入choosen實施ComputerAbstractFactory到你的經營業務 代碼和你做 - 一切正常,平板電腦生成,手機等

您需要決定在應用程序中創建什麼樣的抽象,以便調用代碼不會與該抽象的具體實現耦合。我相信IPlayer是你想要的,其中IPodClassic IPodShuffle是具體的實現。 如果我是對的,你應該創建IPlayerFactory

class IPlayerFactory { 
    /** 
    * @return IPlayer 
    */ 
    function create() {...} 
} 

關於你提到的重複。如果iPodFactory擴展了AbstractAppleFactory,它應該實現它的所有方法(順便說一下,如果AbstractAppleFactory沒有任何實現,它應該是一個接口) 您打破了來自SOLID原則的Liskov原理。短版本 - 如果調用代碼依賴於AbstractAppleFactory,並且它將iPodFactory作爲具體實現進行操作,它將在調用createiPhone或createComputer時中斷 - 因此在這種情況下抽象不起作用。

+0

謝謝@Jakub!這是我第一次對模式進行練習。 –

+0

我已經看過「抽象」的定義,並且你是100%正確的。我想我永遠不知道它是什麼! –

0

你是對的,但我認爲你的界面是錯誤的。

首先,不要使用abstract類,除非您需要創建一個將用於子類的方法。使用interface會更好。

這將是我的解決方案:

<?php 
interface AppleFactoryInterface 
{ 
    function create($data); 
} 

這裏是一個iPhoneFactory:

<?php 
class iPhoneFactory implements AppleFactoryInterface 
{ 
    public function create($data) 
    { 
     $klass = sprintf('iPhone'.$data['type']); 
     $instance = new $klass; 
     $instance->setFromArray($data); 

     return $instance; 
    } 
} 

正如你所看到的,我有很少的代碼,這是更好理解。