2017-10-07 8 views
3

J'ai un morceau de code qui ressemble à ceci:Comment convertir une instruction If composée de plusieurs AND, OR dans une instruction switch?

 String cStatus = getStatus_c(); 
    String nStatus = getStatus_n(); 

    if (!((cStatus.equals(PEN) && nStatus.equals(ACT)) 
      || (cStatus.equals(PEN) && nStatus.equals(SUS)) 
      || (cStatus.equals(PEN) && nStatus.equals(PEN_CAN)) 
      || (cStatus.equals(ACT) && nStatus.equals(SUS)) 
      || (cStatus.equals(ACT) && nStatus.equals(PEN_CAN)) 
      || (cStatus.equals(SUS) && nStatus.equals(ACT)) 
      || (cStatus.equals(SUS) && nStatus.equals(PEN_CAN)) 
      || (cStatus.equals(PEN_CAN) && nStatus.equals(ACT)) 
      || (cStatus.equals(PEN_CAN) && nStatus.equals(CAN)))) 
{ 
    //Do someting// 
} 

code ci-dessus remplit mes besoins mais je veux changer à un code plus lisible en utilisant quelque chose comme bloc de commutation, etc. Je sais comment passer des travaux mais je ne suis pas sûr de savoir comment cacher mon code existant.


Juste pour une meilleure lisibilité, voici une version assainis (A est PEN, B est ACT, C est SUS et D est PEN_CAN):

if (! ( (cStat == A && nStat == B) 
     || (cStat == A && nStat == C) 
     || (cStat == A && nStat == D) 
     || (cStat == B && nStat == C) 
     || (cStat == B && nStat == D) 
     || (cStat == C && nStat == B) 
     || (cStat == C && nStat == D) 
     || (cStat == D && nStat == B) 
     || (cStat == D && nStat == D) 
    ) 
) 
+4

Vous ne avez pas vraiment besoin d'un commutateur pour le nettoyer, votre instruction if peut être nettoyé en réduisant la redondance dans l'état de vérification utilisant des parenthèses correctement placés. – zgc7009

+2

Pouvez-vous expliquer logiquement ce que représente l'expression 'boolean'? Beaucoup plus facile à comprendre alors ... Vous pourriez créer des sous-expressions et les stocker dans des variables 'boolean', leur donner ** de bons noms de variables **. Votre expression 'if' utilisera alors ces variables et sera lisible. Vous pouvez également identifier des variables communes dans l'expression et créer des expressions "imbriquées" ** "if". – Zabuza

Répondre

3

code ci-dessus remplit mon exigences, mais je veux le changer en un code plus lisible en utilisant quelque chose comme un bloc de commutation, etc.

Un mélange de AND et OR instruction conditionnelle ne peut être remplacé par un unique cas de commutation.
Vous pouvez utiliser des cas de commutation embarqués (un externe pour gérer cStatus et un intérieur pour gérer nStatus) mais il ne sera pas vraiment donner un code lisible:

boolean isEnabled = true; 
switch (cStatus) { 

    case PEN: 
    switch (nStatus) { 
    case ACT: 
    case SUS: 
    case PEN_CAN: 
     isEnabled = false; 
    } 
    break; 
    case ACT: 
    switch (cStatus) { 
     ... 
    } 
    break; 
} 

Mais vous pouvez rendre votre code plus lisible en éliminant la duplication et en regroupant des instructions conditionnelles avec la même valeur cStatus par exemple. Vous pouvez également utiliser la méthode List.contains() pour vérifier la valeur nStatus associée à la valeur cStatus.

Voici un extrait:

