Ohjelmointi

Java-vinkki 68: Opi ottamaan komentokuvio käyttöön Java-ohjelmassa

Suunnittelumallit paitsi kiihdyttävät olio-projektin (OO) suunnitteluvaihetta myös lisäävät kehitystiimin tuottavuutta ja ohjelmiston laatua. A Komennokuvio on objektin käyttäytymismalli, jonka avulla voimme saavuttaa täydellisen irrotuksen lähettäjän ja vastaanottajan välillä. (A lähettäjä on objekti, joka kutsuu operaation, ja a vastaanotin on objekti, joka vastaanottaa pyynnön suorittaa tietty operaatio. Kanssa irrotus, lähettäjällä ei ole tietoa Vastaanotinkäyttöliittymä.) Termi pyyntö Tässä viitataan suoritettavaan komentoon. Komentokuvion avulla voimme myös muuttaa, milloin ja miten pyyntö täytetään. Siksi komentokuvio tarjoaa meille joustavuutta ja laajennettavuutta.

Ohjelmointikielillä, kuten C, toiminnon osoittimet käytetään poistamaan jättimäisiä kytkinlausekkeita. (Katso tarkempi kuvaus kohdasta "Java Tip 30: Polymorphism and Java".) Koska Java: lla ei ole toiminto-osoittimia, voimme käyttää komentokuviota soittopyyntöjen toteuttamiseen. Näet tämän toiminnassa alla olevassa ensimmäisessä koodiesimerkissä, nimeltään TestCommand.java.

Kehittäjät, jotka ovat tottuneet käyttämään toiminto-osoittimia toisella kielellä, saattavat houkutella käyttämään Menetelmä Reflection API: n objektit samalla tavalla. Esimerkiksi artikkelissa "Java Reflection" Paul Tremblett näyttää, kuinka Reflectionin avulla voidaan toteuttaa tapahtumia käyttämättä kytkinlausekkeita. Olen vastustanut tätä kiusausta, koska Sun ei suosittele Reflection API: n käyttöä, kun muut Java-ohjelmointikielelle luonnollisemmat työkalut riittävät. (Katso Resurssit linkeistä Tremblettin artikkeliin ja Sunin Reflection-opasivulle.) Ohjelmasi on helpompi virheenkorjaus ja ylläpito, jos et käytä Menetelmä esineitä. Sen sijaan sinun tulisi määritellä käyttöliittymä ja toteuttaa se luokissa, jotka suorittavat tarvittavan toiminnon.

Siksi ehdotan, että käytät komentosarjaa yhdistettynä Javan dynaamiseen lataus- ja sidontamekanismiin toiminto-osoittimien toteuttamiseksi. (Lisätietoja Java: n dynaamisesta lataus- ja sidontamekanismista, katso James Goslingin ja Henry McGiltonin "Java-kieliympäristö - Valkoinen kirja", joka on lueteltu Resurssit-luettelossa.)

Noudattamalla yllä olevaa ehdotusta hyödynnämme komentomallin soveltaman polymorfismin jättimäisten kytkinlausekkeiden eliminoimiseksi, mikä johtaa laajennettaviin järjestelmiin. Hyödynnämme myös Javan ainutlaatuisia dynaamisia lataus- ja sidontamekanismeja dynaamisen ja dynaamisesti laajennettavan järjestelmän rakentamiseksi. Tämä on havainnollistettu alla olevassa toisessa esimerkkikoodinäytteessä, nimeltään TestTransactionCommand.java.

Komennokuvio muuttaa pyynnön itse objektiksi. Tämä objekti voidaan tallentaa ja siirtää ympäriinsä kuten muutkin objektit. Avain tähän malliin on a Komento käyttöliittymä, joka ilmoittaa käyttöliittymän toimintojen suorittamiseksi. Yksinkertaisimmassa muodossaan tämä käyttöliittymä sisältää abstraktin suorittaa operaatio. Jokainen betoni Komento luokka määrittää vastaanottimen ja toiminnan parin tallentamalla Vastaanotin instanssimuuttujana. Se tarjoaa erilaisia ​​toteutuksia suorittaa() tapa kutsua pyyntö. Vastaanotin hänellä on tarvittavat tiedot pyynnön toteuttamiseksi.

Alla olevassa kuvassa 1 on esitetty Vaihtaa - yhteenlaskettu Komento esineitä. Sillä on flipUp () ja flipDown () käyttöliittymässä. Vaihtaa kutsutaan kutsuttaja koska se kutsuu suoritustoiminnon komentorajapinnassa.

