2014-05-15 39 views
1

當我下潛到多框架的核心,我想做一個現實檢查,並確保我的一些方法來組成和依賴注入仍是很好的平衡。似乎還在不斷涌現的情況是,我需要提高班級的乾爽程度,爲將來的裝修留出空間,同時確保棘手的封裝不會過度,並且使其跟隨代碼變得非常具有挑戰性。當然會有支持文檔,但我們都希望代碼在很多方面只是「跟我們說話」。所以這裏有一個簡單的場景......哪種設計模式可用於在提供裝飾時保持乾燥?

想象有很多類,如下面的一個。戴夫的車,湯姆的汽車,蘇珊的車,等...等...等....等...

class DaveCar { 
    public $labor; 

    public function getLabor($userInput) 
    { 
     $this->labor = ... // Logic same for ALL cars 
    } 

    public function wheels() 
    { 
     $this->labor += ... // Logic unique to Dave's Car 
     return ...    
    } 

    public function body() 
    { 
     $this->labor *= ... // Logic unique to Dave's Car 
     return ... 
    } 

    public function build() 
    { 
     // Logic here is same for ALL cars 
     return $this->wheels() + $this->body(); 
    } 
} 

現在假設我們創建一個名爲CarBuilder來存儲重複的邏輯類,填充一些汽車類的屬性,也充當裝飾者。我們可以將車班減少到只有那些獨特的功能:

class DaveCar implements CarBuilderInterface{ 
    public $labor; 

    public function wheels() 
    { 
     $this->labor += ... // Logic unique to Dave's Car 
     return ...    
    } 

    public function body() 
    { 
     $this->labor *= ... // Logic unique to Dave's Car 
     return ... 
    } 
} 

,並調用它像這樣(注意:我使用的外牆,沒有單身這裏):

$cheapCar = CarBuilder::(new DaveCar)->getLabor(1)->build(); 
$qualityCar = CarBuilder::(new DaveCar)->getLabor(5)->build(); 

在現實世界(之後我可能會添加更多裝飾,如->buildJSON->buildPDF等等。

這裏有我有,將澄清我的思想的問題是在正確的軌道上:

  1. 這是好我避免繼承嗎? (秉承「組成了繼承」沒有成爲「撰寫-總是」)
  2. 爲什麼我使用什麼樣的設計模式嗎?
  3. 什麼樣的設計模式應該我在這裏使用?
  4. 我隱藏了太多的邏輯嗎?
  5. 我如何確保其他開發人員知道CarBuilder需要在他們的汽車類物業public $labor?接口將提供所需的方法,但對屬性無所作爲。目前,我只是在界面文件中記錄了該屬性是必需的(儘管我無法從界面強制執行它)。

回答

1

你混了的東西一點點。 CarBuilder構建Car s。它就像一個工廠,但對於更復雜,更一般的情況......例如:

class CarBuilder { 
    /** @var Car */ 
    protected $car; 
    public function newCar(){ 
     $this->car = new Car(); 
    } 

    public function addWheels(Wheel $wheel){ 
     $this->car->setWheel($wheel); 
    } 

    public function addWindow(Window $window, $position){ 
      if ($position == Car::FORWARD_WINDOW) 
       $this->car->setForwardWindow($window); 
    } 

    ... 

    /** @return Car */ 
    public function getCar(){ 
      return $this->car; 
    } 
} 

class DaveCarFactory { 
    public function createDaveCar(){ 
     $carBuilder = new CarBuilder(); 
     $carBuilder->newCar(); 
     $carBuilder->addWheels(new VerySpecialWheel()); 
     $carBuilder->addWindow(new UvFilteredWindow(), Car::FORWARD_WINDOW); 
     ... 
     $car = $carBuilder->getCar(); 
     return $car; 
    } 
} 

使用Builder在train wreck anti pattern可以在這種特殊情況下被允許(只要對象隱藏內部數據)並且,換句話說叫fluent interface

class DaveCarFactory { 
    public function createDaveCar(){ 
     return (new CarBuilder()) 
      ->newCar() 
      ->addWheels(new VerySpecialWheel()) 
      ->addWindow(new UvFilteredWindow(), Car::FORWARD_WINDOW) 
      ... 
      ->getCar(); 
    } 
} 
+0

好讓我消化今晚和送還給你的明天。火車殘骸+1流暢接口。我也會給你關於鏈接的想法。 – prograhammer