Programmēšana

Pārņemiet kontroli, izmantojot starpniekservera dizaina modeli

Mans draugs - ne mazāk medicīnas ārsts - man reiz teica, ka pārliecināja draugu kārtot viņam koledžas eksāmenu. Kāds, kurš ieņem kāda cita vietu, ir pazīstams kā a starpniekserveris. Diemžēl manam draugam viņa pilnvarnieks iepriekšējā vakarā dzēra mazliet par daudz un neizturēja testu.

Programmatūrā starpniekservera dizaina modelis izrādās noderīgs daudzos kontekstos. Piemēram, izmantojot Java XML pakotni, jūs izmantojat starpniekserverus, lai piekļūtu tīmekļa pakalpojumiem, izmantojot JAX-RPC (Java API uz XML balstītām attālo procedūru izsaukumiem). 1. piemērā parādīts, kā klients piekļūst vienkāršam Hello World tīmekļa pakalpojumam:

1. piemērs. SOAP (vienkāršs objekta piekļuves protokols) starpniekserveris

public class HelloClient {public static void main (String [] args) {mēģiniet {HelloIF_Stub starpniekserveris = (HelloIF_Stub) (jauns HelloWorldImpl (). GetHelloIF ()); starpniekserveris._setTargetEndpoint (argumenti [0]); System.out.println (starpniekserveris.saka Sveiki ("Hercogs!")); } catch (izņēmums ex) {ex.printStackTrace (); }}} 

1. piemēra kods ir ļoti līdzīgs Hello World tīmekļa pakalpojumu piemēram, kas iekļauts JAX-RPC. Klients iegūst atsauci uz starpniekserveri un ar komandrindas argumentu iestata starpniekservera galapunktu (tīmekļa pakalpojuma URL). Kad klientam ir atsauce uz starpniekserveri, tas izsauc starpniekserveri saki sveiki() metodi. Starpniekserveris pārsūta šīs metodes izsaukumu uz tīmekļa pakalpojumu, kas bieži atrodas citā datorā nekā klients.

1. piemērā ir parādīts viens starpniekservera dizaina modeļa lietojums: piekļuve attāliem objektiem. Pilnvarotie arī izrādās noderīgi, lai pēc pieprasījuma radītu dārgus resursus, a virtuālais starpniekserveris, un piekļuves kontrolei objektiem, a aizsardzības starpniekserveris.

Ja esat izlasījis manu sadaļu "Izrotājiet savu Java kodu" (JavaWorld, 2001. gada decembris), jūs varat redzēt līdzības starp dekoratora un starpniekservera dizaina modeļiem. Abos šablonos tiek izmantots starpniekserveris, kas pārsūta metodes izsaukumus uz citu objektu, kas pazīstams kā reāls priekšmets. Atšķirība ir tāda, ka ar starpniekservera modeli attiecības starp starpniekserveri un reālo objektu parasti tiek noteiktas sastādīšanas laikā, savukārt dekoratorus var rekursīvi konstruēt izpildlaika laikā. Bet es tieku priekšā sev.

Šajā rakstā es vispirms iepazīstinu ar starpniekservera modeli, sākot ar Swing ikonu starpniekservera piemēru. Noslēdzu, apskatot JDK iebūvēto atbalstu Proxy modelim.

Piezīme: Šīs slejas pirmajās divās daļās - "Pārsteidziet savus izstrādātāju draugus ar dizaina modeļiem" (2001. gada oktobris) un "Izrotājiet savu Java kodu" - es apspriedu Decorator modeli, kas ir cieši saistīts ar starpniekservera modeli, tāpēc jūs varētu vēlēties pirms turpināt, apskatīt šos rakstus.

Starpniekservera modelis

Starpniekserveris: kontrolējiet piekļuvi objektam, izmantojot starpniekserveri (pazīstams arī kā aizstājējs vai vietturis).

Šūpoles ikonas iemeslu dēļ, kas aplūkoti sadaļā "Starpniekservera lietojamība", ir lieliska izvēle starpniekservera modeļa ilustrēšanai. Es sāku ar īsu ievadu par Swing ikonām, kam seko Swing ikonu starpniekservera diskusija.

Šūpoles ikonas

Šūpoles ikonas ir mazi attēli, kurus izmanto pogās, izvēlnēs un rīkjoslās. Swing ikonas var izmantot arī pašas, kā parādīts 1. attēlā.

1. attēlā redzamā lietojumprogramma ir norādīta 2. piemērā:

2. piemērs. Swing ikonas

importēt java.awt. *; importēt java.awt.event. *; importēt javax.swing. *; // Šajā klasē tiek pārbaudīta attēla ikona. publiskā klase IconTest paplašina JFrame {private static String IMAGE_NAME = "mandrill.jpg"; privāta statiska int FRAME_X = 150, FRAME_Y = 200, FRAME_WIDTH = 268, FRAME_HEIGHT = 286; privātā ikona imageIcon = null, imageIconProxy = null; static public void main (String args []) {IconTest app = new IconTest (); app.show (); } public IconTest () {super ("Ikonu tests"); imageIcon = jauns ImageIcon(IMAGE_NAME); setBounds (FRAME_X, FRAME_Y, FRAME_WIDTH, FRAME_HEIGHT); setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); } public void paint (Grafika g) {super.paint (g); Ieliktņu ieliktņi = getInsets (); imageIcon.paintIcon(šis, g, ielaidumi.kreisais, ieliktņi.galvenais); }} 