Konkreettinen komento, LightOnCommand, toteuttaa suorittaa komentorajapinnan käyttö. Sillä on tietoa soittaa sopiville Vastaanotin kohteen toiminta. Se toimii tässä tapauksessa sovittimena. Termillä sovitin, Tarkoitan, että betoni Komento esine on yksinkertainen liitin, joka yhdistää Kutsuja ja Vastaanotin eri rajapinnoilla.

Asiakas välittää Kutsuja, Vastaanotinja konkreettiset komento-objektit.

Kuvio 2, sekvenssikaavio, näyttää objektien väliset vuorovaikutukset. Se kuvaa miten Komento irrottaa Kutsuja alkaen Vastaanotin (ja pyyntö, jonka se suorittaa). Asiakas luo konkreettisen komennon parametroimalla konstruktorin sopivalla Vastaanotin. Sitten se tallentaa Komento että Kutsuja. Kutsuja kutsuu takaisin konkreettisen komennon, jolla on tietoa halutun suorittamiseksi Toiminta() operaatio.

Asiakas (luettelossa oleva pääohjelma) luo konkreettisen Komento esine ja asettaa sen Vastaanotin. Kuten Kutsuja esine, Vaihtaa varastoi betonin Komento esine. Kutsuja antaa pyynnön soittamalla suorittaa on Komento esine. Betoni Komento objekti kutsuu toimintojaan Vastaanotin pyynnön toteuttamiseksi.

Tärkein idea on, että konkreettinen komento rekisteröi itsensä Kutsuja ja Kutsuja kutsuu sen takaisin suorittamalla komennon Vastaanotin.

Komentokuvion esimerkkikoodi

Katsotaanpa yksinkertainen esimerkki, joka kuvaa komentokuvion avulla saavutettua takaisinsoittomekanismia.

Esimerkissä näkyy a Tuuletin ja a Kevyt. Tavoitteenamme on kehittää a Vaihtaa joka voi kytkeä objektin päälle tai pois päältä. Näemme, että Tuuletin ja Kevyt on erilaisia ​​käyttöliittymiä, mikä tarkoittaa Vaihtaa on oltava riippumaton Vastaanotin tai sillä ei ole tietoa koodista> Vastaanottimen käyttöliittymä. Tämän ongelman ratkaisemiseksi meidän on parametroitava kaikki Vaihtaas sopivalla komennolla. Ilmeisesti Vaihtaa kytketty Kevyt on erilainen komento kuin Vaihtaa kytketty Tuuletin. Komento luokan on oltava abstrakti tai käyttöliittymä toimiakseen.

Kun a Vaihtaa kutsutaan, se parametroidaan sopivalla komentojoukolla. Komennot tallennetaan yksityisinä muuttujina Vaihtaa.

Kun flipUp () ja flipDown () operaatioita kutsutaan, he yksinkertaisesti tekevät tarvittavan komennon suorittaa (). Vaihtaa ei tiedä mitä tapahtuu seurauksena suorittaa () soitetaan.

