Implementare strategie di strategia multiple variabili?

2

Sto cercando di implementare Strategy Pattern per gestire la serializzazione e la deserializzazione del contenuto. Quindi ho quattro tipi di richieste, ovvero CREA, RECUPERA, AGGIORNA, ELIMINA e per ogni richiesta desidero serializzare / deserializzare il contenuto della richiesta e della risposta.

public interface ContentHandler{

    String serializeRequest(Content con)();
    String serializeResponse(Content con)();

    Content deserializeRequest(String str)();
    Content deserializeResponse(String str)();
}

Ora avrò quattro classi:

    public class CreateContentHandler implements ContentHandler{
        String serializeRequest(Content con){
           // .........    
        }
        String serializeResponse(Content con){
           // ........
        }  

        Content deserializeRequest(String str){

        }
        Content deserializeResponse(String str){

        }

    }

    public class RetrieveContentHandler implements ContentHandler{
     //.........
    }

    public class UpdateContentHandler implements ContentHandler{
     //.........
    }

    public class DeleteContentHandler implements ContentHandler{
    //.........
    }

Ora ho il requisito di gestire diversi tipi di contenuto come JSON, XML, CUSTOM-TYPE. Quindi serializza i contenuti in modo JSON o XML.

Quindi stavo pensando di passare una variabile contenType a ciascuna funzione e gestire il contenuto all'interno di ciascuna funzione avendo casi di switch.

   String serializeRequest(Content con, ContentType type){
       // ....
       switch(type){
          case JSON:

          case XML: 
       }
    }

Ma penso che questo renderà la mia funzione serialize grande con quattro diversi tipi di gestione. Ho tre variabili serialize / deserialize, request / response, xml / json / cutom.

Come posso aggiungere nuove interfacce o classi per soddisfare diversi tipi di contenuti al design attuale ??

Modifica Non sto facendo la mia serializzazione in questo modo come hai detto usando alcuni metodi:

String createStringNode(...);  
    String openSubbloc(...);  
    ... // you have to analyze your switch blocks to determine the primitives

Gestisco la serializzazione / deserializzazione JSON usando un Jackson (libreria JSON). Quindi, quello che faccio è impostare alcune proprietà di ObjectMapper che serializza / deserializza i dati in ogni richiesta.

// JSON serialization

objectMapperPropertiesBuilder = new ObjectMapperPropertiesBuilder();          
objectMapperPropertiesBuilder.setSerializationFeature(SerializationFeature.WRAP_ROOT_VALUE);                                objectMapperPropertiesBuilder.setInclude(Include.NON_DEFAULT);

jsonPayload = JsonUtils.toJsonString(payload, objectMapperPropertiesBuilder.build());

Analogamente per XML, userò una libreria e ne imposterò alcune proprietà. Quindi, come posso implementare la strategia XMLForamtter, JSONFormatter in questo caso ??

Come ogni richiesta / risposta, il contenuto sarà diverso, quindi il processo di serializzazione / deserializzazione sarà diverso (saranno impostate diverse proprietà).

Mi manca qualcosa ??

    
posta Siddharth Trikha 30.07.2016 - 16:10
fonte

2 risposte

6

L'intento del modello di strategia in base al GoF sta per" definire una famiglia di algoritmi, incapsularli e renderli intercambiabili.La strategia consente agli algoritmi di essere indipendenti dal client che li usa "

Nel tuo codice applichi questo modello, realizzando una strategia di ContentHandler che può essere rifiutata in una diversa gestione concreta dei contenuti, a seconda delle richieste da perseguire.

Problema con l'approccio switch:

Tuttavia, nell'implementazione la serializzazione dipende dal formato che si desidera utilizzare. Il modo in cui si passa un tipo di contenuto, utilizzando molti blocchi di switch per produrre il formato appropriato, renderà il codice molto difficile da mantenere: ogni implementazione del gestore di contenuti dovrà fornire tutti i tipi di formati. Immagina che un giorno ti piacerebbe aggiungere un nuovo formato (ad esempio bson ): dovresti rivedere tutti i blocchi switch di tutta la tua implementazione concreta di ContentHandler . È un lavoro enorme, e chiaramente non applica molto bene separazione delle preoccupazioni .

Alternativa:

Ma guardandolo più da vicino, hai qui l'opportunità di aggiungere un secondo livello di strategie. Ciascuno dei blocchi di interruttori corrisponderebbe a un tipo di operazione primitiva sul contenuto per produrre il formato. È un'altra famiglia di algoritmi. Dovresti quindi rendere il formato una strategia pure:

public interface SerialFormatter {
    String createStringNode(...);  
    String openSubbloc(...);  
    ... // you have to analyze your switch blocks to determine the primitives
};

E quindi raggruppare tutte le primitive specifiche del formato secondo questa logica:

class JSONFormatter implements SerialFormatter { ... }; 
class XMLFormatter implements SerialFormatter { ... }; 

Se un giorno vuoi supportare un nuovo formato, aggiungi una nuova classe di questo tipo.

Quindi puoi semplificare la logica del serializzatore:

String serializeRequest(Content con, SerialFormatter fmt){
   // ....
   String s = fmt.openSubbloc ("ID") + 
       fmt.createStringNode ("Name", con.name() ) +
       ...
       fmt.closeSubbloc("ID"); 
   return s;  
 }

Conclusione

Il design che utilizza una combinazione di più strategie viene talvolta chiamato "design basato su criteri" È un approccio molto potente: con n tipi di richieste e m formato, dovresti scrivere classi m + n con una sola responsabilità, invece di scrivere classi m (vedi altra risposta alla tua domanda) o scrivere n classi e almeno n m piuttosto ridondante cases .

    
risposta data 01.08.2016 - 22:16
fonte
-1

Per seguire Apri Chiudi principio e anche Principio della singola responsabilità Ti suggerisco tali divisioni:

public interface ContentSerializer{
    String serialize(Content str);
    String deserialize(Content str);
}

public interface RequestSerializer extends ContentSerializer{}
public interface ResponseSerializer extends ContentSerializer{}

e quindi disporre di un'implementazione speciale per ogni combinazione che hai:

JsonCreateRequestSerializer, JsonCreateResponseSerializer,
XmlUpdateSerializer, ...

Aumenterà rapidamente il numero di classi nel tuo progetto, ma ti porterà la libertà su come espandere questa struttura, e darà anche il tuo codice giusto ordine.

Alla fine della giornata il tuo codice conterrà comunque il caso di switch di grandi dimensioni almeno in fase di costruzione dell'istanza corretta di ContentSerializer ma puoi comunque nasconderlo in fabbrica:

public class RequestSerializerFactory{
    public static ContentSerializer createCreateRequestSerializer(ContentType type){}
    public static ContentSerializer createUpdateRequestSerializer(ContentType type){}
    public static ContentSerializer createRetrieveRequestSerializer(ContentType type){}
    public static ContentSerializer createDeleteRequestSerializer(ContentType type){}

} //and same for Response
    
risposta data 01.08.2016 - 20:49
fonte