【问题标题】:PHP OOP Constructor Design PatternPHP OOP 构造函数设计模式
【发布时间】:2014-10-12 14:28:49
【问题描述】:

我有这个代码。它有效,但有可能做得更好吗?用更少的代码?

public function __construct($type ,$brand, $model, $year, $mileage, $height, $width, $depth, $ps, $color, $price, $value, $seats)
{
    if (is_int($type)) {
        $this->_type = $type;
    } else {
        throw new Exception('Wrong Value in Type. Expected integer');
    }
}

...

我创建一个这样的对象

try {
    $firstCar = new Car(1, 'Audi', 'A3', 2011, 94512, 2, 2, 2, 105, 'Black', 1000, 1920, 5);
} catch ( Exception $error) {
    die($error->getMessage());
}

我对 2 个类中的每个变量重复“IF-ELSE”语句。它的代码太多了。

这里有一些建议吗?

【问题讨论】:

  • 这感觉就像你向构造函数传递了太多参数:如果你必须这样做,而不是为每个属性使用 setter 方法,可能会循环 func_get_args()
  • 对于codereview.stackexchange.com来说,这似乎是一个很好的问题
  • 嘿@MarkBaker。也许吧,但我找不到更好的解决方案。阅读一些有关设计模式的内容,但我不知道如何处理该代码。
  • 我认为验证输入不是班级的工作。这应该在每次将信息传递给构造函数之前在外部完成。
  • 在@mark-baker 评论之后,re:循环通过 func_get_args()... 您可以将该数组传递给类中的私有方法,该方法仅验证所有元素。或者每个参数的设置器都有自己的验证器。这里还有另一个关于同一件事的讨论:stackoverflow.com/questions/15186202/…

标签: php oop design-patterns


【解决方案1】:

代码不多,就是乱七八糟。

可能问题是在一个地方有太多东西,将值对象中的属性“类型”分组,然后这些值对象中的每一个都会处理它们的“验证”

示例:

  • 高度、宽度、深度应为尺寸
  • 类型、品牌、型号、年份应按CarModel
  • 价格,价值应该去价格
  • ...

或类似的东西,你应该知道它们之间的关系

会导致:

function __construct(CarType $model, Size $size, Price $price, $seats)
{
    // no need to validade CarType did that
    $this->model = $model;
    ....
}

为了帮助创建对象,您可以使用工厂或构建器

【讨论】:

    【解决方案2】:

    为了检查值是否为整数,您可以在回调方式中使用 filter_var 或者您可以将数组作为参数传递并按以下方式使用 filter_var_array 函数, 以下是我的示例代码:

    $firstCar = new Car(1, 'Audi', 'A3', 2011, 94512, 2, 2, 2, 105, 'Black', 1000, 1920, 5);
    
    public function __construct($type ,$brand, $model, $year, $mileage, $height, $width, $depth, $ps, $color, $price, $value, $seats) {
    $arrInput = func_get_args();
    
    // this is enough to check only all arguments are integer or not by comparing the counts by input and filter array
    $arrFilter = array_filter(filter_var_array($arrInput,FILTER_VALIDATE_INT));
    
     if (count($arrFilter) < count($arrInput)) { // means there should be atleast one non-integer value
        // to get the exact values which are exaclty not interger
        $arrResult = array_diff($arrInput, $arrFilter);
        throw new('your error'); // or return $arrResult; // this return Audi, A3 and Black
     }
    
     }
    

    您可以根据需要使用 try/catch 通过从构造函数中抛出错误来捕获错误,或者通过从构造函数返回 $arrResult 来获取非整数的结果值。

    【讨论】:

      【解决方案3】:

      我以不同的方式解决了问题。

      $this->setType($type);
      
      protected function setType($worth)
      {
          if (is_int($worth)) {
              $this->_type = $worth;
          } else {
              throw new Exception('Wrong Value in Type. Expected valid integer');
          }
      }
      

      这对于我传递给类的每个参数。

      对于那些对此感兴趣的人。不是最好的解决方案,但它会缩短子类。

      【讨论】:

        【解决方案4】:

        假设,每个字段都必须是int

        ...
        
        private function checkArgument($arg) {
            if (is_int($type)) {
                $this->_type = $type;
            } else {
                throw new Exception('Wrong Value in Type. Expected integer');
            }
        }
        
        ...
        
        public function __construct($type ,$brand, $model, $year, $mileage, ...) {
            checkArgument($type);
            checkArgument($brand);
            ...
        }
        

        您也可以使用func_get_args(),获取数组中的所有参数,然后循环它们。

        【讨论】:

        • 看起来更好,但并不完美。没有更短的方法?
        • 我有整数、字符串、布尔值和浮点数。
        • 短:我不这么认为。更优雅,是的:Validator 接口,每种类型的实现(BooleanValidatorIntegerValidator,...)。将您的参数映射到验证器,遍历它们并验证每个参数。一个更优雅的版本是使用静态类型语言(如 HACK - 我不知道它有多成熟),并让解释器完成所有工作。
        猜你喜欢
        • 2012-05-25
        • 2012-05-09
        • 1970-01-01
        • 2023-03-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多