Si tratta di un buon servizio di localizzazione, ed è questo il modello di localizzazione del servizio (?) OK?

0

Sto lavorando in Zend framework 1 e stavo usando Zend_Registry per archiviare gli oggetti in modo che potessi sostituirli nei miei controller mentre test delle unità:

$auth = Zend_Registry::get('Auth'); // set in Bootstrap.php

Volevo memorizzare le chiusure che potevano essere eseguite quando erano richieste (piuttosto che tutte durante Booostrtap anche se non erano utilizzate in quella richiesta), ma il Registro non sembra farlo. Immagino che prima delle 5.3 non ci fossero chiusure?

Quindi, ho creato la mia classe di localizzatore di servizi. Ho pensato di estendere Zend_Registry ma preferisco avere qualcosa che possa essere usato al di fuori di ZF1, in più è piuttosto semplice in ogni caso:

<?php

class App_Services
{
    /**
    * @var array $container will store our services
    */
    private $container = array();

    /**
    * Returns the *Singleton* instance of this class.
    *
    * @staticvar Singleton $instance The *Singleton* instances of this class.
    *
    * @return Singleton The *Singleton* instance.
    */
    public static function getInstance()
    {
        static $instance = null;
        if (null === $instance) {
            $instance = new App_Services();
        }

        return $instance;
    }

    /**
    * Get a service from the container
    * 
    * @param string $name Index of the service in container
    * @return various Service
    */
    public function get($id)
    {
        $instance = self::getInstance();

        // if not set, return null
        if (! isset($instance->container[$id]))
            return null;

        // if a closure, call it and return the return value
        if ($instance->container[$id] instanceof \Closure) {
            $instance->container[$id] = $instance->container[$id]();
            return $instance->container[$id];
        }

        return $instance->container[$id];
    }

    /**
    * Set a service in the container
    * 
    * @param string $id Name (index) of the service in container
    * @param string $service Service to store
    */
    public function set($id, $service)
    {
        $instance = self::getInstance();

        $instance->container[$id] = $service;
    }
}

.. e su Bootstrap posso fare:

$auth = App_Services::set('Auth', function() {
    return new Auth();
});

.. quindi entro le azioni del mio controller che posso fare:

$auth = App_Service::get('Auth');

.. come prima.

In ogni caso, si tratta di una buona implementazione di un localizzatore di servizi? Inoltre, questo o Zend_Registry può essere utilizzato come un localizzatore di servizi? Mi piacerebbe capire meglio il pattern mentre leggo che il pattern di localizzatore di servizi è una buona idea, poi ho letto che è un pattern anti, ma penso che alcune volte dipenda da come sono implementati i pattern che rendono poi buoni pattern o anti pattern. Apprezzerei qualsiasi consiglio su questo, grazie.

    
posta Martyn 13.02.2015 - 11:31
fonte

1 risposta

2

Vorrei cambiare alcune cose:

  1. rimuovi singleton, crea private static $container = [] ad ogni modo stai usando solo metodi statici per recuperarlo.
  2. prendi in considerazione l'ipotesi di generare un'eccezione speciale quando ricevi il servizio non impostato.
  3. ri-considerare la cache automatica per i servizi (è possibile che tu non la desideri per ogni servizio)

Considerando la discussione modello / anti-pattern che ho trovato per lo più citato, questo articolo: link che è riassunto:

Let's examine why this is so. In short, the problem with Service Locator is that it hides a class' dependencies, causing run-time errors instead of compile-time errors, as well as making the code more difficult to maintain because it becomes unclear when you would be introducing a breaking change.

Quindi fondamentalmente non ti riguarda: tutti i tuoi errori sono errori di run-time in PHP. (Oppure errore di run time di unitTests se sei intelligente: D).

In ogni caso puoi trasformare ogni schema nella sua anti-versione quando lo usi eccessivamente. Pensa ogni volta se qualche tipo di dipendenza (DI) o altra Inversion of Controll (IoC) ti sta meglio.

    
risposta data 20.02.2015 - 17:23
fonte