Programavimas

68 „Java“ patarimas: sužinokite, kaip „Java“ įdiegti komandų šabloną

Dizaino modeliai ne tik pagreitina į objektą orientuoto (OO) projekto projektavimo etapą, bet ir padidina kūrėjų komandos produktyvumą ir programinės įrangos kokybę. A Komandos modelis yra objekto elgesio modelis, leidžiantis mums visiškai atsieti siuntėją ir imtuvą. (A siuntėjas yra objektas, kuris iškviečia operaciją, ir a imtuvas yra objektas, gaunantis prašymą atlikti tam tikrą operaciją. Su atsiejimas, siuntėjas neturi žinių apie Imtuvassąsaja.) Terminas prašymą čia nurodo komandą, kurią reikia vykdyti. „Command“ modelis taip pat leidžia mums keisti, kada ir kaip įvykdoma užklausa. Todėl komandų modelis suteikia mums lankstumo ir išplėtimo galimybių.

Programavimo kalbomis, tokiomis kaip C, funkcijų rodyklės yra naudojami milžiniškų jungiklių teiginiams pašalinti. (Išsamesnį aprašymą žr. „Java 30 patarimas: polimorfizmas ir„ Java “.) Kadangi„ Java “neturi funkcijų rodyklių, mes galime naudoti komandų šabloną atgaliniams skambučiams įgyvendinti. Tai pamatysite pirmame žemiau pateiktame kodo pavyzdyje, vadinamame TestCommand.java.

Kūrėjai, įpratę naudoti funkcijų rodykles kita kalba, gali susigundyti naudoti Metodas „Reflection“ API objektai tokiu pačiu būdu. Pavyzdžiui, savo straipsnyje „Java Reflection“ Paulas Tremblettas parodo, kaip naudoti „Reflection“ operacijoms įgyvendinti nenaudojant jungiklių sakinių. Aš atsispiriau šiai pagundai, nes „Sun“ nepataria naudoti „Reflection“ API, kai pakaks kitų natūralesnių „Java“ programavimo kalbos įrankių. (Žr. Šaltinius, kuriuose pateikiamos nuorodos į „Tremblett“ straipsnį ir „Sun“ atspindžio pamokų puslapį.) Jei nenaudosite, jūsų programą bus lengviau derinti ir prižiūrėti. Metodas objektai. Vietoj to turėtumėte apibrėžti sąsają ir ją įdiegti klasėse, kurios atlieka reikiamą veiksmą.

Todėl funkcijų rodyklėms įgyvendinti siūlau naudoti komandų šabloną kartu su dinaminiu „Java“ įkėlimo ir įrišimo mechanizmu. (Išsamesnės informacijos apie dinaminį „Java“ įkėlimo ir įrišimo mechanizmą žr. Jameso Goslingo ir Henry McGiltono „Java kalbos aplinka - baltoji knyga“, pateiktą šaltiniuose.)

Laikydamiesi pirmiau pateikto pasiūlymo, mes išnaudojame polimorfizmą, kurį suteikia „Command“ šablonas, kad pašalintume milžiniškus jungiklių teiginius, dėl kurių atsiranda išplėstinės sistemos. Mes taip pat išnaudojame unikalius „Java“ dinaminius įkėlimo ir susiejimo mechanizmus, kad sukurtume dinamišką ir dinamiškai išplečiamą sistemą. Tai iliustruoja antrasis žemiau pateiktas kodo pavyzdys, vadinamas TestTransactionCommand.java.

Komandos modelis paverčia patį prašymą objektu. Šį objektą galima laikyti ir perduoti aplinkui kaip kitus objektus. Šio modelio raktas yra a Komanda sąsaja, kuri deklaruoja sąsają operacijoms vykdyti. Paprasčiausia forma šioje sąsajoje yra abstraktus vykdyti operacija. Kiekvienas betonas Komanda klasėje nurodoma imtuvo ir veiksmo pora, saugant Imtuvas kaip egzemplioriaus kintamasis. Tai suteikia skirtingą programos įgyvendinimą vykdyti () būdas iškviesti užklausą. Imtuvas turi žinių, reikalingų prašymui įvykdyti.

Žemiau pateiktame 1 paveiksle pavaizduota Perjungti - visuma Komanda objektai. Tai turi apversti aukštyn() ir „flipDown“ () operacijas savo sąsajoje. Perjungti yra vadinamas kviestinis nes komandų sąsajoje iškviečia vykdymo operaciją.

