Programmēšana

Java padoms 68: Uzziniet, kā Java ieviest komandu modeli

Projektēšanas modeļi ne tikai paātrina objektorientēta (OO) projekta projektēšanas posmu, bet arī palielina izstrādes komandas produktivitāti un programmatūras kvalitāti. A Komandas modelis ir objekta uzvedības modelis, kas ļauj mums panākt pilnīgu atsaistīšanu starp sūtītāju un saņēmēju. (A sūtītājs ir objekts, kas izsauc operāciju, un a uztvērējs ir objekts, kas saņem pieprasījumu veikt noteiktu darbību. Ar atsaistīšana, sūtītājam nav zināšanu par Uztvērējssaskarne.) Termins pieprasījumu šeit attiecas uz komandu, kas jāizpilda. Komandas modelis arī ļauj mums mainīt, kad un kā tiek izpildīts pieprasījums. Tāpēc komandu modelis mums nodrošina elastību, kā arī paplašināmību.

Tādās programmēšanas valodās kā C, funkciju norādes tiek izmantoti, lai izslēgtu milzu slēdža paziņojumus. (Detalizētāku aprakstu skatiet sadaļā "Java Tip 30: Polimorfisms un Java".) Tā kā Java nav funkciju norāžu, mēs varam izmantot komandu modeli, lai ieviestu atzvanīšanu. Jūs redzēsiet to darbībā pirmajā koda piemērā, ko sauc TestCommand.java.

Izstrādātājiem, kuri pieraduši izmantot funkciju rādītājus citā valodā, varētu rasties kārdinājums to izmantot Metode Reflection API objektus tādā pašā veidā. Piemēram, Pols Tremblets savā rakstā "Java Reflection" parāda, kā izmantot Reflection, lai ieviestu darījumus, neizmantojot komutatoru paziņojumus. Es esmu pretojies šim kārdinājumam, jo ​​Sun neiesaka izmantot Reflection API, kad pietiks ar citiem Java programmēšanas valodai dabiskākiem rīkiem. (Skatiet resursus, kuros atrodamas saites uz Tremblett rakstu un Sun pārdomu lapas lapu.) Ja neizmantojat, programmu būs vieglāk atkļūdot un uzturēt. Metode objektiem. Tā vietā jums vajadzētu definēt saskarni un ieviest to klasēs, kas veic nepieciešamo darbību.

Tāpēc, lai ieviestu funkciju rādītājus, es iesaku jums izmantot komandu modeli kopā ar Java dinamisko ielādes un saistīšanas mehānismu. (Sīkāku informāciju par Java dinamisko ielādes un saistīšanas mehānismu skat. Džeimsa Goslinga un Henrija MakGiltona "Java valodas vide - balta grāmata", kas uzskaitīta sadaļā Resursi.)

Ievērojot iepriekš minēto ieteikumu, mēs izmantojam polimorfismu, ko nodrošina komandu modeļa izmantošana, lai novērstu milzīgu slēdžu paziņojumus, kā rezultātā izveidojas paplašināmas sistēmas. Mēs arī izmantojam Java unikālos dinamiskos ielādes un saistīšanas mehānismus, lai izveidotu dinamisku un dinamiski paplašināmu sistēmu. Tas ir parādīts otrajā koda parauga piemērā zemāk, saukts TestTransactionCommand.java.

Komandas modelis pats pieprasījumu pārvērš par objektu. Šo objektu var glabāt un nodot apkārt tāpat kā citus objektus. Šī modeļa atslēga ir a Komanda interfeiss, kas deklarē interfeisu darbību izpildei. Vienkāršākajā formā šajā saskarnē ir abstrakts izpildīt darbība. Katrs betons Komanda klase norāda uztvērēja un darbības pāri, saglabājot Uztvērējs kā instances mainīgo. Tas nodrošina dažādas programmas ieviešanu izpildīt() metodi pieprasījuma atsaukšanai. The Uztvērējs ir pieprasījuma izpildei nepieciešamās zināšanas.

Zemāk 1. attēlā parādīts Slēdzis - apkopojums Komanda objektiem. Tā ir flipUp () un flipDown () tās saskarnē. Slēdzis sauc par aicinātājs jo tas izsauc izpildes operāciju komandu saskarnē.

