Как я могу создать новые экземпляры разных классов хорошим способом?

0

У меня есть класс, более конкретный репозиторий. В этом хранилище будут храниться мои валидаторы, чтобы я мог связаться с ними, когда захочу. В настоящее время это выглядит так:

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 НЕ должен знать о классах до их добавления. Это работает нормально, пока я возвращаю текущий объект.

Но вместо этого мне нужен новый объект класса. Я мог бы это сделать, поставив статическую функцию getInstance() в каждом валидаторе или каким-то образом использовать eval, но я надеюсь, что может быть другой, менее уродливый способ.

Теги:
object

2 ответа

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;
}
  • 0
    Спасибо, приятель, похоже, решил мою проблему на месте!
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;
}

Перемещение всей логики проверки в один класс нарушает принцип единого ответственно, поскольку он ответственен за проверку всех классов, которые его используют. Он быстро выйдет из-под контроля.

Обратите внимание, что я использовал константу для проверки - вам редко приходится менять правила проверки для класса во время выполнения.

  • 0
    Привет, спасибо за твой отличный совет! Я определенно буду реализовывать это позже, в настоящее время существует очень ограниченный набор валидаторов и вещей, которые должны быть проверены, но, как вы говорите, одиночные клавиши считаются анти-паттернами.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню