Differenze tra proxy e motivo decorativo


136

Puoi dare qualche buona spiegazione qual è la differenza tra Proxy e Decorator ?

La differenza principale che vedo è che quando assumiamo che Proxy usi la composizione e Decorator usi l' aggregazione , sembra chiaro che usando più (uno o più) Decoratori è possibile modificare / aggiungere funzionalità a istanze preesistenti (decorare), mentre Il proxy ha la propria istanza interna della classe proxy e ai delegati aggiunge alcune funzionalità aggiuntive (comportamento del proxy).

La domanda è: il proxy creato con aggregazione è ancora proxy o piuttosto Decorator ? È consentito (per definizione nei modelli GoF) di creare proxy con aggregazione?


2
Alcuni link: Proxy and Decorator
Sotirios Delimanolis,

5
Dove ti è venuta l'idea che Proxy utilizza la composizione e Decorator usa l'aggregazione?
CPerkins,

1
@CPerkins vede il mio commento per la risposta di Rahul Tripathi.
Łukasz Rzeszotarski,

1
E anche decoratore ( patterns.cs.up.ac.za/examples/ch2/decorator-theory.cs ) - ovviamente aggregazione, proxy ( patterns.cs.up.ac.za/examples/ch2/proxy-theory.cs ) - ovviamente composizione.
Hyankov,

Risposte:


17

Ecco la citazione diretta dal GoF (pagina 216).

Sebbene i decoratori possano avere implementazioni simili a quelle dei proxy, i decoratori hanno uno scopo diverso. Un decoratore aggiunge una o più responsabilità a un oggetto, mentre un proxy controlla l'accesso a un oggetto.

I proxy variano nella misura in cui sono implementati come un decoratore. Un proxy di protezione potrebbe essere implementato esattamente come un decoratore. D'altra parte, un proxy remoto non conterrà un riferimento diretto al suo soggetto reale ma solo un riferimento indiretto, come "ID host e indirizzo locale sull'host". Un proxy virtuale inizierà con un riferimento indiretto come un nome file, ma alla fine otterrà e utilizzerà un riferimento diretto.

Le risposte più diffuse indicano che un proxy conosce il tipo concreto del suo delegato. Da questa citazione possiamo vedere che non è sempre vero.

La differenza tra Proxy e Decorator secondo GoF è che Proxy limita il client. Decoratore no. Proxy può limitare quello che un cliente fa controllando l'accesso alla funzionalità; oppure può limitare ciò che un client conosce eseguendo azioni invisibili e sconosciute al client. Decorator fa il contrario: migliora ciò che fa il suo delegato in modo che sia visibile ai clienti.

Potremmo dire che Proxy è una scatola nera mentre Decorator è una scatola bianca.

La relazione di composizione tra wrapper e delegato è la relazione sbagliata su cui concentrarsi quando si contrappone Proxy con Decorator, perché la composizione è la caratteristica che questi due motivi hanno in comune. La relazione tra wrapper e client è ciò che differenzia questi due modelli.

  • Decorator informa e autorizza il suo cliente.
  • Il proxy limita e non autorizza il suo client.

114

La vera differenza non è la proprietà (composizione contro aggregazione), ma piuttosto informazioni di tipo.

A un decoratore viene sempre passato il suo delegato. Un proxy potrebbe crearlo lui stesso o potrebbe averlo iniettato.

Ma un proxy conosce sempre il (più) tipo specifico del delegato. In altre parole, il proxy e il suo delegato avranno lo stesso tipo di base, ma il proxy punta a un tipo derivato. Un decoratore indica il proprio tipo di base. Pertanto, la differenza sta nelle informazioni in fase di compilazione sul tipo di delegato.

In un linguaggio dinamico, se il delegato viene iniettato e sembra avere la stessa interfaccia, allora non c'è differenza.

La risposta alla tua domanda è sì".


2
"Ma un proxy conosce sempre il (più) tipo specifico di delegato." Non credo sia vero. Immagina un proxy remoto. Il meccanismo di proxy non ha bisogno di conoscere alcun dettaglio dell'oggetto remoto. Il sistema remoto registra l'oggetto con l'interfaccia specificata. E il proxy locale espone la stessa interfaccia.
Alexey,