List<String> nStatusValueForcStatutPen = Arrays.asList("ACT", "SUS", "PEN_CAN"); 
List<String> nStatusValueForcStatutAct = Arrays.asList("SUS", "PEN_CAN"); 
... 
if (!((cStatus.equals(PEN) && nStatusValueForcStatutPen.contains(nStatus)) 
    || (cStatus.equals(ACT) && nStatusValueForcStatutAct.contains(nStatus)) 
    ... 
} 
1

Je vous suggère de créer un diagramme pour bien comprendre la combinaison de toutes les conditions.

Tout d'abord, vous pouvez clairement voir que PAN est toujours le CURRENT_STATUS ainsi, vous pouvez raccourcir la première condition.

Deuxièmement, il existe plusieurs ocnditions bidirectionnelles, où certains états peuvent être NEW_STATUS ou CURRENT_STATUS. Il est facile d'être exprimé par la deuxième condition.

Enfin, il y a 2 conditions à sens unique (SUS ->PEN_CAN ->CAN) exprimés par la dernière condition.

les combiner:

boolean penCondition = CURRENT_STATUS.equals(PEN) && 
    (NEW_STATUS.equals(SUS) || NEW_STATUS.equals(PEN_CAN) || NEW_STATUS.equals(ACT)); 
boolean twoWayCondition = CURRENT_STATUS.equals(ACT) && (NEW_STATUS.equals(SUS) && NEW_STATUS.equals(PEN_CAN)) || 
    NEW_STATUS.equals(ACT) && (CURRENT_STATUS.equals(SUS) && CURRENT_STATUS.equals(PEN_CAN)); 
boolean oneWayCondition = (CURRENT_STATUS.equals(SUS) && NEW_STATUS.equals(PEN_CAN)) || 
    (CURRENT_STATUS.equals(PEN_CAN) && NEW_STATUS.equals(CAN)); 

if !(penCondition || twoWayCondition || oneWayCondition) { 

} 
0
StatusChange curCange = new StatusChange(CURRENT_STATUS, NEW_STATUS); 

if(!ngChange.contains(curChange)){ 

......do something..... 

} 

//New codes 

class StatusChange{ 

  final Status cur; 

  final Status nw; 

  ..override equals method...... 

} 


Set<StatusChange> ngChange=new HashSet(); 
(
ngChange.add(new StatusChange(PEN,ACT)); 
ngChange.add(new StatusChange(ACT,PEN)); 
......... 
) 
1

Le code que vous avez ne nécessite pas une instruction switch. Vous pouvez envisager d'utiliser un Set

Voici le code:

public class Combination 
{ 
    private final String cStatus; 
    private final String nStatus; 

    public Combination(
     final String cStatusValue, 
     final String nStatusValue) 
    { 
     cStatus = StringUtils.trimToEmpty(cStatusValue); 
     nStatus = StringUtils.trimToEmpty(nStatusValue); 
    } 

    public int hashCode() 
    { 
     final int returnValue; 

     returnValue = cStatus.hashCode() + nStatus.hashCode(); 
    } 

    public boolean equals(final Object object) 
    { 
     ... implement equals 
    } 
} 

... during setup 
private Set<Combination> goodCombinationSet = new HashSet<Combination>(); 

... add all good combinations to the goodCombinationSet. 


... when testing. 

final Combination testCombination = new Combination(cStatus, nStatus); 

if (goodCombinationSet.contains(testCombination)) 
... do something 
1

Ci-dessous mon code final et je pense qu'il est beaucoup plus facile à lire et propre que la version précédente:

Chaîne c État = getcStatus();
Chaîne nStatus = getnStatus();

Chaîne transitionString = cStatus + "_" + nStatus;

switch (transitionString) { 
    case "PEN_ACT": 
     break; 
    case "PEN_SUS": 
     break; 
    case "PEN_PENCAN": 
     break; 
    case "ACT_SUS": 
     break; 
    case "ACT_PENCAN": 
     break; 
    case "SUS_ACT": 
     break; 
    case "SUS_PENCAN": 
     break; 
    case "PENCAN_AC": 
     break; 
    case "PENCAN_CAN": 
     break; 
    default: { 
     //DO SOMETHING 
     //In my case throwing an exception i.e. program will not continue further. 
    } 
    } 
    { 
    //DO SOMETHING ELSE 
    }