Konkreti komanda, „LightOnCommand“, įgyvendina vykdyti komandos sąsajos veikimas. Ji turi žinių paskambinti tinkamam Imtuvas objekto veikimas. Šiuo atveju jis veikia kaip adapteris. Pagal terminą adapteris, Turiu omeny, kad betonas Komanda objektas yra paprasta jungtis, jungianti Kvietėjas ir Imtuvas su skirtingomis sąsajomis.

Klientas akimirksniu Kvietėjas, Imtuvasir konkretūs komandos objektai.

2 paveiksle, sekos schemoje, parodoma objektų sąveika. Tai iliustruoja kaip Komanda atsieti Kvietėjas nuo Imtuvas (ir jo įvykdytą prašymą). Klientas sukuria konkrečią komandą, parametruodamas savo konstruktorių tinkamu Imtuvas. Tada jis saugo Komanda viduje konors Kvietėjas. Kvietėjas atšaukia konkrečią komandą, kuri turi žinių norimam įvykdyti Veiksmas () operacija.

Klientas (pagrindinė programa sąraše) sukuria konkretų Komanda objektas ir nustato jo Imtuvas. Kaip Kvietėjas objektas, Perjungti sandėliuoja betoną Komanda objektas. Kvietėjas išduoda prašymą skambindamas vykdyti ant Komanda objektas. Betonas Komanda objektas iškviečia jo operacijas Imtuvas įvykdyti prašymą.

Pagrindinė mintis yra ta, kad konkreti komanda užsiregistruoja Kvietėjas ir Kvietėjas skambina atgal, vykdydamas komandą Imtuvas.

Komandos šablono pavyzdinis kodas

Pažvelkime į paprastą pavyzdį, iliustruojantį atgalinio ryšio mechanizmą, pasiektą naudojant „Command“ modelį.

Pavyzdys rodo a Ventiliatorius ir a Šviesa. Mūsų tikslas yra sukurti a Perjungti kuris gali įjungti arba išjungti objektą. Mes matome, kad Ventiliatorius ir Šviesa turi skirtingas sąsajas, o tai reiškia Perjungti turi būti nepriklausoma nuo Imtuvas sąsaja arba ji neturi žinių apie kodą> Imtuvo sąsaja. Norėdami išspręsti šią problemą, turime nustatyti kiekvieną iš parametrų Perjungtis su atitinkama komanda. Akivaizdu, kad Perjungti prijungtas prie Šviesa turės kitą komandą nei Perjungti prijungtas prie Ventiliatorius. Komanda klasė turi būti abstrakti arba sąsaja, kad tai veiktų.

Kai konstruktorius a Perjungti yra iškviečiamas, jis yra parametruojamas atitinkamu komandų rinkiniu. Komandos bus saugomos kaip privatūs Perjungti.

Kai apversti aukštyn() ir „flipDown“ () iškviečiamos operacijos, jos tiesiog atliks atitinkamą komandą vykdyti (). Perjungti neįsivaizduos, kas nutiks dėl to vykdyti () skambinama.

