Programiranje

Prevzemite nadzor z vzorcem oblikovanja proxy

Moj prijatelj - nič manj zdravnik - mi je nekoč rekel, da je prepričal prijatelja, da je namesto njega opravil fakultetni izpit. Nekdo, ki zavzame mesto nekoga drugega, je znan kot zastopnik. Na žalost mojega prijatelja je prejšnji večer njegov pooblaščenec popil malo preveč in ni opravil testa.

V programski opremi se vzorec oblikovanja proxy izkaže za uporabnega v številnih kontekstih. Na primer, s paketom Java XML Pack uporabite strežnike proxy za dostop do spletnih storitev z JAX-RPC (Java API za oddaljene klice na podlagi XML). Primer 1 prikazuje, kako odjemalec dostopa do preproste spletne storitve Hello World:

Primer 1. Proxy SOAP (Simple Object Access Protocol)

javni razred HelloClient {public static void main (String [] args) {try {HelloIF_Stub zastopnik = (HelloIF_Stub) (novo HelloWorldImpl (). GetHelloIF ()); zastopnik._setTargetEndpoint (args [0]); System.out.println (zastopnik.sayHello ("Duke!")); } catch (izjema ex) {ex.printStackTrace (); }}} 

Koda primera 1 je zelo podobna primeru spletnih storitev Hello World, ki je vključen v JAX-RPC. Naročnik pridobi sklic na strežnik proxy in s pomočjo argumenta ukazne vrstice nastavi njegovo končno točko (URL spletne storitve). Ko se odjemalec sklicuje na proxy, prikliče strežnik proxy reci živijo() metoda. Proxy posreduje to metodo klicu na spletno storitev, ki je pogosto nameščena na drugem računalniku, kot je odjemalski.

Primer 1 ponazarja eno uporabo vzorca oblikovanja proxy: dostop do oddaljenih predmetov. Proxyji se izkažejo tudi za ustvarjanje dragih virov na zahtevo, a virtualni proxy, in za nadzor dostopa do predmetov, a zaščitni proxy.

Če ste prebrali mojo "Okrasite svojo kodo Java" (JavaWorld, Decembra 2001), boste morda opazili podobnosti med vzorci oblikovanja Decorator in Proxy. Oba vzorca uporabljata proxy, ki posreduje klice metode drugemu predmetu, znanemu kot pravi subjekt. Razlika je v tem, da se z vzorcem proxy odnos med proxyjem in resničnim subjektom običajno nastavi v času prevajanja, medtem ko je okrasitelje mogoče rekurzivno izdelati med izvajanjem. Sem pa v prednosti pred seboj.

V tem članku najprej predstavim vzorec proxy, začenši s primerom proxyja za ikone Swing. Zaključujem s pogledom na vgrajeno podporo JDK za vzorec proxy.

Opomba: V prvih dveh delih tega stolpca - "Presenetite svoje prijatelje razvijalce z vzorci oblikovanja" (oktober 2001) in "Okrasite svojo kodo Java" - sem razpravljal o vzorcu Decorator, ki je tesno povezan z vzorcem proxy, zato boste morda želeli da si pred nadaljevanjem ogledate te članke.

Vzorec proxy

Proxy: Nadzira dostop do predmeta s proxyjem (znan tudi kot nadomestni ali nadomestni znak).

Ikone nihanja so iz razlogov, opisanih v spodnjem razdelku "Uporabnost proxyja", odlična izbira za ponazoritev vzorca proxy. Začnem s kratkim uvodom v ikone Swing, ki mu sledi razprava o namestitvi ikone Swing.

Nihajne ikone

Ikone nihanja so majhne slike, ki se uporabljajo v gumbih, menijih in orodnih vrsticah. Ikone Swing lahko uporabite tudi same, kot prikazuje slika 1.

Aplikacija, prikazana na sliki 1, je navedena v primeru 2:

Primer 2. Nihajne ikone

uvoz java.awt. *; uvoz java.awt.event. *; uvoz javax.swing. *; // Ta razred preizkuša ikono slike. javni razred IconTest razširja JFrame {private static String IMAGE_NAME = "mandrill.jpg"; zasebni statični int FRAME_X = 150, FRAME_Y = 200, FRAME_WIDTH = 268, FRAME_HEIGHT = 286; zasebna ikona imageIcon = null, imageIconProxy = null; statična javna void main (String args []) {Aplikacija IconTest = nova IconTest (); app.show (); } javni IconTest () {super ("Preskus ikone"); imageIcon = nov ImageIcon(IMAGE_NAME); setBounds (FRAME_X, FRAME_Y, FRAME_WIDTH, FRAME_HEIGHT); setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); } javna prazna barva (grafika g) {super.paint (g); Vstavi vstavki = getInsets (); imageIcon.paintIcon(to, g, vstavki.levo, vstavki.vrh); }} 

