È una cattiva pratica per un decoratore interrompere la catena decorativa?

6

Attualmente sto usando decoratori per applicare varie modifiche a un modello prima di renderlo.

Tuttavia, non sono sicuro del mio decoratore di cache, perché attualmente è in grado di rompere la catena di decoratori e restituire un oggetto memorizzato nella cache anziché l'oggetto decorato originale.

class Cache : Decorator
{
    public String Render()
    {
        if(templateCache.IsCached('some_template_identifier'))
        {
            return templateCache.Get('some_template_identifier');
        }
        String renderedTemplate = Template.Render();
        templateCache.Cache(renderedTemplate);
        return renderedTemplate;
    }
}

Questa cattiva pratica è questa? Dovrei sempre restituire l'oggetto decorato originale o è giusto interrompere il flusso in questo modo e restituire un oggetto diverso?

    
posta Sam Hastings 29.02.2012 - 21:34
fonte

3 risposte

3

Questo non sembra spezzarmi alcuna catena.

L'intento del decoratore è che il codice chiamante dovrebbe essere in grado di eseguire il rendering della stringa in modo corretto, se è in possesso dell'oggetto Template o memorizzato nella cache se contiene l'oggetto memorizzato nella cache. Non dovrebbe sapere o preoccuparsi di quanti oggetti sono avvolti attorno all'oggetto di base. Il codice chiamante dovrebbe semplicemente chiamare Render e gestire ciò che ottiene.

La rottura della catena si verificherebbe se il metodo Render del tuo modello avesse una firma diversa dal metodo di rendering memorizzato nella cache, in modo che il codice chiamante dovesse sapere di cosa si tratta.

Tutto ciò detto, anche io non credo che questo sia, per definizione, un modello Decorator.

I decoratori tendono a decorare qualsiasi cosa stiano rendendo, piuttosto che cambiare da dove prende quella stringa. Quindi potresti aver avuto un QuotesWrapper e un LCaseWrapper in modo che se il tuo Template restituisce Hello World! , potresti avvolgerlo in QuotesWrapper per ottenere "Hello World!" o LCaseWrapper per ottenere hello world! o entrambi per ottenere "hello world!" . Per tutto il tempo, il codice chiamante non interessa.

Quello che stai facendo è simile ma non uguale. In nessun modo stai decorando qualcosa. Se mai, è più simile a un proxy, almeno in termini di AOP.

    
risposta data 01.03.2012 - 00:25
fonte
2

No, non credo che un decoratore debba mai interrompere la catena . In sostanza, se Decoratore non decora , non è un Decoratore . * 8' )

Così com'è, non sono sicuro di quale comportamento stavi aspettando di mostrare un decoratore memorizzato nella cache . Suggerirei che un Decoratore cache dovrebbe memorizzare nella cache le decorazioni su un oggetto e non su un oggetto decorato stesso.

In questo modo, quando sposti un oggetto nel tuo decoratore cache , decora l'oggetto con lo stesso set di decorazioni che il tuo oggetto modello ha / avuto.

    
risposta data 01.03.2012 - 15:28
fonte
1

Suppongo, cosa intendevi quando hai detto "Breaking the decorator chain"="Stai scartando l'oggetto passato a" class Cache "e restituendo il tuo

Che tecnicamente non è corretto fare e dovrebbe essere evitato, perché

1) Decorator è un modello strutturale, che modifica la struttura in modo dinamico. Il caching non ha lo stesso scopo di un decoratore, vedi qui il problema fondamentale?

2) Decorator aggiunge / modifica qualcosa all'oggetto seed passato ad esso prima di restituirlo, facendo cache non si aggiunge nulla ad esso

Come risolvere questo allora? le opzioni sono 1 - Assicurati che l'oggetto sia preso dalla cache prima di chiamare la catena di decoratori e applicarla inserendola nel tuo metodo di recupero dei dati

2 - Avere un altro livello di ereditarietà (anche se non lo consiglio) prima di tutti questi decoratori, in cui tutti i modi cercano di ottenere l'oggetto dalla cache, prima di chiamare un metodo virtuale del metodo del decoratore derivato a Render ( )

questo è il mio 2 centesimi

~ Basav

    
risposta data 01.03.2012 - 15:49
fonte

Leggi altre domande sui tag