Konkrētā komanda, LightOnCommand, īsteno izpildīt komandas saskarnes darbība. Tam ir zināšanas, lai izsauktu atbilstošo Uztvērējs objekta darbība. Šajā gadījumā tas darbojas kā adapteris. Ar terminu adapteris, Es domāju, ka betons Komanda objekts ir vienkāršs savienotājs, kas savieno Uzaicinātājs un Uztvērējs ar dažādām saskarnēm.

Klients momentāno Uzaicinātājs, Uztvērējs, un konkrētie komandu objekti.

2. secības diagramma parāda mijiedarbību starp objektiem. Tas ilustrē, kā Komanda atvieno Uzaicinātājs no Uztvērējs (un pieprasījumu, ko tā izpilda). Klients izveido konkrētu komandu, parametrizējot tā konstruktoru ar atbilstošo Uztvērējs. Tad tas uzglabā Komanda iekš Uzaicinātājs. The Uzaicinātājs izsauc konkrētu komandu, kurai ir zināšanas, lai izpildītu vēlamo Darbība () darbība.

Klients (galvenā programma sarakstā) izveido konkrētu Komanda objektu un iestata to Uztvērējs. Kā Uzaicinātājs objekts, Slēdzis uzglabā betonu Komanda objekts. The Uzaicinātājs izsniedz pieprasījumu, zvanot izpildīt uz Komanda objekts. Betons Komanda objekts izsauc operācijas ar to Uztvērējs izpildīt lūgumu.

Galvenā ideja šeit ir tāda, ka konkrētā komanda reģistrējas Uzaicinātājs un Uzaicinātājs izsauc to, izpildot komandu Uztvērējs.

Komandas parauga koda piemērs

Apskatīsim vienkāršu piemēru, kas ilustrē atzvana mehānismu, kas sasniegts, izmantojot komandu modeli.

Piemērs parāda a Ventilators un a Gaisma. Mūsu mērķis ir attīstīt Slēdzis kas var ieslēgt vai izslēgt objektu. Mēs redzam, ka Ventilators un Gaisma ir dažādas saskarnes, kas nozīmē Slēdzis jābūt neatkarīgai no Uztvērējs vai tam nav zināšanu par kodu> Uztvērēja saskarne. Lai atrisinātu šo problēmu, mums ir jāparametrē katrs no šiem parametriem Slēdziss ar atbilstošu komandu. Acīmredzot Slēdzis savienots ar Gaisma būs cita komanda nekā Slēdzis savienots ar Ventilators. The Komanda klasei jābūt abstraktai vai saskarnei, lai tā darbotos.

Kad konstruktors a Slēdzis tiek izsaukts, tas tiek parametrizēts ar atbilstošu komandu kopu. Komandas tiks saglabātas kā privāti mainīgie Slēdzis.

Kad flipUp () un flipDown () tiek izsauktas operācijas, viņi vienkārši veiks atbilstošo komandu izpildīt( ). The Slēdzis nebūs ne jausmas, kas notiek izpildīt( ) tiek izsaukts.

