Ohjelmointi

Suunnittelu staattisilla jäsenillä

Vaikka Java on suuressa määrin objektisuuntautunut, se ei ole a puhdas olio-kieli. Yksi syy siihen, että Java ei ole pelkästään olio-suuntautunut, on se, että kaikki sen sisällöt eivät ole esineitä. Esimerkiksi Java antaa sinun ilmoittaa primitiivityyppiset muuttujat (int, kellua, looginenjne.), jotka eivät ole esineitä. Ja Javalla on staattisia kenttiä ja menetelmiä, jotka ovat itsenäisiä ja erillisiä objekteista. Tässä artikkelissa annetaan neuvoja staattisten kenttien ja menetelmien käyttämisestä Java-ohjelmassa pitäen samalla suunnittelussa olio kohdennettu.

Luokan elinkaarella Java-virtuaalikoneessa (JVM) on paljon yhtäläisyyksiä kohteen elinaikaan. Aivan kuten objektilla voi olla tila, jota edustavat sen esiintymismuuttujien arvot, luokassa voi olla tila, jota edustavat sen luokan muuttujien arvot. Aivan kuten JVM asettaa esiintymämuuttujat oletusarvoihin ennen alustuskoodin suorittamista, JVM asettaa luokan muuttujat oletusarvoihin ennen alustuskoodin suorittamista. Ja kuten esineitä, luokat voidaan kerätä roskiksi, jos käynnissä oleva sovellus ei enää viittaa niihin.

Luokkien ja objektien välillä on kuitenkin merkittäviä eroja. Ehkä tärkein ero on tapa, jolla esiintymä- ja luokkamenetelmiä käytetään: esiintymistavat ovat (suurimmaksi osaksi) dynaamisesti sidottuja, mutta luokkamenetelmät ovat staattisesti sidottuja. (Kolmessa erikoistapauksessa instanssimenetelmät eivät ole dynaamisesti sidottuja: yksityisten instanssimenetelmien kutsuminen, sen sisällä menetelmät (konstruktorit) ja kutsut super avainsana. Katso lisätietoja kohdasta Resurssit.)

Toinen ero luokkien ja objektien välillä on yksityisten käyttöoikeustasojen myöntämä tietojen piilotusaste. Jos ilmentymämuuttuja julistetaan yksityiseksi, vain ilmentymämenetelmät voivat käyttää sitä. Tämän avulla voit varmistaa ilmentymätiedon eheyden ja tehdä esineistä langattomia. Loput ohjelmasta eivät voi käyttää näitä ilmentymämuuttujia suoraan, mutta niiden on käytävä läpi ilmentymämenetelmät manipuloimaan ilmentymämuuttujia. Kun haluat saada luokan käyttäytymään hyvin suunnitellun objektin tavoin, voit tehdä luokan muuttujista yksityiset ja määrittää luokkamenetelmät, jotka manipuloivat niitä. Et kuitenkaan saa niin hyvää takuuta säikeiden turvallisuudesta tai edes tietojen eheydestä tällä tavalla, koska tietyntyyppisellä koodilla on erityinen etuoikeus, joka antaa heille suoran pääsyn yksityisen luokan muuttujiin: ilmentymämenetelmiin ja jopa esim. muuttujat, voivat käyttää näitä yksityisen luokan muuttujia suoraan.

Joten staattisilla kentillä ja luokkamenetelmillä, vaikka ne ovat monin tavoin samanlaisia ​​kuin esineiden instanssikentät ja -menetelmät, on merkittäviä eroja, joiden pitäisi vaikuttaa tapaan, jolla käytät niitä suunnittelussa.

Luokkien kohtelu esineinä

Suunnitellessasi Java-ohjelmia kohtaat todennäköisesti monia tilanteita, joissa sinusta tuntuu tarvetta esineelle, joka toimii jollain tavalla kuin luokka. Voit esimerkiksi haluta objektin, jonka käyttöikä vastaa luokan kestoa. Tai saatat haluta objektin, joka rajoittaisi luokan tavoin vain yhden ilmentymä annetussa nimiavaruudessa.

