Hogyan cserélhetünk sok Java-utasítást Java-ban

1. Áttekintés

A döntési konstrukciók minden programozási nyelv létfontosságú részét képezik. De eljutottunk a beágyazott, ha sok olyan utasítás kódolásába, amelyek bonyolultabbá és nehezebben karbantarthatóvá teszik kódunkat.

Ebben az oktatóanyagban végigmegyünk a a beágyazott if nyilatkozatok helyettesítésének különféle módjai.

Vizsgáljuk meg a különböző lehetőségeket, hogyan egyszerűsíthetjük a kódot.

2. Esettanulmány

Gyakran találkozunk olyan üzleti logikával, amely rengeteg feltételt tartalmaz, és mindegyiknek más és más feldolgozásra van szüksége. A bemutató kedvéért vegyük a példát Számológép osztály. Olyan módszerünk lesz, amely két számot és egy operátort vesz be bevitelként, és a művelet alapján adja vissza az eredményt:

public int kiszámítja (int a, int b, String operátor) {int eredmény = Egész szám.MIN_ÉRTÉK; if ("add" .egyenlő (operátor)) {eredmény = a + b; } else if ("szoroz" .egyenlő (operátor)) {eredmény = a * b; } else if ("oszt" .egyenlő (operátor)) {eredmény = a / b; } else if ("kivonás" .egyenlő (operátor)) {eredmény = a - b; } visszatérési eredmény; }

Ezt a segítségével is megvalósíthatjuk kapcsoló nyilatkozatok:

