2016-05-04 5 views
1

verhindern Ich habe eine Factory Method, um eine Klasse zu instanziieren. Gibt es eine Möglichkeit, diese Klasse von direkter Instanziierung abzuhalten?Factory-Methode: Eine Klasse von Direct Instancing

Die einzige Option, die ich sehe, ist ein Argument in die __construct() übergeben, aber das ist nicht etwas, das ich suche.

Auf der anderen Seite wäre die __construct() private wäre ideal, aber ich möchte nicht MyClass die Factory ohne tatsächlichen Bedarf zu erweitern.

Was denkst du?

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

Zuerst; Die Definition von MyClass sollte noch einmal überarbeitet werden: ** class MyClass() {** sollte ** class MyClass ** ohne **() ** nach dem class MyClass lesen ;-) – Poiz

+0

@Poiz danke, didn bemerke diesen Tippfehler nicht. Jetzt korrigiert. –

+0

Was ist Ihr Anwendungsfall? – PeeHaa

Antwort

2

Es gibt Hacks zu tun, dass:

  • Erbe zu missbrauchen einen protected Konstruktor verwenden
  • die Factory-Methode innerhalb der Klasse setzen, so dass es den privaten Konstruktor aufrufen können, die eigentlich nicht ist ein Hack. Aber warum nicht den Konstruktor überhaupt benutzen?
  • Reflexion mit dem privaten Konstruktor zugreifen

ich nichts davon zu fördern. Was ich persönlich mache, ist die API mit Dingen wie @internal zu dokumentieren und sie dem Kunden nach diesem Vertrag zu überlassen.

+0

Ich stimme zu. Es ist schwer, dumm zu machen. Irgendwann musst du es einfach gehen lassen. – PeeHaa

+0

Danke Markus, stimme völlig mit dir überein Hacks. –

1

Im Wesentlichen sollten Sie Ihren Code so etwas wie dieses gelesen haben:

DIE FABRIK

<?php 
    class Factory { 

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

DER KLASSE WERDEN ÜBER DIE FABRIK instanziiert

 <?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 
    } 

Könnten Sie diese stattdessen versuchen?

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

Danke, dass Sie mich wissen lassen. Das ist jedoch nicht die Frage, die ich stelle. –

+0

Ich habe den Code aktualisiert ... du könntest ihn dir anschauen ... (wenn du willst) ;-) – Poiz

+0

Das wird auch nicht funktionieren. Betrachte nach '$ theClass = Factory :: instance (" MyClass ");' die Zeile '$ theClass = new MyClass();' wird funktionieren! –