Come si chiama un "Proxy" che delega a * diverse * implementazioni?

4

In un proxy GoF tradizionale, si dispone di un'interfaccia, un'implementazione che implementa l'interfaccia e un proxy che implementa anche l'interfaccia, fa riferimento a un'istanza di implementazione e delega le chiamate sui metodi dell'interfaccia agli stessi metodi in l'istanza di implementazione.

Supponiamo che chiamerai la coppia Interfaccia / Implementazione come un "frammento" e ne avresti diverse diverse. Ora immagina di creare un'intera interfaccia che implementa tutte le interfacce Fragment e un singolo proxy intero che ha implementato l'Interfaccia intera e che è stata delegata all'istanza di Implementazione frammento appropriata.

Esempio di codice (Java):

// Fragment A:
interface FragmentA { ... }
class FragmentAImpl implements FragmentA { ... }
// Whole A. That is the interface that "clients use"
interfaces WholeA extends FragmentA { // EMPTY! }
// *automatically generated* Proxy:
class ProxyA implements WholeA {
    private FragmentA implA;
    // Implements FragmentA through delegation to implA
}

// Fragment B:
interface FragmentB { ... }
class FragmentBImpl implements FragmentB { ... }
// Whole B. That is the interface that "clients use"
interfaces WholeB extends WholeA, FragmentB { // EMPTY! }
// *automatically generated* Proxy:
class ProxyB extends ProxyA implements WholeB {
    private FragmentB implB;
    // Implements FragmentB through delegation to implB
}

// Fragment C: similar to Fragment B, but with different *added behavior*.

Questo modello è (dato che i Pattern devono essere una soluzione comune ai problemi comuni)? E se sì, come ha un nome? O potrebbe essere definito chiaramente come una combinazione di modelli?

Essere in grado di descrivere chiaramente come funziona questo codice in termini di pattern renderebbe molto più facile spiegare agli altri come creare codice compatibile e aiutare a trovare un framework che già implementa questo pattern.

Un Proxy normalmente delegati a una singola istanza .

Un Facade normalmente offre una diversa interfaccia a quel più oggetti che nasconde.

Un Bridge offre anche una diversa interfaccia a quella singola istanza che nasconde.

Un Composito si aspetta che tutti i componenti condividano la stessa interfaccia di base .

Un Decoratore estende l'interfaccia dell'oggetto avvolto, come qui, ma normalmente implementa la funzionalità aggiuntiva stessa , invece di delegare a un altro oggetto.

Un intero che implementa un singolo frammento è solo un pattern Proxy, ma un intero che estende un altro è più vicino a un pattern Decorator.

Ci sono diversi motivi per farlo in questo modo. In primo luogo, il codice client dovrebbe vedere WholeB come estensione di WholeA, sebbene l'implementatore di FragmentB non possa estendere FragmentA (che è stato implementato da qualcun altro). In secondo luogo, i riferimenti a WholeX (ProxyX) rimangono validi, anche se l'implementazione di FragmentX viene sostituita da un runtime. In terzo luogo, sia ProxyB che ProxyC possono condividere la stessa istanza di FragmentAImpl.

    
posta Sebastien Diot 17.09.2011 - 12:01
fonte

3 risposte

7

Vorrei ancora andare con la facciata.

Offre una singola porta di chiamata per i clienti che necessitano dei servizi di diverse interfacce. Questa è una facciata. Il fatto che normalmente una facciata dichiari un'interfaccia specifica invece di riutilizzare quelli delle classi / oggetti che aggrega è, per me, un dettaglio di implementazione.

Aggiorna

Dal libro GoF:

Intent: Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystems easier to use.

Specialmente quando leggi

Motivation: Structuring a system into sybsystems helps reduce complexity. A common design goal it to minimize the communication and dependencies between subsysems. One way to achieve this goal is to introduce a facade object that provides a single, simplified interface to the more general facilities of a subsystem.

Mentre il commento di @pdr sembra corretto, vorrei discutere in modo diverso.

L'interfaccia "semplificata" può certamente essere la stessa delle interfacce poste dietro la facciata. È solo una questione di quanto siano semplici quelle interfacce "facades".

Inoltre, non prendo "semplifica" come requisito per un oggetto come facciata.

La motivazione a ridurre al minimo la comunicazione e le dipendenze tra i sottosistemi è molto più importante e l'obiettivo principale del modello di facciata. Una facciata oggetto che fornisce un singolo punto di accesso a più sottosistemi (immutati interfacce di), soddisfa comunque questo obiettivo indipendentemente dal fatto che (anche) semplifichi l'interfaccia o le interfacce offerte dai sottosistemi che nasconde.

    
risposta data 17.09.2011 - 12:17
fonte
6

Un mediatore? Oppure multiplexer inverso?

In ogni caso, non c'è motivo di attenersi dogmaticamente agli stessi schemi in GoF. Quel libro dovrebbe espandere il tuo vocabolario professionale e forse anche insegnarti qualche buona idea, ma non sono i dieci comandamenti del programmatore.

Non ho potuto vedere qui una ragione per utilizzare effettivamente il pattern Proxy, in teoria.

Avere un'interfaccia / implementazione separate è molto buono, ma ciò non significa che debba agire come un proxy. Se vuoi un nome, etichettalo come "liberamente accoppiato".

Puoi chiamarlo qualsiasi nome che abbia senso. Non devi cercare di trovare un nome standard quando non è del tutto ovvio.

In generale, trovo che l'intero modo dogmatico di creare codice pulito a volte sia deviato dallo scopo originale - creare codice che sia facile da leggere e capire.

Se non riesci a trovare un nome completamente standard per quello che stai facendo, non provare a trasformarlo in uno schema o nome esistente. Questo confonde solo gli altri programmatori.

Dagli solo uno nuovo che abbia senso per te e per i tuoi colleghi programmatori. Consulta insieme, nel tuo posto di lavoro - dove è importante.

    
risposta data 17.09.2011 - 12:23
fonte
2

Non tentare di separare i modelli di progettazione dai relativi dettagli di implementazione. Fare ciò causerà grande confusione quando verrai in Strategia e Stato, o ti costringerai a complicare eccessivamente le cose per evitare di avere argomenti sul metodo Execute di un comando.

Separare i modelli di progettazione dal loro intento. Per prendere i cinque esempi:

Un Proxy è una classe che crea un'interfaccia per qualcosa di costoso, che non è facilmente duplicato, come una connessione di rete o una grande porzione di memoria. * vedi commenti

Una facciata è una semplificazione di un'API complicata. Ridurre la superficie, come si dice; rendendolo più semplice da usare.

Un bridge è il punto in cui un'astrazione viene disaccoppiata dall'implementazione, così che quando l'implementazione cambia, il codice chiamante non deve. Inizialmente, l'interfaccia non deve essere diversa, come hai suggerito, non puoi semplicemente insistere che restino uguali.

Un Composito è per prendere più oggetti e avvolgerli in una sola astrazione.

Un decoratore consente agli oggetti di essere avvolti in oggetti con la stessa interfaccia, in modo da aggiungere funzionalità senza modificare il codice chiamante.

È difficile capire dal tuo esempio che stai cercando di implementare, perché hai descritto l'implementazione e non l'intenzione. Ma suppongo che il modello Proxy sia appropriato.

    
risposta data 17.09.2011 - 17:57
fonte

Leggi altre domande sui tag