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 Vastaanotin
kä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
, Vastaanotin
ja 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 Vaihtaa
s 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
, KomentoVastaanotin
ja 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 onVaihtaa
vastaava kuin edellisessä esimerkissä. Se tallentaa geneerisen lääkkeenTransactionCommand
esine yksityisestimyCommand
muuttuja. KunrunCommands ()
kutsutaan, se kutsuusuorittaa ()
sopivistaTransactionCommand
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.