Iepriekšējā lietojumprogramma izveido attēla ikonu - javax.swing.ImageIcon - un pēc tam ignorē krāsot () metode ikonas krāsošanai.

Swing image-icon starpniekserveri

1. attēlā redzamā lietojumprogramma ir slikta Swing attēlu ikonu izmantošana, jo attēlu ikonas jāizmanto tikai maziem attēliem. Šis ierobežojums pastāv, jo attēlu veidošana ir dārga un ImageIcon gadījumi izveido savus attēlus, kad tie tiek konstruēti. Ja lietojumprogramma vienlaikus izveido daudz lielu attēlu, tas var izraisīt ievērojamu veiktspējas rezultātu. Turklāt, ja lietojumprogramma neizmanto visus savus attēlus, to izveide ir izšķērdīga.

Labāks risinājums ielādē attēlus, kad tie kļūst nepieciešami. Lai to izdarītu, starpniekserveris var izveidot īsto ikonu pirmo reizi, kad tiek veikti starpniekserveri paintIcon () metodi sauc. 2. attēlā parādīta lietojumprogramma, kurā ir attēla ikona (kreisajā pusē) un attēla ikonas starpniekserveris (labajā pusē). Augšējā attēlā ir redzama lietojumprogramma tūlīt pēc tās palaišanas. Tā kā attēlu ikonas ielādē savus attēlus, kad tie tiek konstruēti, ikonas attēls tiek parādīts, tiklīdz tiek atvērts lietojumprogrammas logs. Turpretim starpniekserveris neielādē savu attēlu, kamēr tas nav nokrāsots pirmo reizi. Kamēr attēls nav ielādēts, starpniekserveris ap perimetru iezīmē robežu un parāda "Notiek attēla ielāde ...". Apakšējā attēlā 2. attēlā parādīta lietojumprogramma pēc tam, kad starpniekserveris ir ielādējis savu attēlu.

Esmu uzskaitījis 3. piemērā 2. attēlā redzamo lietojumprogrammu:

3. piemērs. Pārsūtiet ikonu starpniekserverus

importēt java.awt. *; importēt java.awt.event. *; importēt javax.swing. *; // Šī klase pārbauda virtuālo starpniekserveri, kas ir starpniekserveris, kas // aizkavē dārga resursa (ikonas) ielādi, līdz šis // resurss ir nepieciešams. publiskā klase VirtualProxyTest paplašina JFrame {private static String IMAGE_NAME = "mandrill.jpg"; privāta statiska int IMAGE_WIDTH = 256, IMAGE_HEIGHT = 256, SPACING = 5, FRAME_X = 150, FRAME_Y = 200, FRAME_WIDTH = 530, FRAME_HEIGHT = 286; privātā ikona imageIcon = null, imageIconProxy = null; static public void main (String args []) {VirtualProxyTest app = new VirtualProxyTest (); app.show (); } public VirtualProxyTest () {super ("Virtuālā starpniekservera tests"); // Izveidojiet attēla ikonu un attēla ikonas starpniekserveri. imageIcon = new ImageIcon (IMAGE_NAME); imageIconProxy = jauns ImageIconProxy(IMAGE_NAME, IMAGE_WIDTH, IMAGE_HEIGHT); // Iestatiet rāmja robežas un rāmja noklusējuma // aizvēršanas darbību. setBounds (FRAME_X, FRAME_Y, FRAME_WIDTH, FRAME_HEIGHT); setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); } public void paint (Grafika g) {super.paint (g); Ieliktņu ieliktņi = getInsets (); imageIcon.paintIcon(šis, g, ielaidumi.kreisais, ieliktņi.tops); imageIconProxy.paintIcon(this, g, insets.left + IMAGE_WIDTH + SPACING, // width insets.top); // augums}} 

3. piemērs ir gandrīz identisks 2. piemēram, izņemot attēla ikonas starpniekservera pievienošanu. 3. piemērs izveido ikonu un starpniekserveri savā konstruktorā un ignorē to krāsot () metode to krāsošanai. Pirms diskusijas par starpniekservera ieviešanu apskatiet 3. attēlu, kas ir starpniekservera reālā priekšmeta klases diagramma javax.swing.ImageIcon klasē.

The javax.swing.Icon interfeiss, kas nosaka Swing ikonu būtību, ietver trīs metodes: paintIcon (), getIconWidth (), un getIconHeight (). The ImageIcon klase īsteno Ikona saskarni un pievieno savas metodes. Attēlu ikonas satur arī to attēlu aprakstu un atsauci uz tiem.

Attēlu ikonu starpnieki ievieš Ikona saskarni un uztur atsauci uz attēla ikonu - reālo priekšmetu, kā parādīts klases diagrammā 4. attēlā.

The ImageIconProxy klase ir norādīta 4. piemērā.

