Фабричный метод: предотвратить класс от прямого инстансинга

у меня есть Factory Method чтобы экземпляр класса. Есть ли способ предотвратить прямое создание экземпляров этого класса?

Единственный вариант, который я вижу, это использовать аргумент, переданный в __construct(), но это не то, что я ищу.

С другой стороны, делая __construct() личное было бы идеально, но я не хочу MyClass продлить Factory без фактической необходимости.

Что, вы парни, думаете?

Заводской метод:

class Factory
{
public static function instance()
{
return new MyClass(true);
}
}

Мои занятия:

class MyClass
{
public function __construct($isFactory = false)
{
if (!$isFactory) {
throw new Exception('Use Factory::instance() to create an object');
}
}
}

1

Решение

Для этого есть хаки:

  • злоупотребляя наследством, чтобы использовать protected конструктор
  • поместить фабричный метод внутри класса, чтобы он мог вызывать приватный конструктор, что на самом деле не является хаком. Но тогда почему бы вообще не использовать конструктор?
  • используя отражение для доступа к приватному конструктору

Я не продвигаю ничего из этого. Что я лично делаю, так это документирую API с такими вещами, как @internal и оставьте это клиенту после того контракта.

2

Другие решения

По сути, ваш код должен был прочитать что-то вроде этого:

ФАБРИКА

    <?php
class Factory {

public static function instance(){
return new MyClass(true); //HERE YOU ARE INSTANTIATING
}
}

КЛАСС, КОТОРЫЙ БУДЕТ ИНСТАНЦИРОВАНО С ЗАВОДА

     <?php
//NOT MyClass() <--- YOU ARE DEFINING.... NOT INSTANTIATING...
class MyClass {

public function __construct($isFactory = false) {
if (!$isFactory) {
throw new Exception('Use Factory::instance() to create an object');
}
}

//...MORE METHODS
}

Не могли бы вы попробовать это вместо этого?

    <?php
class Factory
{
private static $FACTORY_GUARANTOR;      //ONLY SET DURING INSTANTIATION
public static function instance($type) {
if (class_exists($type)) {
self::$FACTORY_GUARANTOR = 1;
$instance = new $type();
self::$FACTORY_GUARANTOR = null;
return $instance;
}
else {
throw new Exception("Class not found...");
}
}

//YOU CAN GET $FACTORYGUARANTOR EXTERNALLY BUT NEVER SET IT;
public static function getGuarantor(){
return self::$FACTORY_GUARANTOR;
}
}class MyClass {
protected $property1;
protected $property3;
protected $property2;

public function __construct() {
// IF SOMEONE TRIES TO INSTANTIATE THE CLASS OUTSIDE OF THE FACTORY... BLOW A WHISTLE
if(!Factory::getGuarantor()){
throw new Exception('Use Factory::instance() to create an object');
}
// IF THE PROGRAM MADE IT TO THIS POINT;
// JUST INSTANTIATE THE CLASS BECAUSE MOST LIKELY IT IS COMING FROM THE FACTORY
var_dump($this); // A LITTLE CONFIRMATION....
}

//...MORE METHODS
}

// TRY IT OUT:
/*INSTANCE A: RIGHT*/   $theClass   = Factory::instance("MyClass"); //INSTANTIATES THE CLASS
/*INSTANCE B: WRONG*/   $theClass   = new MyClass();                //THROWS AN EXCEPTION
1

По вопросам рекламы [email protected]