Prejšnja aplikacija ustvari ikono slike - primerek javax.swing.ImageIcon - in nato preglasi barva () način za barvanje ikone.

Swing slikovno-ikono proxy

Aplikacija, prikazana na sliki 1, slabo uporablja ikone Swing image, ker bi morali ikone slike uporabljati samo za majhne slike. Ta omejitev obstaja, ker je ustvarjanje slik drago in ImageIcon primerki ustvarijo svoje slike, ko so zgrajene. Če aplikacija naenkrat ustvari veliko velikih slik, bi to lahko povzročilo znaten hit uspešnosti. Če aplikacija ne uporablja vseh svojih slik, jih je potratno ustvarjati vnaprej.

Boljša rešitev naloži slike, ko postanejo potrebne. V ta namen lahko posrednik prvič ustvari pravo ikono paintIcon () metoda se imenuje. Na sliki 2 je prikazana aplikacija, ki vsebuje ikono slike (na levi) in proxy slike-ikone (na desni). Zgornja slika prikazuje aplikacijo takoj po zagonu. Ker ikone slike naložijo svoje slike, ko so izdelane, se slika ikone prikaže takoj, ko se odpre okno aplikacije. Nasprotno pa proxy ne naloži svoje slike, dokler ni prvič poslikan. Dokler se slika ne naloži, proxy nariše obrobo po njenem obodu in prikaže »Nalaganje slike ...« Spodnja slika na sliki 2 prikazuje aplikacijo, potem ko je proxy naložil svojo sliko.

Navedel sem aplikacijo, prikazano na sliki 2 v primeru 3:

Primer 3. Proxyji nihajnih ikon

uvoz java.awt. *; uvoz java.awt.event. *; uvoz javax.swing. *; // Ta razred preizkuša virtualni strežnik proxy, ki je strežnik proxy, ki // odloži nalaganje dragega vira (ikone), dokler ta // vir ni potreben. javni razred VirtualProxyTest razširja JFrame {private static String IMAGE_NAME = "mandrill.jpg"; zasebni statični int IMAGE_WIDTH = 256, IMAGE_HEIGHT = 256, RAZMAK = 5, FRAME_X = 150, FRAME_Y = 200, FRAME_WIDTH = 530, FRAME_HEIGHT = 286; zasebna ikona imageIcon = null, imageIconProxy = null; statična javna void main (String args []) {VirtualProxyTest app = new VirtualProxyTest (); app.show (); } javni VirtualProxyTest () {super ("Test navideznega proxyja"); // Ustvari ikono slike in proxy slike-ikone. imageIcon = nova ImageIcon (IMAGE_NAME); imageIconProxy = novo ImageIconProxy(IMAGE_NAME, IMAGE_WIDTH, IMAGE_HEIGHT); // Nastavite meje okvira in privzeto // zapiranje okvira. setBounds (FRAME_X, FRAME_Y, FRAME_WIDTH, FRAME_HEIGHT); setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); } javna prazna barva (grafika g) {super.paint (g); Vstavi vstavki = getInsets (); imageIcon.paintIcon(to, g, vstavki.levo, vstavki.vrh); imageIconProxy.paintIcon(this, g, insets.left + IMAGE_WIDTH + SPACING, // width insets.top); // višina}} 

Primer 3 je skoraj enak primeru 2, razen dodajanja proxy-ja image-icon. Aplikacija Primer 3 ustvari ikono in proxy v svojem konstruktorju in jih preglasi barva () metoda za njihovo barvanje. Preden se pogovorimo o izvajanju proxyja, si oglejte sliko 3, ki je diagram razreda resničnega predmeta proxyja, javax.swing.ImageIcon razred.

The javax.swing.Icon Vmesnik, ki opredeljuje bistvo ikon Swing, vključuje tri metode: paintIcon (), getIconWidth (), in getIconHeight (). The ImageIcon razred izvaja Ikona vmesnik in dodaja lastne metode. Ikone slik vsebujejo tudi opis in sklic na njihove slike.

Proxyji image-icon izvajajo Ikona vmesnik in ohranite sklic na ikono slike - resnično temo - kot prikazuje diagram razredov na sliki 4.

The ImageIconProxy razred je naveden v primeru 4.

Primer 4. ImageIconProxy.java

