2016-05-29 55 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类”的理由,因为我不得不覆盖整个数组$的规则。 ......除此之外,把这个数组放在一个“特征”中不是更好吗? –