3
Ho tenuto un corso su questo ad Amazon da un docente in visita che conosceva le sue cose. Esiste una differenza tra l'uso di un eseguibile "proxy" (ad esempio con un servizio Web) e il modello di progettazione proxy. Gli UML del modello Proxy e del modello Decorator possono essere diversi. Ma nulla impedisce a un proxy di avere la stessa API del suo delegato. Decorator è un sottoinsieme rigoroso di Proxy, ma un Decorator potrebbe ancora essere chiamato Proxy a seconda che l'API sottostante sia garantita la stessa.
cdunn2001,

85

Decorator Pattern si concentra sull'aggiunta dinamica di funzioni a un oggetto, mentre Proxy Pattern si concentra sul controllo dell'accesso a un oggetto.

MODIFICARE:-

La relazione tra un proxy e il soggetto reale viene in genere impostata al momento della compilazione, il proxy lo crea in qualche modo, mentre Decorator viene assegnato al soggetto in fase di esecuzione, conoscendo solo l'interfaccia del soggetto.


5
Tuttavia, è possibile utilizzare un proxy per aggiungere funzionalità. Pensa ai proxy AOP.
Sotirios Delimanolis,

5
Completamente d'accordo, signore. Vorrei convertire che in altre parole quello che volevo dire era con Proxy Pattern, la classe proxy può nascondere le informazioni di dettaglio di un oggetto dal suo client. Pertanto, quando si utilizza Proxy Pattern, di solito creiamo un'istanza di abject all'interno della classe proxy. E quando si utilizza il motivo Decoratore, in genere passiamo l'oggetto originale come parametro al costruttore del decoratore.
Rahul Tripathi,

In questo caso, quando l'istanza è "nascosta" nel proxy, la differenza è chiara per me (come ho scritto), tuttavia penso che spesso le persone chiamano come classi proxy che prendono l'oggetto proxy che è stato passato come parametro del costruttore. In questo caso la differenza nell'aggiungere nuove funzionalità o nel controllo è (molto) sottile per me.
Łukasz Rzeszotarski,

5
La relazione tra un proxy e il soggetto reale viene in genere impostata al momento della compilazione, il proxy lo crea in qualche modo, mentre Decorator o Adapter vengono assegnati al soggetto in fase di esecuzione, conoscendo solo l'interfaccia del soggetto. Spero che abbia un senso !!! :)
Rahul Tripathi,

1
Potresti aggiungere questa riga alla tua risposta.
Łukasz Rzeszotarski,

49

Il decoratore ottiene il riferimento per l'oggetto decorato (di solito tramite il costruttore) mentre il proxy è responsabile di farlo da solo.

Il proxy potrebbe non istanziare affatto l'oggetto di wrapping (come questo fanno gli ORM per impedire l'accesso non necessario al DB se non vengono utilizzati campi / getter di oggetti) mentre Decorator mantiene sempre il collegamento all'istanza di wrapping effettiva.

Proxy solitamente utilizzato dai framework per aggiungere sicurezza o memorizzazione nella cache / oziare e costruito dal framework (non dallo stesso sviluppatore normale).

Decorator di solito veniva utilizzato per aggiungere nuovi comportamenti a classi vecchie o legacy dallo stesso sviluppatore in base all'interfaccia piuttosto che alla classe effettiva (quindi funziona su un'ampia gamma di istanze di interfaccia, il proxy è intorno alla classe concreta).


22

Differenze chiave:

  1. Il proxy fornisce la stessa interfaccia. Decorator offre un'interfaccia migliorata.
  2. Decoratore e Proxy hanno scopi diversi ma strutture simili. Entrambi descrivono come fornire un livello di riferimento indiretto a un altro oggetto e le implementazioni mantengono un riferimento all'oggetto a cui inoltrano le richieste.
  3. Decoratore può essere visto come un composito degenerato con un solo componente. Tuttavia, un decoratore aggiunge ulteriori responsabilità: non è destinato all'aggregazione di oggetti.
  4. Decorator supporta la composizione ricorsiva
  5. La classe Decorator dichiara una relazione di composizione con l'interfaccia LCD (Lowest Class Denominator) e questo membro di dati viene inizializzato nel suo costruttore.
  6. Utilizzare il proxy per l'inizializzazione lenta, il miglioramento delle prestazioni memorizzando nella cache l'oggetto e controllando l'accesso al client / chiamante

L' articolo di Sourcemaking cita in modo eccellente somiglianze e differenze.

Domande / collegamenti SE correlati:

