如何以良好的方式创建不同类的新实例?

时间:2014-11-07 13:21:35

标签: php object

我有一个类,更具体的一个存储库。这个存储库将保存我的验证器,以便我可以随时访问它们。目前它看起来像这样:

class ValidatorRepository {
     private $validators; 

     public function __construct() {
          $this->validators = array();
     }

     public function get($key) {
          return $this->validators[$key];
     }

     public function add($key, iValidator $value) {
          $this->validators[$key] = $value;
     }
     public static function getInstance() {
           //(...)
     }
}

通过这门课,我想做这样的事情:

$vr = ValidatorRepository::getInstance(); 
$vr->add("string", new StringValidator()); 

如果更好的话,我可以插入除实例化对象之外的其他内容。

..以及之后的其他地方;

$vr = ValidatorRepository::getInstance(); 
$vr->get("string"); // should return a *new* instance of StringValidator.

这个想法是ValidatorRepository在添加这些类之前不应该知道这些类。只要我返回当前对象,这样就可以了。

但我想要一个类的 new 对象。我可以通过在每个验证器中放置一个静态getInstance()函数,或者以某种方式使用eval,但我希望可能有另一种不那么丑陋的方式。

2 个答案:

答案 0 :(得分:1)

我相信你应该能够做这么简单的事情:

public function add( $key, iValidator $value ) {
    $this->validators[ $key ] = get_class( $value ); // this call can be moved to get() if you wish
}

public function get( $key ) {
    return new $this->validators[ $key ];
}

get_class()考虑​​了名称空间,所以如果你使用名称空间,那么它仍然可以。


稍微灵活一点的方法可能就是:

public function add( $key, iValidator $value ) {
    $this->validators[ $key ] = $value;
}

public function get( $key, $new = true ) {
    if ($new) {
        $class = get_class( $this->validators[ $key ] );
        $class = new $class;
    } else {
        $class = $this->validators[ $key ];
    }

    return $class;
}

答案 1 :(得分:1)

你应该使用的是继承:

abstract class Validated {

    public function validate(){
        foreach(self::VALIDATIONS as $val) {
            // ...
        }
    } 
}

class Person extends Validated {

    protected $name;

    const VALIDATIONS = array(
       'name' => array( 'length' => new LengthValidator(15) )
    ); 
}

或特征:

trait Validated {
    function validate(){
        // ...
    }
}

class Person {
    use Validated;
}

将所有验证逻辑推送到单个类中会违反single responsibly principle,因为它负责验证使用它的所有类。它很快就会失控。

请注意,我已使用常量进行验证 - 您很少需要在运行时更改类的验证规则。