Tällaisissa suunnittelutilanteissa voi olla houkuttelevaa luoda luokka ja käyttää sitä objektin tavoin luokkamuuttujien määrittelemiseksi, yksityiseksi tekemiseksi ja joidenkin luokkamuuttujia manipuloivien julkisten luokkamenetelmien määrittämiseksi. Kuten esineellä, sellaisella luokalla on tila. Hyvin suunnitellun objektin tavoin myös tilaa määrittelevät muuttujat ovat yksityisiä, ja ulkomaailma voi vaikuttaa tähän tilaan vain luokkamenetelmillä.

Valitettavasti tässä "luokka-esine" -menetelmässä on joitain ongelmia. Koska luokkamenetelmät ovat staattisesti sidottuja, luokkaesi esineesi ei nauti polymorfismin ja upcastingin joustavuudesta. (Polymorfismin ja dynaamisen sitoutumisen määritelmät ovat Design Techniques -artikkelissa Composition versus Heritage.) Polymorfismi on mahdollista ja upcasting hyödyllinen dynaamisella sitoutumisella, mutta luokan menetelmät eivät ole sidottuja dynaamisesti. Jos joku aliluokittaa luokkasi esineeksi, hän ei pysty siihen ohittaa luokkamenetelmät ilmoittamalla samannimiset luokkamenetelmät; he vain pystyvät piilottaa niitä. Kun jompaankumpaan näistä uudelleen määritetyistä luokkamenetelmistä käytetään, JVM valitsee menetelmän toteutuksen suoritettavaksi ei objektin luokan ajon aikana, vaan muuttujan tyypin mukaan kääntämisajankohtana.

Lisäksi säikeiden turvallisuus ja tietojen eheys, joka saavutetaan huolella toteuttamalla luokkamenetelmät luokassa-esineessäsi, on kuin olkesta rakennettu talo. Lankasi turvallisuus ja tietojen eheys taataan, kunhan kaikki käyttävät luokan menetelmiä manipuloimaan luokan muuttujiin tallennettua tilaa. Huolimaton tai käsittelemätön ohjelmoija voi kuitenkin, lisäämällä yhden instanssimenetelmän, joka käyttää suoraan yksityisen luokan muuttujiasi, tahattomasti huijata ja puhaltaa ja puhaltaa langan turvallisuuden ja tietojen eheyden.

Tästä syystä luokkamuuttujia ja luokkamenetelmiä koskeva pääohjeeni on:

Älä käsittele luokkia esineinä.

Toisin sanoen, älä suunnittele luokan staattisilla kentillä ja menetelmillä ikään kuin ne olisivat objektin ilmentymäkentät ja -menetelmät.

Jos haluat jonkin tilan ja käyttäytymisen, jonka elinaika vastaa luokan ikää, vältä luokan muuttujien ja luokkamenetelmien käyttämistä objektin simulointiin. Luo sen sijaan todellinen objekti ja käytä luokan muuttujaa pitääkseen siihen viittausta ja luokkamenetelmiä tarjotaksesi pääsyn objektiviittaukseen. Jos haluat varmistaa, että vain yksi tila ja käyttäytyminen esiintyy yhdessä nimiavaruudessa, älä yritä suunnitella luokkaa, joka simuloi objektia. Luo sen sijaan a singleton - esine, jolla on vain yksi esiintymä nimitilaa kohden.

Joten mihin luokan jäsenet ovat hyviä?

Mielestäni paras ajattelutapa kasvatettavaksi Java-ohjelmia suunniteltaessa on ajatella esineitä, esineitä, esineitä. Keskity suurten kohteiden suunnitteluun ja ajattele luokkia ensisijaisesti esineiden piirustuksina - rakenne, jossa määrität ilmentymämuuttujat ja ilmentymämenetelmät, jotka muodostavat hyvin suunnitellut objektisi. Sen lisäksi voit ajatella luokkia tarjoavan muutamia erikoispalveluja, joita objektit eivät pysty tarjoamaan tai eivät voi tarjota yhtä tyylikkäästi. Ajattele luokkia seuraavasti:

  • oikea paikka määritellä "hyödyllisyysmenetelmät" (menetelmät, jotka ottavat syötteen ja tuottavat tuloksia vain välitettyjen parametrien ja palautusarvon kautta)
  • tapa hallita pääsyä esineisiin ja tietoihin

Hyödyllisyysmenetelmät

