2015-09-22 15 views
9

Ho due enumerazioni correlate.Due mappature relative alle enumerazioni?

Enum1:

public enum HttpMethodName 
{ 
    GET, POST, PUT, DELETE; 
} 

Enum2:

public enum ProtocolOperation { 
    CREATE(1), RETRIEVE(2), UPDATE(3), DELETE(4), NOTIFY(5); 


    private BigInteger operationId; 

    public BigInteger getOperationId() { 
     return operationId; 
    } 

    private ProtocolOperation(int operationId) { 
     this.operationId = BigInteger.valueOf(operationId); 
    } 
} 

I valori enums hanno mappatura come:

Create--> POST 
Retrieve--> GET 
Update--> PUT 
Delete--> DELETE 
Notify---> POST 

Quindi c'è mappatura uno a uno tra i valori ad eccezione solo per POST caso che può avere due valori Create o Notify in base a una condizione. ci

public enum HttpMethodName 
    { 

     POST(new List(ProtocolOperation.CREATE, ProtocolOperation.NOTIFY)) ,GET (new List(ProtocolOperation.RETRIEVE)) , 
PUT (new List(ProtocolOperation.UPDATE) ,DELETE(new List(ProtocolOperation.DELETE) ; 

     List<ProtocolOperation > ops; 
     HttpMethodName (List<ProtocolOperation> ops) 
     { 
      this.ops = ops; 
     } 
    } 

è un approccio migliore ??:

Stavo pensando di mantenere la mappatura come List

EDIT:

vorrò mappatura entrambi i modi da HttpMethodName <----> ProtocolOperation

+0

Era quello ultima modifica per rendere la parola "sia" bold, una reazione alla mia risposta? Perché la mia risposta ha una mappatura in entrambe le direzioni. – Andreas

+0

uso può usare BiMap in Guava – yelliver

+0

Ti aspetti due istanze 'Map', o le risposte esistenti raccomandano metodi abbastanza buoni? Forse puoi anche condividere in che modo questa relazione sarà utilizzata ulteriormente nella tua base di codice? –

risposta

8

Perché fare ritieni che il tuo attuale approccio sia insoddisfacente?

Senza la conoscenza delle vostre preoccupazioni Posso solo suggerire di togliere boilerplate:

import static ProtocolOperation.*; 

public enum HttpMethodName { 
    GET(RETRIEVE), 
    POST(CREATE, NOTIFY), 
    PUT(UPDATE), 
    DELETE(ProtocolOperation.DELETE); 

    final List<ProtocolOperation> ops; 

    HttpMethodName(ProtocolOperation... ops) { 
     this.ops = Collections.unmodifiableList(Arrays.asList(ops)); 
    } 
} 

UPD:

Se si desidera avere la mappatura in entrambi i modi, ha senso hardcode mappatura da ProtocolOperation a HttpMethodName prima (in quanto non necessita di lista) e creare un semplice metodo di ricerca in MttpMethodName:

public enum ProtocolOperation { 
    CREATE(1, HttpMethodName.POST), 
    RETRIEVE(2, HttpMethodName.GET), 
    UPDATE(3, HttpMethodName.PUT), 
    DELETE(4, HttpMethodName.DELETE), 
    NOTIFY(5, HttpMethodName.POST); 

    private BigInteger operationId; 
    private HttpMethodName methodName; 

    public BigInteger getOperationId() { 
     return operationId; 
    } 

    public HttpMethodName getMethodName() { 
     return methodName; 
    } 

    private ProtocolOperation(int operationId, HttpMethodName httpMethodName) { 
     this.methodName = httpMethodName; 
     this.operationId = BigInteger.valueOf(operationId); 
    } 
} 

public enum HttpMethodName { 
    GET, 
    POST, 
    PUT, 
    DELETE; 

    List<ProtocolOperation> getProtocolOperations() { 
     List<ProtocolOperation> ops = new ArrayList<ProtocolOperation>(2); 
     for (ProtocolOperation op : ProtocolOperation.values()) { 
      if (op.getMethodName() == this) { 
       ops.add(op); 
      } 
     } 
     return ops; 
    } 
} 

come si avere un numero costante e piccolo di valori, non è necessario creare la mappa statica finale in HttpMethodName per fornire la mappatura all'indietro, la ricerca lineare è abbastanza veloce per il tuo caso.

+0

Dato che OP vuole una mappa da 'ProtocolOperazione' a' HttpMethodName', avresti dovuto farlo in un altro modo, eliminando anche la necessità di un elenco. – Andreas

+0

@Andreas: Ciò porterebbe ad iterare i valori enum ogni volta per trovare la mappatura ?? –

+0

@Andreas, cosa ti fa pensare che OP desideri effettuare il mapping da 'ProtocolOperation' a' HttpMethodName'? A giudicare dalle sue parole 'I valori delle enumerazioni hanno una mappatura come:' e la seguente tabella supporrebbe che egli desideri una mappa da 'HttpMethodName' a' ProtocolOperation'. – Aivean

1

vorrei andare con la separazione logica da enum. Il tuo approccio è un accoppiamento stretto, meno elastico. Con tale libreria con trasformare Metod si sono più flessibili

private static final Map<HttpMethodName , ProtocolOperation> mapping = new HashMap<>(); 
static { 
mapping .put(Create, POST); 
// rest of methods 
} 

E qui il corpo del vostro metodo di mappatura (sto usando Jdk8):

public static Optional<HttpMethodName > map(ProtocolOperation op){ 
if (!mapping.containsKey(op)){ 
    return Optional.empty(); 
} 
    return Optional.of(mapping.get(op)); 
} 

In breve: enum non dovrebbe avere alcuna logica di business associati con loro, per la mappatura e la trasformazione dovrebbero essere usati metodi esterni (utils).

UPDATE: Come @Andreas ha giustamente osservato, in questo particolare esempio, dove la mappatura è fisso, e non dovrebbe essere esteso, si può stare con il suo modo di inizializzazione:

HttpMethodName(ProtocolOperation... ops) { 
    this.ops = Collections.unmodifiableList(Arrays.asList(ops)); 
} 
+1

Perché la cosa che enum non dovrebbe contenere la mappatura? Per me, la relazione tra i metodi HTTP e i loro ruoli è definita dal protocollo HTTP. Avresti ragione se ci fossero diversi (diciamo, più di due) mappature differenti che coinvolgono l'enum 'HttpMethodName', ma lo trovo improbabile. – Aivean

+0

Pochi anni dopo stavo facendo lo stesso approccio. In questo esempio potrebbe avere un senso, ma generalmente tendiamo a mantenere il codice aperto per le estensioni. Avere mappature in una classe di utilità ci consentirà di creare mappature separate per altri client/moduli, ecc. Ma devo ammettere che in questo esempio, mantenere una lista di enumerati enum di un enum può essere buono. – Beri

4

Creare la mappatura da ProtocolOperation a HttpMethodName come mostrato con le frecce, quindi sono semplici riferimenti, non elenchi.

La mappatura inversa può quindi essere un metodo statico che itera i 5 valori enum per le corrispondenze. Ci sono solo 5 valori, quindi una ricerca sequenziale è sufficientemente veloce, a meno che non si tratti di qualcosa che si fa in un ciclo molto stretto, ed è improbabile in questo caso. Inoltre, non dovresti codificare le prestazioni finché un profiler non dice che hai un problema.

state seguite le mappature come segue:

// From ProtocolOperation to HttpMethodName 
HttpMethodName method = ProtocolOperation.CREATE.getHttpMethodName(); 

// From HttpMethodName to ProtocolOperation 
ProtocolOperation op = ProtocolOperation.forMethod(HttpMethodName.GET); 

Implementazione:

public enum HttpMethodName 
{ 
    GET, POST, PUT, DELETE; 
} 
public enum ProtocolOperation { 
    CREATE (1, HttpMethodName.POST), 
    RETRIEVE(2, HttpMethodName.GET), 
    UPDATE (3, HttpMethodName.PUT), 
    DELETE (4, HttpMethodName.DELETE), 
    NOTIFY (5, HttpMethodName.POST); 

    private final int   operationId; 
    private final HttpMethodName httpMethodName; 

    private ProtocolOperation(int operationId, HttpMethodName httpMethodName) { 
     this.operationId = operationId; 
     this.httpMethodName = httpMethodName; 
    } 

    public int getOperationId() { 
     return this.operationId; 
    } 

    public HttpMethodName getHttpMethodName() { 
     return this.httpMethodName; 
    } 

    public static List<ProtocolOperation> forMethod(HttpMethodName httpMethodName) { 
     List<ProtocolOperation> ops = new ArrayList<>(); 
     for (ProtocolOperation op : values()) 
      if (op.httpMethodName == httpMethodName) 
       ops.add(op); 
     return ops; 
    } 
} 
+0

Wow, ho pubblicato la tua stessa soluzione. Questo non era intenzionale. Invitandoti :) – Aivean

+1

@Aivean Le grandi menti pensano allo stesso modo, eh. ;-) – Andreas

Problemi correlati