4. piemērs. ImageIconProxy.java

// ImageIconProxy ir ikonas starpniekserveris (vai aizstājējs). // Starpniekserveris aizkavē attēla ielādi, līdz pirmo reizi tiek uzzīmēts // attēls. Kamēr ikona ielādē savu attēlu, // starpniekserveris iezīmē robežu, un ziņa "Notiek attēla ielāde ..." klase ImageIconProxy ievieš javax.swing.Icon {private Ikona realIcon = nulle; būla isIconCreated = nepatiesa; privāta virkne imageName; privātā int platums, augstums; public ImageIconProxy (String imageName, int platums, int augstums) {this.imageName = imageName; this.width = platums; tas.augums = augstums; } public int getIconHeight () {return isIconCreated? augstums: realIcon.getIconHeight (); } public int getIconWidth () {return isIconCreated realIcon == null? platums: realIcon.getIconWidth (); } // Starpniekservera krāsa () ir pārslogota, lai uzzīmētu robežu // un ziņojumu ("Notiek attēla ielāde ..."), kamēr attēls // tiek ielādēts. Pēc attēla ielādes tas tiek uzzīmēts. Ievērojiet //, ka starpniekserveris neielādē attēlu, kamēr tas nav // faktiski vajadzīgs. public void paintIcon (galīgais komponents c, grafika g, int x, int y) { ja (isIconCreated) { realIcon.paintIcon(c, g, x, y); } cits g.drawRect(x, y, platums-1, augstums-1); g.drawString("Notiek attēla ielāde ...", x + 20, y + 20); // Ikona ir izveidota (tas nozīmē, ka attēls ir ielādēts) // citā pavedienā. sinhronizēts (tas) {SwingUtilities.invokeLater (jauns Runnable () {public void run () {mēģiniet {// Palēnināt attēla ielādes procesu. Thread.currentThread (). sleep (2000); // ImageIcon konstruktors izveido attēlu . realIcon = new ImageIcon (imageName); isIconCreated = patiess; } catch (InterruptedException ex) {ex.printStackTrace (); } // Pēc ikonas // izveides pārkrāsojiet ikonas komponentu. c. pārkrāsot (); } }); } } } } 

ImageIconProxy saglabā atsauci uz īsto ikonu ar realIcon locekļa mainīgais. Pirmo reizi, kad tiek krāsots starpniekserveris, īstā ikona tiek izveidota uz atsevišķa pavediena, lai atļautu krāsot taisnstūri un virkni (aicinājumi g.drawRect () un g.drawString () nestājas spēkā līdz paintIcon () metode atgriež). Pēc īstās ikonas izveides un tāpēc attēla ielādes komponents, kas parāda ikonu, tiek pārkrāsots. 5. attēlā parādīta šo notikumu secības diagramma.

5. attēla secības diagramma ir raksturīga visiem starpniekserveriem: Starpniekserveri kontrolē piekļuvi savam reālajam subjektam. Šīs kontroles dēļ pilnvarotie bieži aktualizē savu reālo tēmu, kā tas ir attēla ikonu starpniekserverim, kas uzskaitīts 4. piemērā. Šī izpausme ir viena no atšķirībām starp starpniekservera modeli un dekoratora modeli: dekoratori reti izveido savus reālos objektus.

JDK iebūvētais atbalsts starpniekservera dizaina modelim

Starpniekservera modelis ir viens no vissvarīgākajiem dizaina modeļiem, jo ​​tas nodrošina alternatīvu funkcionalitātes paplašināšanai ar mantojumu. Šī alternatīva ir objekta sastāvs, kur objekta (starpniekservera) pārsūtīšanas metode izsauc slēgtu objektu (reālu subjektu).

Priekšroka dodama objekta sastāvam, nevis mantojumam, jo, sastādot, norobežojošie objekti var manipulēt ar savu slēgto objektu tikai caur slēgtā objekta saskarni, kā rezultātā objekti ir brīvi savienoti. Turpretī ar mantojumu klases ir cieši saistītas ar to pamatklasi, jo bāzes klases iekšējās ir redzams tā paplašinājumiem. Šīs redzamības dēļ mantojumu bieži sauc par baltās kastes atkārtota izmantošana. No otras puses, ar kompozīciju, norobežojošā objekta iekšējie ir nav redzams uz slēgto objektu (un otrādi); tāpēc sastāvu bieži sauc par melnās kastes atkārtota izmantošana. Ja viss ir vienāds, melnās kastes atkārtota izmantošana (sastāvs) ir vēlama nekā baltās kastes atkārtota izmantošana (mantojums), jo vaļīga savienojuma rezultātā veidojas kaļamākas un elastīgākas sistēmas.

Tā kā starpniekservera modelis ir tik svarīgs, J2SE 1.3 (Java 2 platforma, Standard Edition) un ne tikai to tieši atbalsta. Šis atbalsts ietver trīs klases no java.lang.reflect iepakojums: Starpniekserveris, Metode, un InvocationHandler. 5. piemērā parādīts vienkāršs piemērs, kurā starpniekservera modelim tiek izmantots JDK atbalsts:

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