// ImageIconProxy je proxy (ali nadomestni) ikone. // Proxy odloži nalaganje slike do prvega risanja // slike. Medtem ko ikona nalaga svojo sliko, // proxy nariše obrobo in sporočilo »Nalaganje slike ...« razreda ImageIconProxy implementira javax.swing.Icon {private Ikona realIcon = nič; logično isIconCreated = napačno; zasebni niz imageName; zasebna int širina, višina; public ImageIconProxy (Niz imageName, int širina, int višina) {this.imageName = imageName; this.width = širina; this.height = višina; } public int getIconHeight () {return isIconCreate? višina: realIcon.getIconHeight (); } public int getIconWidth () {return isIconCreated realIcon == null? širina: realIcon.getIconWidth (); } // Metoda proxy's paint () je preobremenjena, da nariše obrobo // in sporočilo ("Nalaganje slike ..."), medtem ko se slika // naloži. Ko se slika naloži, se nariše. Opazite //, da proxy slike ne naloži, dokler // dejansko ni potrebna. public void paintIcon (končna komponenta c, grafika g, int x, int y) { če (isIconCreated) { realIcon.paintIcon(c, g, x, y); } še { g.drawRect(x, y, širina-1, višina-1); g.drawString("Nalaganje slike ...", x + 20, y + 20); // Ikona je ustvarjena (kar pomeni, da je slika naložena) // na drugi niti. sinhronizirano (to) {SwingUtilities.invokeLater (new Runnable () {public void run () {try {// Upočasni postopek nalaganja slike. Thread.currentThread (). sleep (2000); // Konstruktor ImageIcon ustvari sliko . realIcon = nova ImageIcon (imageName); isIconCreated = res; } catch (InterruptedException ex) {ex.printStackTrace (); } // Po ponovni barvi komponente ikone po ustvarjanju ikone //. c.repaint (); } }); } } } } 

ImageIconProxy ohranja sklic na pravo ikono z realIcon spremenljivka člana. Ko prvič pobarvate strežnik proxy, se na ločeni niti ustvari prava ikona, ki omogoča barvanje pravokotnika in niza (klici na g.drawRect () in g.drawString () ne začnejo veljati do paintIcon () metoda vrne). Ko je ustvarjena prava ikona in je slika naložena, je komponenta, ki prikazuje ikono, prebarvana. Slika 5 prikazuje diagram zaporedja za te dogodke.

Diagram zaporedja na sliki 5 je značilen za vse pooblaščence: pooblaščenci nadzorujejo dostop do svojega resničnega subjekta. Zaradi tega nadzora pooblaščenci pogosto ustvarijo pravi subjekt, kot je primer za proxy ikone slike, naveden v primeru 4. Ta primerek je ena od razlik med vzorcem proxy in vzorcem dekoraterja: dekoraterji redko ustvarijo svoje resnične predmete.

Vgrajena podpora JDK za vzorec oblikovanja proxy

Vzorec proxy je eden najpomembnejših vzorcev oblikovanja, ker ponuja alternativo razširitvi funkcionalnosti z dedovanjem. Ta alternativa je sestava predmeta, kjer objekt (proxy) posreduje klice metode zaprtemu objektu (pravi subjekt).

Sestava predmeta je bolj zaželena kot dedovanje, ker lahko s sestavo obdajajoči predmeti manipulirajo s svojim zaprtim predmetom samo prek vmesnika zaprtega predmeta, kar povzroči ohlapno povezavo med predmeti. Nasprotno pa so razredi z dedovanjem tesno povezani s svojim osnovnim razredom, ker so notranji deli osnovnega razreda vidna do njegovih razširitev. Zaradi te prepoznavnosti se dedovanje pogosto imenuje ponovna uporaba bele škatle. Po drugi strani pa so s sestavo notranjost ograjenega predmeta ni viden na priloženi predmet (in obratno); zato sestavo pogosto imenujemo ponovna uporaba črne skrinjice. Pri vseh enakih pogojih je ponovna uporaba črne škatle (sestava) zaželena kot ponovna uporaba bele dediščine (dedovanje), ker ohlapno spenjanje povzroči bolj voljne in prilagodljive sisteme.

Ker je vzorec proxy tako pomemben, ga J2SE 1.3 (Java 2 Platform, Standard Edition) in še več neposredno podpira. Ta podpora vključuje tri razrede iz java.lang.reflect paket: Zastopnik, Metoda, in InvocationHandler. Primer 5 prikazuje preprost primer, ki uporablja podporo JDK za vzorec proxy:

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