Menetelmät, jotka eivät manipuloi tai käytä objektin tai luokan tilaa, jota kutsun "apuohjelmamenetelmiksi". Hyödyllisyysmenetelmät palauttavat vain osan (tai arvoja), jotka on laskettu vain menetelmälle välitetyistä tiedoista parametreina. Sinun tulisi tehdä tällaisista menetelmistä staattisia ja sijoittaa ne luokkaan, joka liittyy läheisimmin menetelmän tarjoamaan palveluun.

Esimerkki hyödyllisyysmenetelmästä on Merkkijono copyValueOf (char [] data) luokan menetelmä Merkkijono. Tämä menetelmä tuottaa tuotoksen, tyypin palautusarvon Merkkijono, vain sen syöttöparametrista, taulukko hiiltyäs. Koska copyValueOf () se ei käytä eikä vaikuta minkään objektin tai luokan tilaan, se on apuohjelma. Ja kuten kaikkien hyödyllisyysmenetelmien pitäisi olla, copyValueOf () on luokan menetelmä.

Joten yksi tärkeimmistä tavoista käyttää luokkamenetelmiä on hyödyllisyysmenetelmät - menetelmät, jotka palauttavat tuotoksen, joka lasketaan yksinomaan syöttöparametreista. Muihin luokkamenetelmien käyttötarkoituksiin liittyy luokan muuttujia.

Luokan muuttujat tietojen piilottamiseen

Yksi olio-ohjelmoinnin perusmääräyksistä on tietojen piilottaminen - tietojen käytön rajoittaminen ohjelman osien välisten riippuvuuksien minimoimiseksi. Jos tietyllä tiedolla on rajoitettu käytettävyys, kyseiset tiedot voivat muuttua rikkomatta niitä ohjelman osia, jotka eivät voi käyttää tietoja.

Jos esimerkiksi objektia tarvitaan vain tietyn luokan ilmentymille, viittaus siihen voidaan tallentaa yksityisen luokan muuttujaan. Tämä antaa kaikille tämän luokan esiintymille kätevän pääsyn kyseiseen objektiin - esiintymät käyttävät sitä vain suoraan - mutta mikään muu koodi missään muualla ohjelmassa ei pääse siihen. Samalla tavalla voit käyttää paketin käyttöoikeutta ja suojattuja luokan muuttujia vähentämään objektien näkyvyyttä, jotka kaikkien paketin ja alaluokkien jäsenten on jaettava.

Julkiset luokan muuttujat ovat erilainen tarina. Jos julkinen luokan muuttuja ei ole lopullinen, se on globaali muuttuja: se ikävä rakenne, joka on tietojen piilottamisen vastakohta. Julkisen luokan muuttujalle ei ole koskaan mitään tekosyitä, ellei se ole lopullinen.

Lopulliset julkisen luokan muuttujat, olivatpa ne primitiivisiä tyyppejä tai objektiviittauksia, palvelevat hyödyllistä tarkoitusta. Primitiivisten tyyppien tai tyyppien muuttujat Merkkijono ovat yksinkertaisesti vakioita, jotka yleensä auttavat tekemään ohjelmista joustavampia (helpommin muutettavissa). Vakioita käyttävää koodia on helpompi muuttaa, koska voit muuttaa vakioarvoa yhdessä paikassa. Viitetyyppien julkisten lopullisten luokan muuttujien avulla voit antaa maailmanlaajuisen pääsyn kohteisiin, joita tarvitaan maailmanlaajuisesti. Esimerkiksi, System.in, System.outja System.err ovat julkisia lopullisen luokan muuttujia, jotka antavat globaalin pääsyn vakiotulolähtöihin ja virtavirtoihin.

Tärkein tapa luokkamuuttujien tarkastelemiseen on siis mekanismi, jolla rajoitetaan muuttujien tai objektien saatavuutta (tarkoittaen, piilottaa). Kun yhdistät luokan menetelmät luokan muuttujiin, voit ottaa käyttöön vielä monimutkaisempia käyttöoikeuskäytäntöjä.

Luokkamenetelmien käyttäminen luokan muuttujien kanssa