TestCommand.java klase Fan {public void startRotate () {System.out.println ("Ventilators rotē"); } public void stopRotate () {System.out.println ("Ventilators negriežas"); }} klases gaisma {public void turnOn () {System.out.println ("Gaisma ir ieslēgta"); } public void turnOff () {System.out.println ("Gaisma ir izslēgta"); }} klases slēdzis {privātā komanda UpCommand, DownCommand; publiskais slēdzis (Command Up, Command Down) {UpCommand = Up; // konkrētā komanda reģistrējas ar izsaucēju DownCommand = Down; } void flipUp () {// izsaucējs izsauc konkrētu komandu, kas izpilda komandu uztvērējā UpCommand. izpildīt ( ) ; } void flipDown () {DownCommand. izpildīt ( ); }} klases LightOnCommand īsteno komandu {private Light myLight; public LightOnCommand (Light L) {myLight = L; } public void izpildīt () {myLight. ieslēdz( ); }} klases LightOffCommand īsteno komandu {private Light myLight; public LightOffCommand (Light L) {myLight = L; } public void izpildīt () {myLight. izslēgt( ); }} klases FanOnCommand īsteno komandu {private Fan myFan; publiskais FanOnCommand (F ventilators) {myFan = F; } public void izpildīt () {myFan. startRotate (); }} klases FanOffCommand izpilda komandu {private Fan myFan; publiskais FanOffCommand (F ventilators) {myFan = F; } public void izpildīt () {myFan. stopRotate (); }} public class TestCommand {public static void main (String [] args) {Gaismas testLight = jauns Gaisma (); LightOnCommand testLOC = jauns LightOnCommand (testLight); LightOffCommand testLFC = jauns LightOffCommand (testLight); Slēdzis testSwitch = jauns slēdzis (testLOC, testLFC); testSwitch.flipUp (); testSwitch.flipDown (); Ventilatora testa ventilators = jauns ventilators (); FanOnCommand foc = jauns FanOnCommand (testFan); FanOffCommand ffc = jauns FanOffCommand (testFan); Slēdzis ts = jauns slēdzis (foc, ffc); ts.flipUp (); ts.flipDown (); }} Command.java publiskā saskarne Command {public abstract void execute (); } 

Iepriekš koda piemērā ievērojiet, ka komandu modelis pilnībā atdala objektu, kas izsauc operāciju - (Slēdzis ) - no tiem, kuriem ir zināšanas to izpildei - Gaisma un Ventilators. Tas mums dod lielu elastību: objektam, kas izsniedz pieprasījumu, jāzina tikai tas, kā to izsniegt; tai nav jāzina, kā pieprasījums tiks izpildīts.

Komandu shēma, lai ieviestu darījumus

Komandas modelis ir pazīstams arī kā darbība vai darījuma modelis. Ļaujiet mums apsvērt serveri, kas pieņem un apstrādā darījumus, kurus klienti piegādā, izmantojot TCP / IP kontaktligzdas savienojumu. Šie darījumi sastāv no komandas, kam seko nulle vai vairāk argumentu.

Izstrādātāji katrai komandai var izmantot slēdzi ar burtu un burtu. Lietošana Slēdzis priekšraksti kodēšanas laikā ir nepareiza dizaina pazīme objektorientēta projekta projektēšanas posmā. Komandas ir objektorientēts veids, kā atbalstīt darījumus, un tās var izmantot, lai atrisinātu šo noformējuma problēmu.

Programmas klienta kodā TestTransactionCommand.java, visi pieprasījumi tiek iekļauti vispārīgajā TransactionCommand objekts. The TransactionCommand konstruktoru izveido klients, un tas ir reģistrēts CommandManager. Rindā esošos pieprasījumus var izpildīt dažādos laikos, zvanot uz runCommands (), kas dod mums lielu elastību. Tas arī dod mums iespēju apkopot komandas saliktā komandā. man arī ir CommandArgument, CommandReceiver, un CommandManager klases un apakšklases TransactionCommand - proti AddCommand un SubtractCommand. Tālāk ir sniegts katras šīs klases apraksts:

  • CommandArgument ir palīgu klase, kurā glabājas komandas argumenti. To var pārrakstīt, lai vienkāršotu uzdevumu nodot lielu vai mainīgu jebkura veida argumentu skaitu.

  • CommandReceiver ievieš visas komandu apstrādes metodes un tiek ieviests kā Singletona modelis.

  • CommandManager ir aicinātājs un ir Slēdzis ekvivalents no iepriekšējā piemēra. Tajā tiek glabāti vispārīgie TransactionCommand objekts savā privātajā myCommand mainīgais. Kad runCommands () tiek izsaukts, tas izsauc izpildīt( ) no atbilstošajiem TransactionCommand objekts.

Java valodā ir iespējams meklēt klases definīciju, kurai piešķirta virkne ar tās nosaukumu. Iekš izpildīt ( ) operācija TransactionCommand klase, es aprēķinu klases nosaukumu un dinamiski saistu to ar darbojas sistēmu - tas ir, klases tiek ielādētas lidojumā pēc nepieciešamības. Kā darījumu komandu apakšklases nosaukumu izmantoju nosaukumu piešķiršanas kārtību, komandas nosaukumu, kas sasiets ar virkni "Komanda", lai to varētu dinamiski ielādēt.

Ievērojiet, ka Klase objekts, kuru atdeva newInstance () ir jānodod atbilstošajam tipam. Tas nozīmē, ka jaunajai klasei vai nu jāievieš saskarne, vai apakšklase esošai klasei, kas kompilācijas laikā ir zināma programmai. Šajā gadījumā, tā kā mēs īstenojam Komanda saskarni, tā nav problēma.

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