TestCommand.java-luokan tuuletin {public void startRotate () {System.out.println ("Tuuletin pyörii"); } public void stopRotate () {System.out.println ("Tuuletin ei pyöri"); }} luokan valo {public void turnOn () {System.out.println ("Valo palaa"); } public void turnOff () {System.out.println ("Valo ei pala"); }} luokan vaihto {yksityinen komento UpCommand, DownCommand; julkinen kytkin (komento ylös, komento alas) {UpCommand = ylös; // konkreettinen komento rekisteröi itsensä kutsuttajalla DownCommand = Down; } void flipUp () {// kutsuja kutsuu takaisin konkreettisen komennon, joka suorittaa komennon vastaanottimen UpCommandissa. suorittaa (); } void flipDown () {DownCommand. suorittaa (); }} luokan LightOnCommand toteuttaa komennon {private Light myLight; julkinen LightOnCommand (valo L) {myLight = L; } public void suorittaa () {myLight. kiihottua( ); }} luokan LightOffCommand toteuttaa komennon {private Light myLight; julkinen LightOffCommand (valo L) {myLight = L; } public void suorittaa () {myLight. sammuttaa( ); }} luokka FanOnCommand toteuttaa komennon {yksityinen tuuletin myFan; julkinen FanOnCommand (tuuletin F) {myFan = F; } public void suorittaa () {myFan. startRotate (); }} luokka FanOffCommand toteuttaa komennon {yksityinen tuuletin myFan; julkinen FanOffCommand (tuuletin F) {myFan = F; } public void suorittaa () {myFan. stopRotate (); }} public class TestCommand {public static void main (String [] args) {Light testLight = uusi valo (); LightOnCommand testLOC = uusi LightOnCommand (testLight); LightOffCommand testLFC = uusi LightOffCommand (testLight); Kytkin testSwitch = uusi kytkin (testLOC, testLFC); testSwitch.flipUp (); testSwitch.flipDown (); Puhaltimen testiFan = uusi tuuletin (); FanOnCommand foc = uusi FanOnCommand (testFan); FanOffCommand ffc = uusi FanOffCommand (testFan); Kytkin ts = uusi kytkin (foc, ffc); ts.flipUp (); ts.flipDown (); }} Command.java julkinen käyttöliittymä Command {public abstract void execute (); } 

Huomaa yllä olevassa koodiesimerkissä, että komentokuvio irrottaa kokonaan operaation kutsuvan objektin - (Vaihtaa ) - niistä, joilla on tietoa sen suorittamiseen - Kevyt ja Tuuletin. Tämä antaa meille paljon joustavuutta: pyynnön esittävän kohteen on tiedettävä vain, miten se voidaan lähettää; sen ei tarvitse tietää, miten pyyntö toteutetaan.

Komennomalli tapahtumien toteuttamiseksi

Komentokuvio tunnetaan myös nimellä toiminta tai tapahtumakuvio. Tarkastellaan palvelinta, joka hyväksyy ja käsittelee asiakkaiden toimittamat tapahtumat TCP / IP-liitäntäyhteyden kautta. Nämä tapahtumat koostuvat komennosta, jota seuraa nolla tai useampia argumentteja.

Kehittäjät saattavat käyttää kytkinlauseketta kotelon kanssa jokaiselle komennolle. Käyttö Vaihtaa lausunnot koodauksen aikana ovat merkki huonosta suunnittelusta olio-projektin suunnitteluvaiheessa. Komennot edustavat olio-suuntautunutta tapaa tukea tapahtumia, ja niitä voidaan käyttää ratkaisemaan tämä suunnitteluongelma.

Ohjelman asiakaskoodissa TestTransactionCommand.java, kaikki pyynnöt kapseloidaan yleiseen TransactionCommand esine. TransactionCommand konstruktori on asiakkaan luoma ja se on rekisteröity CommandManager. Jonossa olevat pyynnöt voidaan suorittaa eri aikoina soittamalla runCommands (), mikä antaa meille paljon joustavuutta. Se antaa meille myös mahdollisuuden koota komennot komposiittikomennoksi. minulla on myös KomentoArgumentti, KomentoVastaanotinja CommandManager luokat ja alaluokat TransactionCommand -- nimittäin Lisää komento ja VähennäKomento. Seuraavassa on kuvaus kustakin näistä luokista:

  • KomentoArgumentti on auttajaluokka, joka tallentaa komennon argumentit. Se voidaan kirjoittaa uudelleen yksinkertaistamaan tehtävää välittää suuri tai vaihteleva määrä minkä tahansa tyyppisiä argumentteja.

  • KomentoVastaanotin toteuttaa kaikki komentojen käsittelymenetelmät ja toteutetaan Singleton-mallina.

  • CommandManager on kutsuttaja ja on Vaihtaa vastaava kuin edellisessä esimerkissä. Se tallentaa geneerisen lääkkeen TransactionCommand esine yksityisesti myCommand muuttuja. Kun runCommands () kutsutaan, se kutsuu suorittaa () sopivista TransactionCommand esine.

Java-ohjelmassa on mahdollista etsiä luokan määritelmä, jolle annetaan merkkijono, joka sisältää sen nimen. vuonna suorittaa () käyttö TransactionCommand luokka, lasken luokan nimen ja linkitän sen dynaamisesti käynnissä olevaan järjestelmään - ts. luokat ladataan lennossa tarpeen mukaan. Käytän tapahtumakomennon alaluokan nimenä nimeämiskäytäntöä, komento, joka on liitetty merkkijonolla "Komento", jotta se voidaan ladata dynaamisesti.

Huomaa, että Luokka objektin palauttama newInstance () on valettava sopivaan tyyppiin. Tämä tarkoittaa, että uuden luokan on joko toteutettava käyttöliittymä tai aliluokka olemassa oleva luokka, joka on ohjelman tiedossa kääntöhetkellä. Tässä tapauksessa, koska toteutamme Komento käyttöliittymä, tämä ei ole ongelma.

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