Kako zamijeniti mnoge izjave ako na Javi

1. Pregled

Konstrukcije odluka vitalni su dio svakog programskog jezika. Ali kopčamo u kodiranju velikog broja ugniježđenih if izjava koje naš kod čine složenijim i teškim za održavanje.

U ovom uputstvu proći ćemo kroz razni načini zamjene ugniježđenih if izraza.

Istražimo različite mogućnosti kako pojednostaviti kod.

2. Studija slučaja

Često se susrećemo s poslovnom logikom koja uključuje puno uvjeta i svaki od njih treba različitu obradu. Zarad demo, uzmimo primjer a Kalkulator razred. Imat ćemo metodu koja uzima dva broja i operator kao ulaz i vraća rezultat na temelju operacije:

javni int izračun (int a, int b, operator niza) {int rezultat = Integer.MIN_VALUE; if ("dodaj" .equals (operator)) {rezultat = a + b; } inače if ("množi" .equals (operator)) {rezultat = a * b; } inače if ("podijeli" .equals (operator)) {rezultat = a / b; } inače if ("oduzeti" .jednake (operator)) {rezultat = a - b; } vratiti rezultat; }

To također možemo implementirati pomoću sklopka izjave:

javni int izračunUsingSwitch (int a, int b, operator niza) {prekidač (operator) {slučaj "dodaj": rezultat = a + b; pauza; // ostali slučajevi} return result; }

U tipičnom razvoju, if izjave mogu postati puno veće i složenije prirode. Također, naredbe prekidača ne odgovaraju dobro kada postoje složeni uvjeti.

Još jedan nuspojava ugnježđenih konstrukcija odluka jest da oni postaju neupravljivi. Na primjer, ako trebamo dodati novi operator, moramo dodati novi if izraz i implementirati operaciju.

3. Refaktoriranje

Istražimo alternativne opcije za zamjenu složenih if izjava u mnogo jednostavniji i upravljiviji kod.

3.1. Tvornička klasa

Mnogo puta susrećemo konstrukte odluka koji na kraju rade slične operacije u svakoj grani. To pruža priliku da se izvući tvorničku metodu koja vraća objekt zadane vrste i izvodi operaciju na temelju ponašanja konkretnog objekta.

Za naš primjer, definirajmo Operacija sučelje koje ima jedan primijeniti metoda:

javno sučelje Operation {int apply (int a, int b); }

Metoda uzima dva broja kao ulaz i vraća rezultat. Definirajmo klasu za izvođenje dodavanja:

javna klasa Dodatak implementira operaciju {@Preuzmi public int apply (int a, int b) {return a + b; }}

Sada ćemo implementirati tvorničku klasu koja vraća primjerke Operacija na temelju datog operatora:

javna klasa OperatorFactory {static map operationMap = new HashMap (); static {operationMap.put ("dodaj", novi Dodatak ()); operationMap.put ("podijeli", novi odjeljak ()); // više operatora} javni statički Izborni getOperation (operator niza) {return Opcijski.ofNullable (operationMap.get (operator)); }}

Sada, u Kalkulator klase, možemo upitati tvornicu da bismo dobili relevantnu operaciju i primijenili se na izvorne brojeve:

javni int izračunUsingFactory (int a, int b, operator niza) {Operacija targetOperation = OperatorFactory .getOperation (operator) .orElseThrow (() -> novi IllegalArgumentException ("Nevažeći operator")); vratiti targetOperation.apply (a, b); }

U ovom smo primjeru vidjeli kako se delegira odgovornost za labavo povezane predmete koje poslužuje tvornička klasa. No, moglo bi biti šanse da se ugniježđeni ako izrazi jednostavno prebace u tvorničku klasu što poništava našu svrhu.

Alternativno, možemo održavati spremište objekata u a Karta što bi se moglo potražiti za brzo traženje. Kao što smo vidjeli OperatorFactory # operationMap služi našoj svrsi. Također možemo inicijalizirati Karta tijekom izvođenja i konfigurirajte ih za traženje.

3.2. Korištenje enuma

Pored upotrebe Karta, također možemo koristiti Enum za označavanje određene poslovne logike. Nakon toga ih možemo koristiti bilo u ugniježđenim ako izjave ili preklopno kućišteizjave. Alternativno, možemo ih koristiti i kao tvornicu predmeta i oblikovati za izvršavanje povezane poslovne logike.

To bi smanjilo broj ugniježđenih if izjava i prenijelo odgovornost na pojedinca Enum vrijednosti.

Pogledajmo kako to možemo postići. U početku trebamo definirati svoje Enum:

javni popisivač {ADD, MULTIPLY, SUBTRACT, DIVIDE}

Kao što možemo primijetiti, vrijednosti su oznake različitih operatora koji će se dalje koristiti za izračunavanje. Uvijek imamo mogućnost koristiti vrijednosti kao različite uvjete u ugniježđenim izrazima if ili switch slučajevima, ali osmislimo alternativni način delegiranja logike na Enum sebe.

Definirat ćemo metode za svaki od Enum vrijednosti i izvršite proračun. Na primjer:

DODAJTE {@Preuzmi javni int apply (int a, int b) {return a + b; }}, // ostali operatori public abstract int apply (int a, int b);

A onda u Kalkulator klase, možemo definirati metodu za izvođenje operacije:

javni int izračun (int a, int b, operator operatora) {return operator.apply (a, b); }

Sada se na metodu možemo pozvati pomoću pretvaranje Niz vrijednost za Operater pomoću Operator # valueOf () metoda:

@Test public void whenCalculateUsingEnumOperator_thenReturnCorrectResult () {Kalkulator kalkulatora = novi kalkulator (); int rezultat = calculator.calculate (3, 4, Operator.valueOf ("ADD")); assertEquals (7, rezultat); }

3.3. Uzorak naredbe

U prethodnoj raspravi vidjeli smo upotrebu tvorničke klase za vraćanje instance ispravnog poslovnog objekta za zadani operater. Kasnije se poslovni objekt koristi za izračun u Kalkulator.

Također možemo dizajnirati a Kalkulator # izračunaj metoda za prihvaćanje naredbe koja se može izvršiti na ulazima. Ovo će biti još jedan način zamjene ugniježđenih ako izjave.

Prvo ćemo definirati naše Naredba sučelje:

naredba javnog sučelja {Integer execute (); }

Dalje, implementiramo AddCommand:

javna klasa AddCommand implementira naredbu {// Instance varijable public AddCommand (int a, int b) {this.a = a; ovo.b = b; } @Override public Integer execute () {return a + b; }}

Napokon, predstavimo novu metodu u Kalkulator koja prihvaća i izvršava Naredba:

javni int izračun (naredba naredbe) {return command.execute (); }

Dalje, možemo se pozvati na izračun instancijom AddCommand i pošaljite ga na Kalkulator # izračunaj metoda:

@Test public void whenCalculateUsingCommand_thenReturnCorrectResult () {Kalkulator kalkulatora = novi kalkulator (); int rezultat = calculator.calculate (novi AddCommand (3, 7)); assertEquals (10, rezultat); }

3.4. Rule Engine

Kada na kraju napišemo velik broj ugniježđenih izjava if, svaki od uvjeta prikazuje poslovno pravilo koje se mora procijeniti kako bi se ispravna logika obradila. Stroj pravila uklanja takvu složenost iz glavnog koda. A RuleEngine ocjenjuje Pravila i vraća rezultat na temelju unosa.

Krenimo kroz primjer osmišljavanjem jednostavnog RuleEngine koja obrađuje an Izraz kroz skup Pravila i vraća rezultat odabranom Pravilo. Prvo ćemo definirati a Pravilo sučelje:

javno sučelje Pravilo {logička procjena (izraz izraza); Rezultat getResult (); }

Drugo, provedimo a RuleEngine:

javna klasa RuleEngine {privatna statička pravila popisa = new ArrayList (); static {rules.add (novo AddRule ()); } postupak javnog rezultata (izraz izraza) {Pravilo pravila = pravila .stream () .filter (r -> r.evaluate (izraz)) .findFirst () .orElseThrow (() -> new IllegalArgumentException ("Izraz se ne podudara ni s jednim Pravilo")); vratiti pravilo.getResult (); }}

The RuleEngine prihvaća an Izraz objekt i vraća Proizlaziti. Sada, dizajnirajmo Izraz razred kao skupina od dvoje Cijeli broj predmeti s Operater koji će se primijeniti:

izraz javne klase {private Integer x; privatni cijeli broj y; privatni operator operatora; }

I na kraju definirajmo običaj AddRule razred koji ocjenjuje samo kad DODAJ operaciju je navedeno:

javna klasa AddRule implementira pravilo {@Override javna logička procjena (izraz izraza) {boolean evalResult = false; if (expression.getOperator () == Operator.ADD) {this.result = expression.getX () + expression.getY (); evalResult = true; } povratak evalResult; }}

Sada ćemo se pozvati na RuleEngine s an Izraz:

@Test public void whenNumbersGivenToRuleEngine_thenReturnCorrectResult () {Izraz izraza = novi izraz (5, 5, Operator.ADD); RuleEngine engine = novi RuleEngine (); Rezultat rezultata = engine.process (izraz); assertNotNull (rezultat); assertEquals (10, result.getValue ()); }

4. Zaključak

U ovom uputstvu istražili smo niz različitih mogućnosti za pojednostavljenje složenog koda. Također smo naučili kako zamijeniti ugniježđene izjave if upotrebom učinkovitih obrazaca dizajna.

Kao i uvijek, kompletni izvorni kod možemo pronaći preko GitHub spremišta.


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