2016-05-04 7 views
1

У меня есть Factory Method для экземпляра класса. Есть ли способ предотвратить прямое наведение этого класса?Метод фабрики: Предотвращение класса из Direct Instancing

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

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

Что вы, ребята, думаете?

Factory Method:

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

MyClass:

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

Первый; определение MyClass должно быть пересмотрено: ** класс MyClass() {** должен читать ** класс MyClass {** без **() ** после класса MyClass ... ;-) – Poiz

+0

@Poiz thanks, didn Не обращай внимания на эту опечатку. Исправлено сейчас. –

+0

Каков ваш прецедент? – PeeHaa

ответ

2

Есть писаки, чтобы сделать это:

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

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

+0

Согласен. Трудно исправить глупость. В какой-то момент вам просто нужно отпустить это. – PeeHaa

+0

Спасибо, Маркус, полностью согласен с тобой о хаках. –

1

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

ФАБРИКА

<?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 
+0

Спасибо, что сообщили мне. Однако это не вопрос, который я задаю. –

+0

Я обновил код ... вы можете взглянуть на него ... (если хотите) ;-) – Poiz

+0

Это тоже не сработает. Рассмотрим после '$ theClass = Factory :: instance (« MyClass »);' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ' –