2016-05-29 34 views
1

我經常與以下案件一起,我不確定這是否是在OOP中的良好做法。所以我想也許你可以幫助我。php類與對象屬性的預定義規則

我會與添加水果水果籃,像這樣的一個示例簡化此:

$obj = new FruitBasket(); 
$obj->add(new Fruit('Banana')); 
$obj->add(new Fruit('Apple')); 
$obj->add(new Fruit('Kiwi')); 
$obj->get(); 

類「水果籃」簡單地相加並輸出這些數據:

class FruitBasket { 
    private $fruits = []; 

    public function add(Fruit $fruit) 
    { 
     $this->fruits[] = $fruit; 
    } 

    public function get() 
    { 
     foreach ($this->fruits as $fruit) 
     { 
      echo $fruit->get('type') .': '. $fruit->get('color') .' with '. ($fruit->get('seed') === true ? 'seeds.' : 'no seeds.') . '<br>'; 
     } 
    } 
} 

確定。 那麼「果」類 - 這是我在想一個更好的做法:

class Fruit { 
    private $type; 
    private $color; 
    private $seed; 
    // Is this cool(?): 
    private $rules = [ 
     'Apple' => ['color' => 'red', 'seed' => true], 
     'Banana' => ['color' => 'yellow', 'seed' => false], 
     'Kiwi' => ['color' => 'green', 'seed' => true] 
     // … 
    ]; 

    public function __construct($type) 
    { 
     if (isset($this->rules[$type])) 
     { 
      $this->type = $type; 
      $this->color = $this->rules[$type]['color']; 
      $this->seed = $this->rules[$type]['seed']; 
     } 
    } 

    public function get($attr = null) 
    { 
     if (isset($this->$attr) && !is_null($this->$attr)) 
      return $this->$attr; 
    } 
} 

這個類(水果)包含一個屬性$rules,這是所有可能的陣列(或「允許」)水果。在這個例子中,只有3個,但在現實世界中,它們也可能達到20個。該數組還包含每個水果的屬性。不會改變的屬性,因爲香蕉永遠是黃色的(讓我們這麼說)。所以這些屬性是常量。 當Fruit-object被創建時,構造函數設置所有這些屬性。

所以我的問題是:有這種可能的水果及其屬性的數組是好的嗎?

...

我寫的水果類和類的替代版本,每種類型的水果。在這裏看到:

abstract class Apple { 
    const color = 'red'; 
    const seed = true; 
} 

abstract class Banana { 
    const color = 'yellow'; 
    const seed = false; 
} 

abstract class Kiwi { 
    const color = 'green'; 
    const seed = true; 
} 

// … 

class Fruit { 
    private $type; 
    private $color; 
    private $seed; 

    public function __construct($type) 
    { 
     $class = $type; // just to make it clear 

     if (class_exists($class)) 
     { 
      $this->type = $type; 
      $this->color = $class::color; 
      $this->seed = $class::seed; 
     } 
    } 

    public function get($attr = null) 
    { 
     if (isset($this->$attr) && !is_null($this->$attr)) 
      return $this->$attr; 
    } 
} 

這些類設置爲「抽象」,因爲我不想從它們創建對象。 (我知道(!)我可以將這些水果類延伸到水果類,但這不適用於任何情況,這裏不是重點。) 我也不喜歡這個(第二種)版本是,我需要爲每個水果創建自己的文件(當使用自動加載...)。

因此,如果我比較每個水果的20個類別,並將它們放入20個單獨的文件中,並使用一個簡單的數組進行比較......嗯......數組非常簡單。

但我想知道的是......有沒有這個問題的任何「最佳做法」? 任何模式?你會建議什麼?

+0

讓我知道我的答案是否對你有幫助。 – Webeng

回答

2

鑑於這兩種方法的工作,它歸結爲可讀性和實用性。我個人發現第一種方法更加用戶友好。你可以很容易地看到水果和它在給定數組中的屬性之間的關係。

我可能會看到的唯一問題是該類可能會因添加更多屬性而變得太大,並且可能使Fruit類中的其他變量和函數變矮。你可以或者創建另一個類,用於存儲規則:

class Rules { 
    protected $rules = [ 
     'Apple' => ['color' => 'red', 'seed' => true], 
     'Banana' => ['color' => 'yellow', 'seed' => false], 
     'Kiwi' => ['color' => 'green', 'seed' => true] 
     // … 
    ]; 
} 

,然後讓水果類擴展它:

class Fruit extends Rules {//... 

這會給你2個好處:

  1. 清潔代碼。

  2. 如果出於某種原因,將來您需要在另一個班級使用這些規則,那麼您也可以簡單地擴展它。

+0

瘋了。從來沒有想到這一點。另外我會設置這個類來抽象。這很好,但我會等待更好的。因爲我不相信你用「擴展Rules類」的理由,因爲我不得不覆蓋整個數組$的規則。 ......除此之外,把這個數組放在一個「特徵」中不是更好嗎? –