public int calcUsingSwitch (int a, int b, String operátor) {switch (operátor) {case "add": eredmény = a + b; szünet; // egyéb esetek} return result; }

Tipikus fejlődésben az if nyilatkozatok sokkal nagyobbak és összetettebbek lehetnek. Is, a kapcsoló utasítások nem felelnek meg jól, ha összetett feltételek vannak.

A beágyazott döntési konstrukciók másik mellékhatása, hogy kezelhetetlenné válnak. Például, ha új operátort kell hozzáadnunk, akkor hozzá kell adnunk egy új if utasítást, és végre kell hajtanunk a műveletet.

3. Refaktorálás

Fedezzük fel az alternatív lehetőségeket a komplex, ha a fenti utasítások helyettesítésére sokkal egyszerűbb és kezelhetőbb kódra.

3.1. Gyári osztály

Sokszor találkozunk olyan döntési konstrukciókkal, amelyek végül minden ágban hasonló műveletet hajtanak végre. Ez lehetőséget ad arra kivonat egy gyári metódust, amely egy adott típusú objektumot ad vissza, és a műveletet a konkrét objektum viselkedése alapján hajtja végre.

Például definiáljunk egy Művelet interfész, amelynek egyetlen alkalmaz módszer:

nyilvános felület Művelet {int alkalmazni (int a, int b); }

A módszer két számot vesz be bevitelként, és az eredményt adja vissza. Határozzunk meg egy osztályt a kiegészítések végrehajtásához:

public class Addition végrehajtja a {@Orride public int Apply (int a, int b) {műveletet {return a + b; }}

Most bevezetünk egy gyári osztályt, amely visszaadja a Művelet az adott operátor alapján:

public class OperatorFactory {static Map operationMap = new HashMap (); statikus {operationMap.put ("add", új Addition ()); operationMap.put ("osztás", új osztály ()); // további operátorok} public static Opcionális getOperation (String operátor) {return Optional.ofNullable (operationMap.get (operátor)); }}

Most, a Számológép osztályban lekérdezhetjük a gyárat a megfelelő művelet megszerzéséhez, és alkalmazhatjuk a forrásszámokra:

public int calcUsingFactory (int a, int b, String operátor) {Operation targetOperation = OperatorFactory .getOperation (operátor) .orElseThrow (() -> új IllegalArgumentException ("Érvénytelen operátor")); return targetOperation.apply (a, b); }

Ebben a példában láthattuk, hogyan ruházzák át a felelősséget a gyárosztály által kiszolgált, lazán összekapcsolt objektumokra. De lehetnek olyan esélyek, ahol a beágyazott, ha az állításokat egyszerűen a gyári osztályba helyezik át, ami meghiúsítja célunkat.

Alternatív megoldásként objektumok tárházát tarthatjuk fenn a Térkép amelyet gyors megkeresés céljából lehet lekérdezni. Ahogy láttuk OperatorFactory # operationMap célunkat szolgálja. Inicializálhatjuk is Térkép futás közben, és konfigurálja őket keresésre.

3.2. Enums használata

A használata mellett Térkép, használhatjuk is Enum egy adott üzleti logika felcímkézésére. Ezt követően akár a beágyazottban is felhasználhatjuk őket ha állítások vagy kapcsolószekrénynyilatkozatok. Alternatív megoldásként objektumok gyáraként is felhasználhatjuk őket, és stratégiázhatjuk őket a kapcsolódó üzleti logika végrehajtására.

Ez csökkentené a beágyazott, ha nyilatkozatok számát, és a felelősséget az egyénre ruházná Enum értékek.

Lássuk, hogyan érhetjük el. Eleinte meg kell határoznunk a sajátunkat Enum:

public enum Operátor {ADD, MULTIPLY, SUBTRACT, DIVIDE}

Amint megfigyelhetjük, az értékek a különböző operátorok címkéi, amelyeket tovább fognak használni a számításhoz. Mindig lehetőségünk van arra, hogy az értékeket különböző feltételként használjuk a beágyazott if utasításokban vagy az esetváltásban, de tervezzünk egy alternatív módot a logika delegálására a Enum maga.

Meghatározzuk a módszereket az egyes Enum értékeket és végezze el a számítást. Például:

ADD {@Orride public int Apply (int a, int b) {return a + b; }}, // egyéb operátorok public abstract int érvényesek (int a, int b);

És akkor a Számológép osztályban meghatározhatunk egy módszert a művelet végrehajtására:

public int kiszámítja (int a, int b, Operator operator) {return operator.apply (a, b); }

Most a módszerrel hívhatjuk meg konvertálása a Húr érték a Operátor a Operator # valueOf () módszer:

@Test public void whenCalculateUsingEnumOperator_thenReturnCorrectResult () {Számológép kalkulátor = új Számológép (); int eredmény = számológép.kalkulál (3, 4, Operator.valueOf ("ADD")); assertEquals (7, eredmény); }

3.3. Parancsminta

Az előző beszélgetés során a gyári osztály használatával láthattuk a megfelelő üzleti objektum példányát az adott operátor számára. Később az üzleti objektumot használják a számítás elvégzésére a Számológép.

Tervezhetünk is a Számológép # kiszámítása metódus a bemeneteken végrehajtható parancs elfogadására. Ez egy másik módja lesz a beágyazottak cseréjének ha állítások.

Először meghatározzuk Parancs felület:

nyilvános felület Parancs {Egész szám végrehajtása (); }

Ezután hajtsuk végre a AddCommand:

public class Az AddCommand végrehajtja a Command {// Példányváltozók public AddCommand (int a, int b) {this.a = a; ez.b = b; } @Orride public Integer execute () {return a + b; }}

Végül mutassunk be egy új módszert a Számológép amely elfogadja és végrehajtja a Parancs:

public int kiszámítja (Command parancs) {return command.execute (); }

Ezután egy an példányosításával hívhatjuk meg a számítást AddCommand és elküldi a Számológép # kiszámítása módszer:

@Test public void whenCalculateUsingCommand_thenReturnCorrectResult () {Számológép kalkulátor = új Számológép (); int eredmény = számológép.kalkulál (új AddCommand (3, 7)); assertEquals (10, eredmény); }

3.4. Szabály motor

Amikor végül sok beágyazott if utasítást írunk, mindegyik feltétel egy üzleti szabályt ábrázol, amelyet ki kell értékelni a feldolgozandó logika szempontjából. A szabály motor kiveszi az ilyen összetettséget a fő kódból. A RuleEngine értékeli a Szabályok és a bemenet alapján adja vissza az eredményt.

Nézzünk végig egy példát egy egyszerű tervezésével RuleEngine amely egy an Kifejezés halmazán keresztül Szabályok és visszaadja a kiválasztott eredményét Szabály. Először meghatározzuk a Szabály felület:

nyilvános felület Szabály {logikai értékelés (Expression kifejezés); Eredmény getResult (); }

Másodszor, hajtsuk végre a RuleEngine:

public class RuleEngine {private static List rules = new ArrayList (); statikus {szabályok.add (új AddRule ()); } public Eredmény folyamata (Expression kifejezés) {Szabály szabály = szabályok .stream () .filter (r -> r.evaluate (kifejezés)) .findFirst () .orElseThrow (() -> new IllegalArgumentException ("A kifejezés nem felel meg egyiknek sem) Szabály")); return szabály.getResult (); }}

A RuleEngine elfogad egy Kifejezés objektumot adja vissza Eredmény. Most, tervezzük meg a Kifejezés osztály kétfős csoportként Egész szám tárgyakat a Operátor amelyet alkalmazni fognak:

public class Expression {privát egész szám x; magán Integer y; magánüzemeltető üzemeltető; }

És végül határozzunk meg egy szokást AddRule osztály, amely csak akkor értékeli, ha a ADD művelet meg van határozva:

public class AddRule végrehajtja a szabályt {@Orride public boolean assessment (Expression expression) {boolean evalResult = false; if (kifejezés.getOperator () == Operátor.ADD) {this.result = kifejezés.getX () + kifejezés.getY (); evalResult = true; } return evalResult; }}

Most hivatkozunk a RuleEngine egy valamivel Kifejezés:

@Test public void whenNumbersGivenToRuleEngine_thenReturnCorrectResult () {Kifejezés kifejezés = új kifejezés (5, 5, Operator.ADD); RuleEngine engine = új RuleEngine (); Eredmény eredménye = motor.folyamat (kifejezés); assertNotNull (eredmény); assertEquals (10, eredmény.getValue ()); }

4. Következtetés

Ebben az oktatóanyagban számos különböző lehetőséget vizsgáltunk meg az összetett kód egyszerűsítése érdekében. Megtanultuk azt is, hogyan lehet a beágyazott, ha állításokat hatékony tervezési mintákkal helyettesíteni.

Mint mindig, a teljes forráskódot a GitHub adattáron találjuk meg.


$config[zx-auto] not found$config[zx-overlay] not found