Quando utilizzare il motivo decorativo?

Qual è la differenza esatta tra i modelli Adapter e Proxy?


3

Proxy e Decorator si differenziano per scopo e dove si concentrano sull'implementazione interna. Il proxy è per l'utilizzo di un oggetto remoto, tra processi o tra reti come se fosse un oggetto locale. Decorator serve per aggiungere nuovi comportamenti all'interfaccia originale.

Mentre entrambi i modelli sono simili nella struttura, la maggior parte della complessità del proxy sta nel garantire comunicazioni adeguate con l'oggetto di origine. Decorator, d'altra parte, si concentra sull'implementazione del comportamento aggiunto.


Cosa stai dicendo che è diverso dalle altre 4 risposte già qui?
Stephen Rauch,

Non so se sia tutto lì. Ho appena sentito l'impulso di entrare dopo aver letto le risposte precedenti.
James Lin,

1

Ci è voluto un po 'per capire questa risposta e cosa significa veramente. Alcuni esempi dovrebbero renderlo più chiaro.

Proxy primo:

public interface Authorization {
    String getToken();
} 

E :

// goes to the DB and gets a token for example
public class DBAuthorization implements Authorization {
    @Override
    public String getToken() {
        return "DB-Token";
    }
}

E c'è un chiamante di questo Authorization, piuttosto stupido:

class Caller {
    void authenticatedUserAction(Authorization authorization) {
        System.out.println("doing some action with : " + authorization.getToken());
    }
}

Niente di insolito finora, giusto? Ottieni un token da un determinato servizio, usa quel token. Ora arriva un ulteriore requisito all'immagine, aggiungi la registrazione: significa che registri il token ogni volta. È semplice per questo caso, basta creare un Proxy:

public class LoggingDBAuthorization implements Authorization {

    private final DBAuthorization dbAuthorization = new DBAuthorization();

    @Override
    public String getToken() {
        String token = dbAuthorization.getToken();
        System.out.println("Got token : " + token);
        return token;
    }
}

Come lo useremmo?

public static void main(String[] args) {
    LoggingDBAuthorization loggingDBAuthorization = new LoggingDBAuthorization();

    Caller caller = new Caller();
    caller.authenticatedUserAction(loggingDBAuthorization);
}

Si noti che LoggingDBAuthorization contiene un'istanza di DBAuthorization. Entrambi LoggingDBAuthorizatione DBAuthorization attuare Authorization .

  • Un proxy conterrà alcune implementazioni concrete ( DBAuthorization) dell'interfaccia di base ( Authorization). In altre parole, un proxy sa esattamente cosa viene delegato.

Decorator:

Inizia praticamente come Proxycon un'interfaccia:

public interface JobSeeker {
    int interviewScore();
}

e una sua attuazione:

class Newbie implements JobSeeker  {
    @Override
    public int interviewScore() {
        return 10;
    }
}

E ora vogliamo aggiungere un candidato più esperto, che aggiunge il punteggio del colloquio più quello di un altro JobSeeker:

@RequiredArgsConstructor 
public class TwoYearsInTheIndustry implements JobSeeker {

    private final JobSeeker jobSeeker;

    @Override
    public int interviewScore() {
        return jobSeeker.interviewScore() + 20;
    } 
}

Notate come ho detto che più quello di un altro cercatore di lavoro , no Newbie . A Decoratornon sa esattamente cosa sta decorando, conosce solo il contratto di quell'istanza decorata (lo sa JobSeeker). Prendi nota che questo è diverso da a Proxy; che, al contrario, sa esattamente cosa sta decorando.

Potresti chiederti se c'è davvero qualche differenza tra i due modelli di design in questo caso? E se provassimo a scrivere Decoratorcome Proxy?

public class TwoYearsInTheIndustry implements JobSeeker {

    private final Newbie newbie = new Newbie();

    @Override
    public int interviewScore() {
        return newbie.interviewScore() + 20;
    }
}

Questa è sicuramente un'opzione ed evidenzia quanto vicini siano questi schemi; sono ancora intesi per diversi scenari come spiegato nelle altre risposte.


1

Proxy fornisce la stessa interfaccia all'oggetto spostato, Decorator fornisce un'interfaccia migliorata e Proxy di solito gestisce da solo il ciclo di vita dell'oggetto di servizio, mentre la composizione di Decoratori è sempre controllata dal client.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.