TestCommand.java klasė „Fan“ {public void startRotate () {System.out.println ("Ventiliatorius sukasi"); } public void stopRotate () {System.out.println ("Ventiliatorius nesisuka"); }} klasės šviesa {public void turnOn () {System.out.println ("Šviesa įjungta"); } public void turnOff () {System.out.println ("Šviesa išjungta"); }} klasės jungiklis {privati ​​komanda „UpCommand“, „DownCommand“; viešasis jungiklis (komanda aukštyn, žemyn) {upCommand = aukštyn; // konkreti komanda registruojasi pašaukikliu DownCommand = Down; } void flipUp () {// iškvietėjas iškviečia konkrečią komandą, kuri vykdo komandą imtuve „UpCommand“. vykdyti (); } void flipDown () {DownCommand. vykdyti (); }} klasės „LightOnCommand“ įgyvendina komandą {privatus „Light myLight“; viešoji „LightOnCommand“ (šviesa L) {myLight = L; } public void vykdyti () {myLight. įjungti( ); }} klasės „LightOffCommand“ įgyvendina komandą {privatus „Light myLight“; viešoji „LightOffCommand“ (šviesa L) {myLight = L; } public void vykdyti () {myLight. Išjunk( ); }} klasės „FanOnCommand“ įgyvendina komandą {privatus gerbėjas „myFan“; public FanOnCommand (Fan F) {myFan = F; } public void vykdyti () {myFan. startRotate (); }} klasės „FanOffCommand“ įgyvendina komandą {privatus gerbėjas „myFan“; viešas „FanOffCommand“ (F ventiliatorius) {myFan = F; } public void vykdyti () {myFan. stopRotate (); }} public class TestCommand {public static void main (String [] args) {Šviesos testLight = nauja Šviesa (); „LightOnCommand testLOC“ = nauja „LightOnCommand“ (testLight); „LightOffCommand testLFC“ = nauja „LightOffCommand“ (testLight); Jungiklis testSwitch = naujas jungiklis (testLOC, testLFC); testSwitch.flipUp (); testSwitch.flipDown (); Ventiliatoriaus testas Ventiliatorius = naujas ventiliatorius (); „FanOnCommand foc“ = naujas „FanOnCommand“ (testFan); FanOffCommand ffc = naujas FanOffCommand (testFan); Jungiklis ts = naujas jungiklis (foc, ffc); ts.flipUp (); ts.flipDown (); }} Command.java viešoji sąsaja Command {public abstract void execute (); } 

Pirmiau pateiktame kodo pavyzdyje atkreipkite dėmesį, kad komandos modelis visiškai atsieja objektą, kuris iškviečia operaciją - (Perjungti) - iš tų, kurie turi žinių tai atlikti - Šviesa ir Ventiliatorius. Tai suteikia mums daug lankstumo: prašymą pateikiantis objektas turi žinoti tik kaip jį išduoti; jai nereikia žinoti, kaip bus vykdoma užklausa.

Komandų šablonas operacijoms įgyvendinti

Komandos modelis taip pat žinomas kaip veiksmas arba sandorio modelis. Panagrinėkime serverį, kuris priima ir apdoroja operacijas, kurias klientai teikia per TCP / IP lizdo jungtį. Šias operacijas sudaro komanda, po kurios pateikiama nulis ar daugiau argumentų.

Kūrėjai kiekvienai komandai gali naudoti jungiklio sakinį su didžiosiomis ir mažosiomis raidėmis. Naudojimas Perjungti sakiniai kodavimo metu yra blogo dizaino ženklas projektavimo objektui skirto projekto etape. Komandos yra objektyvus būdas palaikyti operacijas ir gali būti naudojamos šiai dizaino problemai išspręsti.

Programos kliento kode TestTransactionCommand.java, visos užklausos yra sujungtos į bendrąją „TransactionCommand“ objektas. „TransactionCommand“ konstruktorių sukuria klientas ir jis yra užregistruotas „CommandManager“. Eilėje esančias užklausas galima įvykdyti skirtingu laiku paskambinus „runCommands“ (), kuris suteikia mums daug lankstumo. Tai taip pat suteikia mums galimybę surinkti komandas į sudėtinę komandą. aš taip pat turiu „CommandArgument“, „CommandReceiver“ir „CommandManager“ klasės ir poklasiai „TransactionCommand“ - būtent „AddCommand“ ir SubtractCommand. Toliau pateikiamas kiekvienos iš šių klasių aprašymas:

  • „CommandArgument“ yra pagalbininkų klasė, kurioje saugomi komandos argumentai. Ją galima perrašyti, kad būtų supaprastinta užduotis perduoti didelį ar kintantį bet kokio tipo argumentų skaičių.

  • „CommandReceiver“ įgyvendina visus komandų apdorojimo metodus ir yra įgyvendinamas kaip „Singleton“ modelis.

  • „CommandManager“ yra kviestinis ir yra Perjungti atitikmuo iš ankstesnio pavyzdžio. Jame saugomi generiniai vaistai „TransactionCommand“ objektas savo privačiame „myCommand“ kintamasis. Kada „runCommands“ () yra iškviečiamas, jis vadina vykdyti () tinkamų „TransactionCommand“ objektas.

„Java“ programoje galima ieškoti klasės apibrėžimo, suteikiant eilutę su jos pavadinimu. Viduje konors vykdyti () operacija „TransactionCommand“ klasę, aš apskaičiuoju klasės pavadinimą ir dinamiškai susieju jį su veikiančia sistema - tai yra, klasės, kaip reikalaujama, yra pakraunamos skraidant. Kaip operacijos komandos poklasio pavadinimą naudoju pavadinimų suteikimo tvarką, komandos pavadinimą, sujungtą eilute „Komanda“, kad ją būtų galima dinamiškai įkelti.

Atkreipkite dėmesį, kad Klasė objektas, kurį grąžino newInstance () turi būti išmesta į atitinkamą tipą. Tai reiškia, kad naujoji klasė turi arba įdiegti sąsają, arba poklasį esamą klasę, kuri programai žinoma kompiliavimo metu. Šiuo atveju, kadangi mes įgyvendiname Komanda sąsaja, tai nėra problema.

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