Konstanter i Java: Mønstre og antimønstre

1. Introduksjon

I denne artikkelen skal vi lære om bruk av konstanter i Java med fokus på vanlige mønstre og antimønstre.

Vi begynner med noen grunnleggende konvensjoner for å definere konstanter. Derfra vil vi gå over på vanlige antimønstre før vi avslutter med en titt på vanlige mønstre.

2. Grunnleggende

En konstant er en variabel hvis verdi ikke vil endres etter at den er definert.

La oss se på det grunnleggende for å definere en konstant:

privat statisk slutt int OUR_CONSTANT = 1;

Noen av mønstrene vi vil se på vil adressere offentlig eller privat tilgangsmodifiseringsbeslutning. Vi lager konstantene våre statisk og endelig og gi dem en passende type, enten det er en Java-primitiv, en klasse eller en enum. Navnet skal være alle store bokstaver med ordene atskilt med understreking, noen ganger kjent som skrikende slangesak. Til slutt gir vi selve verdien.

3. Antimønstre

Først, la oss begynne med å lære hva vi ikke skal gjøre. La oss se på et par vanlige antimønstre vi kan støte på når vi jobber med Java-konstanter.

3.1. Magiske tall

Magiske tall er numeriske bokstaver i en kodeblokk:

hvis (nummer == 3.14159265359) {// ...}

De er vanskelige for andre utviklere å forstå. I tillegg, hvis vi bruker et tall gjennom hele koden vår, er det vanskelig å takle å endre verdien. Vi bør i stedet definere tallet som en konstant.

3.2. En stor global konstantklasse

Når vi starter et prosjekt, kan det føles naturlig å lage en klasse som heter Konstanter eller Verktøy med den hensikt å definere alle konstanter for applikasjonen der. For mindre prosjekter kan dette være ok, men la oss vurdere et par grunner til at dette ikke er en ideell løsning.

La oss først forestille oss at vi har hundre eller flere konstanter alle i vår konstantklasse. Hvis klassen ikke blir opprettholdt, både for å holde tritt med dokumentasjon og for å omforme konstantene til logiske grupperinger, blir det ganske uleselig. Vi kan til og med ende opp med duplikatkonstanter med litt forskjellige navn. Denne tilnærmingen vil sannsynligvis gi oss problemer med lesbarhet og vedlikehold i alt annet enn de minste prosjektene.

I tillegg til logistikken for å opprettholde Konstanter I selve klassen inviterer vi også andre vedlikeholdsproblemer ved å oppmuntre for mye gjensidig avhengighet med denne ene globale konstantklassen og forskjellige andre deler av applikasjonen vår.

På en mer teknisk side, Java-kompilatoren plasserer verdien av konstanten i referansevariabler i klassene der vi bruker dem. Så hvis vi endrer en av konstantene våre i konstantklassen og bare kompilerer den klassen på nytt og ikke den refererende klassen, kan vi få inkonsekvente konstante verdier.

3.3. Det konstante grensesnittet mot mønster

Det konstante grensesnittmønsteret er når vi definerer et grensesnitt som inneholder alle konstantene for viss funksjonalitet, og deretter har klassene som trenger disse funksjonene for å implementere grensesnittet.

La oss definere et konstant grensesnitt for en kalkulator:

offentlig grensesnitt CalculatorConstants {double PI = 3.14159265359; doble UPPER_LIMIT = 0x1.fffffffffffffP + 1023; enum Operation {ADD, SUBTRACT, MULTIPLY, DIVIDE}; }

Deretter implementerer vi vår KalkulatorKonstanter grensesnitt:

offentlig klasse GeometryCalculator implementerer CalculatorConstants {public double operateOnTwoNumbers (double numberOne, double numberTwo, Operation operation) {// Kode for å utføre en operasjon}}

Det første argumentet mot å bruke et konstant grensesnitt er at det strider mot formålet med et grensesnitt. Vi er ment å bruke grensesnitt for å lage en kontrakt for oppførselen våre implementeringsklasser skal gi. Når vi lager et grensesnitt fullt av konstanter, definerer vi ikke noe atferd.

For det andre, ved å bruke et konstant grensesnitt åpner vi oss for kjøretidsproblemer forårsaket av feltskygging. La oss se på hvordan det kan skje ved å definere en ØVRE GRENSE konstant i vår GeometryCalculator klasse:

offentlig statisk endelig dobbel UPPER_LIMIT = 100000000000000000000.0;

Når vi definerer den konstante i vår GeometryCalculator klasse skjuler vi verdien i KalkulatorKonstanter grensesnitt for klassen vår. Vi kunne da få uventede resultater.

Et annet argument mot dette antimønsteret er at det forårsaker forurensning i navneområdet. Våre KalkulatorKonstanter vil nå være i navneområdet for noen av våre klasser som implementerer grensesnittet, så vel som noen av deres underklasser.

4. Mønstre

Tidligere så vi på riktig form for å definere konstanter. La oss se på noen andre gode fremgangsmåter for å definere konstanter i applikasjonene våre.

4.1. Generell god praksis

Hvis konstanter er logisk knyttet til en klasse, kan vi bare definere dem der. Hvis vi ser på et sett med konstanter som medlemmer av en oppregnet type, kan vi bruke en enum for å definere dem.

La oss definere noen konstanter i a Kalkulator klasse:

offentlig klasse Kalkulator {offentlig statisk endelig dobbel PI = 3.14159265359; privat statisk sluttdobbel UPPER_LIMIT = 0x1.fffffffffffffP + 1023; public enum Operation {ADD, SUBTRACT, DIVIDE, MULTIPLY} public double operateOnTwoNumbers (double numberOne, double numberTwo, Operation operation) {if (numberOne> UPPER_LIMIT) {throw new IllegalArgumentException ("'numberOne' er for stor"); } if (numberTwo> UPPER_LIMIT) {throw new IllegalArgumentException ("'numberTwo' is too large"); } dobbelt svar = 0; switch (operation) {case ADD: answer = numberOne + numberTwo; gå i stykker; sak SUBTRAKT: svar = nummerEn - nummerTo; gå i stykker; sak DIVIDE: svar = nummerEn / nummerTo; gå i stykker; sak MULTIPLY: answer = numberOne * numberTwo; gå i stykker; } returnere svar; }}

I vårt eksempel har vi definert en konstant for ØVRE GRENSE som vi bare planlegger å bruke i Kalkulator klasse, så vi har satt den til privat. Vi ønsker at andre klasser skal kunne bruke PI og Operasjon enum, så vi har satt dem til offentlig.

La oss vurdere noen av fordelene ved å bruke en enum til Operasjon. Den første fordelen er at den begrenser mulige verdier. Tenk deg at metoden vår tar en streng for operasjonsverdien med forventning om at en av fire konstante strenger leveres. Vi kan enkelt forutse et scenario der en utvikler som kaller metoden sender sin egen strengverdi. Med enum, er verdiene begrenset til de vi definerer. Vi kan også se at enums er spesielt godt egnet til bruk i bytte om uttalelser.

4.2. Konstantklasse

Nå som vi har sett på noen generelle god praksis, la oss vurdere saken når en konstante klasse kan være en god idé. La oss forestille oss at applikasjonen vår inneholder en pakke med klasser som trenger å gjøre forskjellige typer matematiske beregninger. I dette tilfellet er det sannsynligvis fornuftig for oss å definere en konstante klasse i den pakken for konstanter som vi vil bruke i beregningsklassene.

La oss lage en MathConstants klasse:

offentlig sluttklasse MathConstants {offentlig statisk sluttdobbel PI = 3.14159265359; statisk endelig dobbel GOLDEN_RATIO = 1.6180; statisk endelig dobbel GRAVITATIONAL_ACCELERATION = 9.8; statisk endelig dobbel EULERS_NUMBER = 2.7182818284590452353602874713527; public enum Operation {ADD, SUBTRACT, DIVIDE, MULTIPLY} private MathConstants () {}}

Det første vi bør legge merke til er at klassen vår er endelig for å forhindre at den utvides. I tillegg har vi definert en privat konstruktør slik at det ikke kan instantieres. Til slutt kan vi se at vi har brukt andre gode fremgangsmåter vi diskuterte tidligere i artikkelen. Vår konstant PI er offentlig fordi vi forventer at vi trenger tilgang til den utenfor pakken. De andre konstantene vi har igjen som pakke-privat, slik at vi får tilgang til dem i pakken vår. Vi har laget alle konstantene våre statisk og endelig og kalte dem i et skrikende slangesak. Operasjonene er et bestemt verdisett, så vi har brukt en enum for å definere dem.

Vi kan se at vår spesifikke konstantklasse på pakkenivå er forskjellig fra en stor global konstantklasse fordi den er lokalisert til pakken vår og inneholder konstanter som er relevante for den pakkens klasser.

5. Konklusjon

I denne artikkelen vurderte vi fordeler og ulemper med noen av de mest populære mønstrene og antimønstrene som ble sett når du bruker konstanter i Java. Vi startet med noen grunnleggende formateringsregler, før vi dekket antimønstre. Etter å ha lært om et par vanlige antimønstre, så vi på mønstre som vi ofte ser brukt på konstanter.

Som alltid er koden tilgjengelig på GitHub.


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