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ējs
saskarne.) 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ēdzis
s 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 irSlēdzis
ekvivalents no iepriekšējā piemēra. Tajā tiek glabāti vispārīgieTransactionCommand
objekts savā privātajāmyCommand
mainīgais. KadrunCommands ()
tiek izsaukts, tas izsaucizpildīt( )
no atbilstošajiemTransactionCommand
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.