2016-05-29 10 views
1

私はしばしば次のケースに遭遇しています。これはOOPの優れたプラクティスであるかどうかわかりません。だから私はあなたがこれで私を助けることができると思った。オブジェクト属性にあらかじめ定義されたルールを持つphpクラス

Iのように、フルーツバスケットにフルーツを追加する例でこれを簡素化されます:

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

クラス "FruitBasket" は、単にデータを追加し、出力:

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>'; 
     } 
    } 
} 

[OK]を。 そして、「フルーツ」クラス - 私はより良い練習と思っていますこれはどこです:

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オブジェクトが作成されると、コンストラクタはこれらのすべての属性を設定します。

私の質問です:この可能な果物とその属性の配列を持つことは良いですか?

...

私は果物の種類ごとにフルーツクラスとクラスの代替バージョンを書きました。これを参照してください:

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

両方の方法が機能すると、読みやすさと実用性が低下します。私は個人的に最初の方法をよりユーザーフレンドリーなものにしています。与えられた配列の果物とその性質の関係を簡単に見ることができます。

私が見るかもしれない唯一の問題は、クラスが多くのプロパティを追加すると大きすぎて、Fruitsクラスの他の変数と関数を矮小化する可能性があることです。

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

をして、あなたのフルーツのクラスは、それを拡張あります:あなたは、代わりにルールを保存するための別のクラスを作成することができ

  1. クリーナーコード:

    class Fruit extends Rules {//... 
    

    これはあなたに2つの恩恵を与えるだろう。

  2. 将来何らかの理由で別のクラスにこれらのルールが必要な場合は、単純に拡張することもできます。

+0

クレイジー。決してこれを考えなかった。さらに、このクラスをabstractに設定します。それはかなり良いですが、私はより良いものを待つでしょう。私はあなたの議論を「ルールクラスを拡張する」とは信じていないので、配列$ルール全体を上書きする必要があるからです。 ...それ以外にも、配列を「形質」に入れる方が良いのではないでしょうか? –

関連する問題