2013-08-27 8 views
1

J'ai une classe qui contient une propriété privée qui est utilisé dans un grand nombre de méthodes de classes:Constructor alternative pour ce scénario

class MyClass 
{ 
    private $_myProperty; 

    public function __construct($myPropertyId) 
    { 
     $this->_initMyPropertyModel($myPropertyId); 
    } 

    public function initMyPropertyModel() 
    { 
     $this->_myProperty = new MyProperty($this->_myPropertyId); 
    } 

    public function methodA() 
    { 
     // do stuff with $this->_myProperty; 
    } 

    public function methodA() 
    { 
     // do stuff with $this->_myProperty; 
    } 

    public function methodC() 
    { 
     // do stuff with $this->_myProperty; 
    } 
} 

Le consructor prend un id pour un modèle et tente ensuite d'instancier un modèle de cet id. Le modèle est défini en tant que propriété, puis utilisé dans toutes les autres méthodes de classe. Le problème avec ceci est que l'instation du modèle peut mal tourner et que le modèle n'est pas correctement instancié, donc il y a un problème potentiel dans chaque méthode qui l'utilise.

Existe-t-il une meilleure façon de gérer ce code? Les deux autres options que je vois sont: 1. Forcer les clients à passer le modèle créé au lieu de l'ID 2. Avoir une vérification de null dans chaque méthode qui utilise le modèle 3. Lancez une exception du constructeur s'il n'est pas instancié correctement Mais je ne pense pas que ce soit du tout souhaitable.

Répondre

1

Dans ce scénario, vous décrivez que j'utiliserais injection de dépendance (DI) pour que le code soit plus flexible, gérable et stable.
Fondamentalement, vos méthodes A B et C dépendent du modèle de propriété approprié, donc la vérification de null doit être évitée.
Lancer des exceptions est toujours un bon choix car il explique ce qui est mal fait. Avec DI au lieu de faire classe via le constructeur et/ou initMyPropertyModel() méthodes responsables de la création de modèles appropriés (étroitement couplés), un processus externe devrait être responsable de cela. Votre constructeur ne devrait dépendre de l'interface modèle:

class MyClass { 
    // do not use private visibility unless you are sure it really needs to be private 
    protected $_myProperty; 

    // we dont care about the concrete object as long as it follows the required interface 
    public function __construct(MyPropertyInterface $property) 
    { 
     $this->_myProperty = $property; 
     $this->_myProperty->initProperty(); // thanks to interface, MyClass can be sure this method can be called! 
    } 
    //... more class code 
} 

interface MyPropertyInterface 
{ 
    public function initProperty(); 
} 

class MyProperty implements MyPropertyInterface 
{ 
    public function initProperty() 
    { 
     echo 'MyProperty initiated!'; 
    } 
} 
class MyProperty2 
{ 
    public function initProperty() 
    { 
     echo 'MyProperty initiated!'; 
    } 
} 

Exemple d'utilisation:

$myObj = new MyClass(new MyProperty()); // works 
$myObj2 = new MyClass(new MyProperty2()); // Catchable fatal error 

Il n'a pas vraiment d'importance si les deux objets de propriété ont les mêmes metods si elles ne mettre en œuvre même interface. De cette façon, vous obligez les clients à utiliser MyClass de la façon dont il est censé être utilisé, ne vous souciez jamais de transmettre de mauvais paramètres avec lesquels votre objet ne peut pas fonctionner.

Bien sûr, il appartient aux clients en utilisant vos classes pour vérifier correctement les objets donc pas des erreurs se produisent:

$prop2 = new MyProperty2(); 
if ($prop2 instanceof MyPropertyInterface) { 
    $myObj2 = new MyClass(new MyProperty2()); 
} else { 
    // throw exception, show error, w/e 
} 
Questions connexes