Commuta l'implementazione dell'interfaccia usando la configurazione [chiusa]

3

Vogliamo consentire allo stesso servizio di base di essere pienamente implementato o, come opzione, di essere un proxy verso un sistema legacy client (tramite un WSDL per esempio).

In questo modo, abbiamo sia l'implementazione (proxy e pieno) che l'altro da utilizzare nella configurazione dell'app.

Quindi, in poche parole, alcune funzionalità desiderate:

  • Due diverse implementazioni (proxy, complete) invece di un'implementazione con un passaggio all'interno
  • Cambia implementazione usando la configurazione: dipendenza da iniezione? riflessione?
  • Nice-to-have: il pacchetto consegnato al client non deve cambiare a seconda della scelta tra proxy o completo
  • Nice-to-have: il cliente può sviluppare la sua implementazione personalizzata dell'interfaccia principale e configurare l'applciation per usarlo

In questo contesto, la domanda è: quali alternative dobbiamo scegliere una implementazione o un'altra interfaccia cambiando semplicemente configurazione?

Grazie

    
posta Marcos 17.12.2012 - 15:41
fonte

4 risposte

5

Un contenitore IoC che carica la sua configurazione da un file di configurazione xml può farlo.

Se stai usando java puoi usare spring-ioc per questo.

Il file di configurazione java per il servizio completo potrebbe contenere questo

<bean id="catalogService" class="com.mycompany.myproduct.MyFullCatalogService" scope="singleton" />

Se si desidera utilizzare la versione proxy

<bean id="catalogService" class="com.mycompany.myproduct.MyProxyCatalogService" scope="singleton" />

La tua applicazione principale chiede al contenitore id="catalogService" per ottenere il servizio corrente.

    
risposta data 17.12.2012 - 16:15
fonte
3

Usiamo questo modello al lavoro:

Production config.properties:
serviceClass=com.mycompany.LiveService

Development config.properties:
serviceClass=com.mycompany.MockService

spring.xml:
<bean id="service" class="${serviceClass}"/>
(with the appropriate property configurer)

Prova anche questo. Mi piace di più, perché non finisci con il mettere i nomi delle classi nella configurazione, che credo dovrebbe parlare a un diverso livello di astrazione.

Production config.properties:
environment=production

Dev config.properties:
environment=development

<bean id="service" class="com.mycompany.ServiceSelector">
    <property name="environment" value="${environment}"/>
    <property name="liveService" ref="liveService"/>
    <property name="mockService" ref="mockService"/>
</bean>

// a proxy that decides on the class to "let through" based on the environment
class ServiceSelector {
    public void setLiveService(Service liveService) {
        this.liveService = liveService;
        updateCurrentService();
    }

    public void setMockService(Service mockService) {
        this.mockService = mockService;
        updateCurrentService();
    }

    public void setEnvironment(Environment environment) {
        this.environment = environment;
        updateCurrentService();
    }

    private void updateCurrentService() {
        if (environment == null) {
            currentService = null;
            return;
        }
        switch (environment) {
            case production:
                currentService = liveService;
                break;
            case development:
                currentService = mockService;
                break;
            default:
                throw new IllegalStateException();
        }
    }
}

Se hai un numero sufficiente di servizi in questa situazione, puoi mettere tutti questi servizi sotto una facciata e implementare un selettore di facciata invece di molti selettori di servizio.

Un'altra variante consiste nel buttare via il file di configurazione e fornire il flag di ambiente nell'ambiente stesso. Potrebbe essere una proprietà JVM definita con -Dname=value quando viene invocata la JVM, ecc.

    
risposta data 28.01.2013 - 03:02
fonte
0

Entrambi injection depend e abstract factory sono perfetti per questo. Hai due implementazioni di un'interfaccia IService dove uno è l'implementazione stessa e un altro è proxy. Dipende dalla configurazione effettiva che puoi iniettare o costruire l'una o l'altra. L'implementazione usando fabbrica astratta è molto più semplice: tutta la logica per determinare cosa costruire è all'interno della fabbrica. Per ottenere ciò con injection injection potresti iniziare con Root di composizione , successivamente definire la configurazione per la creazione dell'istanza (completa o proxy). Questo è molto più difficile da un modo flessibile per ottenere il comportamento richiesto.

    
risposta data 17.12.2012 - 16:03
fonte
0

Dipende da come lo vuoi fare.

  • Il pattern Proxy ti consente di passare internamente all'implementazione senza esporre i dettagli a qualsiasi altra cosa nella tua applicazione. Quindi è possibile in qualsiasi momento passare all'implementazione senza lasciare che qualcos'altro nel codice sia a conoscenza dello switch.

  • Modello di fabbrica: lascia che la fabbrica decida quale implementazione creare (usando un file di configurazione o argomenti di fabbrica). A differenza del proxy, non è possibile passare all'implementazione una volta che una classe ha ricevuto un oggetto creato.

risposta data 17.12.2012 - 16:04
fonte

Leggi altre domande sui tag