Sen lisäksi, että toimitaan hyödyllisyysmenetelminä, luokkamenetelmiä voidaan käyttää luokkamuuttujiin tallennettujen objektien käytön hallintaan - erityisesti sen hallintaan, miten objektit luodaan tai hallitaan. Kaksi esimerkkiä tällaisesta luokkamenetelmästä ovat setSecurityManager () ja getSecurityManager () luokan menetelmät Järjestelmä. Sovelluksen tietoturvapäällikkö on objekti, jota tavallisten tulo-, lähtö- ja virtavirtojen tavoin tarvitaan monissa eri paikoissa. Toisin kuin tavalliset I / O-virtaobjektit, viittausta suojauksenhallintaan ei kuitenkaan tallenneta julkiseen lopullisen luokan muuttujaan. Suojauksen hallintaobjekti on tallennettu yksityisen luokan muuttujaan, ja set and get -menetelmät toteuttavat objektille erityisen käyttöoikeuskäytännön.

Java-tietoturvamalli asettaa erityisen rajoituksen tietoturvahallinnalle. Ennen Java 2: ta (aiemmin nimellä JDK 1.2) sovellus aloitti elämänsä ilman tietoturvapäällikköä (getSecurityManager () palasi tyhjä). Ensimmäinen puhelu setSecurityManager () perusti turvallisuuspäällikön, jota sen jälkeen ei sallittu vaihtaa. Kaikki seuraavat puhelut numeroon setSecurityManager () antaisi turvallisuuspoikkeuksen. Java 2: ssa sovellus käynnistyy aina tietoturvahallinnan kanssa, mutta edellisten versioiden tapaan setSecurityManager () menetelmä antaa sinun muuttaa turvallisuuspäällikkö enintään kerran.

Tietoturvapäällikkö tarjoaa hyvän esimerkin siitä, miten luokkamenetelmiä voidaan käyttää yhdessä yksityisten luokan muuttujien kanssa erityisen käyttökäytännön toteuttamiseksi luokkamuuttujien viittaamille objekteille. Apuohjelmamenetelmien lisäksi ajattele luokkamenetelmiä keinona luoda erityiset käyttökäytännöt objektiviittauksille ja luokan muuttujiin tallennetuille tiedoille.

Ohjeet

Tässä artikkelissa annettu pääneuvo on:

Älä käsittele luokkia esineinä.

Jos tarvitset objektia, tee esine. Rajoita luokkamuuttujien ja -menetelmien käyttö määrittelemään hyödyllisyysmenetelmät ja toteuttamaan erityyppisiä käyttökäytäntöjä luokan muuttujiin tallennetuille kohteille ja primitiivisille tyypeille. Vaikka Java ei ole puhdas olio-orientoitu kieli, Java on kuitenkin suuressa määrin olio-suuntautunut, ja suunnittelun tulisi heijastaa sitä. Ajattele esineitä.

Ensikuussa

Seuraavan kuukauden Suunnittelutekniikat artikkeli on tämän sarakkeen viimeinen. Aloitan pian kirjan suunnittelutekniikkamateriaaliin perustuvan kirjan kirjoittamisen, Joustava Javaja sijoittaa kyseisen materiaalin verkkosivustolleni. Joten seuraa tätä projektia ja lähetä minulle palautetta. Kuukauden tai kahden tauon jälkeen palaan takaisin JavaWorld ja SunWorld uudella sarakkeella, joka keskittyi Jiniin.

Pyyntö lukijoiden osallistumisesta

Kannustan kommenttisi, kritiikkisi, ehdotuksesi, liekkisi - kaikenlaista palautetta - tässä sarakkeessa esitetystä materiaalista. Jos olet eri mieltä jostakin tai sinulla on jotain lisättävää, ilmoita siitä minulle.

Voit osallistua tätä materiaalia käsittelevään keskustelufoorumiin, kirjoittaa kommentin artikkelin alaosassa olevan lomakkeen kautta tai lähettää minulle sähköpostia suoraan alla olevassa linkissä.

Bill Venners on kirjoittanut ohjelmistoja ammattimaisesti 12 vuotta. Piilaaksossa toimiva hän tarjoaa ohjelmistokonsultointi- ja koulutuspalveluja nimellä Artima Software Company. Vuosien varrella hän on kehittänyt ohjelmistoja kulutuselektroniikka-, koulutus-, puolijohde- ja henkivakuutusteollisuudelle. Hän on ohjelmoinut monilla kielillä monilla alustoilla: kokoonpanokieli useille mikroprosessoreille, C Unixille, C ++ Windowsille, Java Webissä. Hän on kirjoittanut McGraw-Hillin julkaiseman kirjan Inside the Java Virtual Machine.