Programavimas

Perimkite valdymą naudodami „Proxy“ dizaino modelį

Mano draugas - ne mažiau medicinos gydytojas - kartą man pasakė, kad įtikino draugą laikyti jam kolegijos egzaminą. Kažkas, kuris užima kažkieno vietą, yra žinomas kaip a įgaliojimas. Deja, mano draugo, jo atstovas prieš naktį išgėrė kiek per daug ir neišlaikė bandymo.

Programinėje įrangoje „Proxy“ dizaino modelis yra naudingas daugeliu atvejų. Pvz., Naudodami „Java XML Pack“, naudojate tarpinius serverius, kad galėtumėte pasiekti žiniatinklio paslaugas naudodami JAX-RPC („Java“ API XML pagrindu atliekamiems nuotolinių procedūrų iškvietimams). 1 pavyzdyje parodyta, kaip klientas pasiekia paprastą „Hello World“ žiniatinklio paslaugą:

1 pavyzdys. SOAP (paprastas objekto prieigos protokolas) tarpinis serveris

public class HelloClient {public static void main (String [] args) {try {HelloIF_Stub įgaliojimas = (HelloIF_Stub) (naujas HelloWorldImpl (). GetHelloIF ()); įgaliojimas._setTargetEndpoint (argumentai [0]); System.out.println (įgaliojimas.pasakyk labas ("kunigaikštis!")); } sugauti (Išimtis ex) {ex.printStackTrace (); }}} 

1 pavyzdžio kodas labai panašus į „Hello World“ žiniatinklio paslaugų pavyzdį, įtrauktą į JAX-RPC. Klientas gauna nuorodą į tarpinį serverį ir nustato tarpinio serverio galinį tašką (žiniatinklio paslaugos URL) su komandinės eilutės argumentu. Kai klientas turi nuorodą į tarpinį serverį, jis iškviečia įgaliotąjį sakyk labas() metodas. Įgaliotasis persiunčia šio metodo iškvietimą žiniatinklio tarnybai, kuri dažnai gyvena kitoje mašinoje nei klientas.

1 pavyzdyje parodytas vienas „Proxy“ dizaino modelio panaudojimas: prieiga prie nuotolinių objektų. Įgaliotieji taip pat yra naudingi kuriant brangius išteklius pagal poreikį, a virtualusis tarpinis serveris, ir prieigos prie objektų kontrolei, a apsaugos proxy.

Jei perskaitėte mano „Papuoškite savo„ Java “kodą“ („JavaWorld“, 2001 m. Gruodžio mėn.), Galite pastebėti „Decorator“ ir „Proxy“ dizaino modelių panašumus. Abiejuose modeliuose naudojamas tarpinis serveris, kuris persiunčia metodo iškvietimus į kitą objektą, vadinamą tikrasis dalykas. Skirtumas yra tas, kad naudojant „Proxy“ modelį santykis tarp tarpinio serverio ir tikrojo subjekto paprastai nustatomas kompiliavimo metu, o dekoratoriai gali būti rekursyviai konstruojami vykdymo metu. Bet aš lenkiu save.

Šiame straipsnyje aš pirmiausia pristatau „Proxy“ modelį, pradedant „Swing“ piktogramų tarpinio serverio pavyzdžiu. Pabaigoje apžvelgiu JDK integruotą „Proxy“ modelio palaikymą.

Pastaba: Pirmose dviejose šio stulpelio dalyse - „Nustebinkite savo kūrėjo draugus dizaino raštais“ (2001 m. Spalio mėn.) Ir „Papuoškite savo„ Java “kodą“ - aptariau „Decorator“ modelį, kuris glaudžiai susijęs su „Proxy“ modeliu, todėl galbūt norėsite prieš tęsdami peržiūrėti šiuos straipsnius.

„Proxy“ modelis

Tarpinis serveris: valdykite prieigą prie objekto naudodami tarpinį serverį (taip pat žinomą kaip pakaitalas arba vietos rezervavimo ženklas).

„Swing“ piktogramos, dėl priežasčių, aptartų toliau pateiktame skyriuje „Tarpinio serverio taikymas“, yra puikus pasirinkimas, kaip iliustruoti tarpinį modelį. Pradedu trumpu „Swing“ piktogramų įvadu, po kurio aptarsiu „Swing“ piktogramos tarpinį serverį.

Sūpynės piktogramos

Sūpynės piktogramos yra mažos nuotraukos, naudojamos mygtukuose, meniu ir įrankių juostose. Taip pat galite patys naudoti „Swing“ piktogramas, kaip pavaizduota 1 paveiksle.

1 paveiksle parodyta programa yra išvardyta 2 pavyzdyje:

2 pavyzdys. Sūpynės piktogramos

importuoti java.awt. *; importuoti java.awt.event. *; importuoti javax.swing. *; // Ši klasė išbando vaizdo piktogramą. viešoji klasė „IconTest“ pratęsia JFrame {private static String IMAGE_NAME = "mandrill.jpg"; privati ​​statinė int FRAME_X = 150, FRAME_Y = 200, FRAME_WIDTH = 268, FRAME_HEIGHT = 286; asmeninė piktograma imageIcon = null, imageIconProxy = null; static public void main (String args []) {IconTest app = new IconTest (); app.show (); } public IconTest () {super ("Icon Test"); imageIcon = naujas ImageIcon(„IMAGE_NAME“); nustatytos ribos (FRAME_X, FRAME_Y, FRAME_WIDTH, FRAME_HEIGHT); setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); } public void paint (grafika g) {super.paint (g); Įdėklų įdėklai = getInsets (); „imageIcon.paintIcon“(tai, g, intarpai.kairė, intarpai.viršelis); }} 

Ankstesnė programa sukuria vaizdo piktogramą - javax.swing.ImageIcon - ir tada nepaiso dažyti() piktogramos dažymo metodas.

„Swing image-icon“ tarpiniai serveriai

1 paveiksle parodyta programa yra netinkama „Swing“ vaizdo piktogramų naudojimas, nes vaizdo piktogramas turėtumėte naudoti tik mažoms nuotraukoms. Šis apribojimas egzistuoja, nes vaizdų kūrimas yra brangus ir „ImageIcon“ egzemplioriai sukuria savo atvaizdus, ​​kai jie yra sukonstruoti. Jei programa sukuria daug didelių vaizdų vienu metu, tai gali sukelti didelį našumą. Be to, jei programa nenaudoja visų savo atvaizdų, jas kurti iš anksto yra nuostolinga.

Geresnis sprendimas įkelia vaizdus, ​​kai jiems reikia. Norėdami tai padaryti, tarpinis serveris gali sukurti tikrąją piktogramą pirmą kartą paintIcon () metodas vadinamas. 2 paveiksle parodyta programa, kurioje yra paveikslėlio piktograma (kairėje) ir vaizdo piktogramos tarpinis serveris (dešinėje). Viršutiniame paveikslėlyje parodyta programa iškart po jos paleidimo. Kadangi vaizdų piktogramos įkelia savo atvaizdus juos sukūrus, piktogramos vaizdas rodomas iškart, kai tik atsidaro programos langas. Priešingai, tarpinis serveris neįkelia savo atvaizdo, kol jis nėra nudažytas pirmą kartą. Kol vaizdas neįkeliamas, tarpinis serveris perimetrą nubrėžia kraštu ir rodo „Įkeliamas vaizdas ...“. Apatiniame 2 paveikslo paveikslėlyje parodyta programa, kai tarpinis serveris įkėlė savo atvaizdą.

Išvardinau 3 pavyzdžio 2 paveiksle pavaizduotą programą:

3 pavyzdys

importuoti java.awt. *; importuoti java.awt.event. *; importuoti javax.swing. *; // Ši klasė išbando virtualųjį tarpinį serverį, kuris yra tarpinis serveris, // vėluojantis įkelti brangų šaltinį (piktogramą), kol to // ištekliaus reikės. viešosios klasės „VirtualProxyTest“ pratęsia JFrame {private static String IMAGE_NAME = "mandrill.jpg"; privati ​​statinė int IMAGE_WIDTH = 256, IMAGE_HEIGHT = 256, SPACING = 5, FRAME_X = 150, FRAME_Y = 200, FRAME_WIDTH = 530, FRAME_HEIGHT = 286; asmeninė piktograma imageIcon = null, imageIconProxy = null; static public void main (String args []) {VirtualProxyTest app = new VirtualProxyTest (); app.show (); } public VirtualProxyTest () {super ("Virtualus tarpinio serverio testas"); // Sukurkite vaizdo piktogramą ir paveikslėlio piktogramą. „imageIcon“ = new ImageIcon (IMAGE_NAME); „imageIconProxy“ = naujas „ImageIconProxy“(IMAGE_NAME, IMAGE_WIDTH, IMAGE_HEIGHT); // Nustatykite rėmelio ribas ir numatytąjį rėmo // uždarymo veiksmą. nustatytos ribos (FRAME_X, FRAME_Y, FRAME_WIDTH, FRAME_HEIGHT); setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); } public void paint (grafika g) {super.paint (g); Įdėklų įdėklai = getInsets (); imageIcon.paintIcon(tai, g, intarpai.kairė, įdėklai.viršelis); „imageIconProxy.paintIcon“(tai, g, intarpai.kairė + IMAGE_WIDTH + SPACING, // plotis insets.top); // aukštis}} 

3 pavyzdys yra beveik identiškas 2 pavyzdžiui, išskyrus vaizdo piktogramos tarpinio serverio pridėjimą. 3 pavyzdžio programa sukuria piktogramą ir tarpinį serverį savo konstruktoriuje ir nepaiso jos dažyti() metodas juos dažyti. Prieš diskutuodami apie tarpinio serverio įgyvendinimą, pažiūrėkite į 3 paveikslą, kuris yra tikrojo įgaliotinio dalyko - klasės diagrama javax.swing.ImageIcon klasė.

javax.swing.Icon sąsaja, apibrėžianti „Swing“ piktogramų esmę, apima tris metodus: paintIcon (), getIconWidth ()ir „getIconHeight“ (). „ImageIcon“ klasė įgyvendina Piktograma sąsają ir prideda savo metodus. Paveikslėlių piktogramose taip pat pateikiamas jų vaizdų aprašymas ir nuoroda į juos.

Vaizdo piktogramos įgaliotieji diegia Piktograma sąsają ir palaikykite nuorodą į paveikslėlio piktogramą - tikrąjį dalyką, kaip parodyta klasės paveiksle 4 paveiksle.

„ImageIconProxy“ klasė yra išvardyta 4 pavyzdyje.

4 pavyzdys. ImageIconProxy.java

// ImageIconProxy yra piktogramos tarpinis serveris (arba pakaitalas). // Tarpinis serveris atideda vaizdo įkėlimą, kol pirmą kartą nupiešiamas // vaizdas. Kol piktograma įkelia savo atvaizdą, // tarpinis serveris nubrėžia kraštinę, o pranešimas „Įkeliamas vaizdas ...“ klasė „ImageIconProxy“ įgyvendina javax.swing.Icon {private Piktograma realIcon = nulis; loginis isIconCreated = klaidinga; privati ​​eilutė imageName; private int plotis, aukštis; public ImageIconProxy (String imageName, int plot, int height) {this.imageName = imageName; this.width = plotis; tai.aukštis = aukštis; } public int getIconHeight () {return isIconCreated? aukštis: realIcon.getIconHeight (); } public int getIconWidth () {return isIconCreated realIcon == null? plotis: realIcon.getIconWidth (); } // Įgaliotojo „paint“ () metodas perkrautas, kad nubrėžtų kraštinę // ir pranešimą („Įkeliamas vaizdas ...“), kol vaizdas // įkeliamas. Įkėlus vaizdą, jis nupiešiamas. Atkreipkite dėmesį, // kad tarpinis serveris neįkelia vaizdo, kol jo tikrai nereikia. public void paintIcon (galutinis komponentas c, grafika g, int x, int y) { jei (isIconCreated) { realIcon.paintIcon(c, g, x, y); } Kitas { g.drawRect(x, y, plotis-1, aukštis-1); g.drawString(„Įkeliamas vaizdas ...“, x + 20, y + 20); // Piktograma sukurta (tai reiškia, kad vaizdas yra įkeltas) // kitoje gijoje. sinchronizuotas (tai) {SwingUtilities.invokeLater (new Runnable () {public void run () {try {// Sulėtinti vaizdo įkėlimo procesą. Thread.currentThread (). sleep (2000); // „ImageIcon“ konstruktorius sukuria vaizdą . realIcon = new ImageIcon (imageName); isIconCreated = tiesa; } sugauti (InterruptedException ex) {ex.printStackTrace (); } // Sukūrę piktogramą // perdažykite piktogramos komponentą. c. perdažyti (); } }); } } } } 

„ImageIconProxy“ palaiko nuorodą į tikrąją piktogramą su realIcon nario kintamasis. Pirmą kartą nudažius tarpinį serverį, ant atskiros gijos sukuriama tikroji piktograma, kad būtų galima nudažyti stačiakampį ir eilutę (raginimai g.drawRect () ir g.drawString () neįsigalios iki paintIcon () metodas grąžina). Sukūrus tikrąją piktogramą ir įkėlus vaizdą, komponentas, rodantis piktogramą, perdažomas. 5 paveiksle parodyta tų įvykių sekos schema.

5 paveikslo sekos schema būdinga visiems įgaliotiniams: įgaliotieji kontroliuoja prieigą prie savo tikrojo subjekto. Dėl tos kontrolės įgaliotiniai dažnai išprovokuoja savo tikrąjį dalyką, kaip tai yra paveikslėlio piktogramos tarpiniam serveriui, nurodytam 4 pavyzdyje. Tas egzempliorius yra vienas iš „Proxy“ modelio ir „Decorator“ modelio skirtumų: dekoratoriai retai kuria savo tikrąsias temas.

JDK įmontuota „Proxy“ dizaino modelio parama

„Proxy“ modelis yra vienas iš svarbiausių dizaino modelių, nes jis suteikia alternatyvą funkcijų išplėtimui paveldint. Ta alternatyva yra objekto kompozicija, kur objekto (tarpinio serverio) persiuntimo metodas iškviečia uždarą objektą (tikrąjį subjektą).

Daiktų kompozicija yra geriau nei paveldėjimas, nes sudėties atveju uždari objektai gali manipuliuoti savo uždaru objektu tik per uždaro objekto sąsają, o tai lemia laisvą objektų sujungimą. Priešingai, paveldint, klasės yra glaudžiai susijusios su savo pagrindine klase, nes pagrindinės klasės vidinės yra matomas prie jos pratęsimų. Dėl šio matomumo paveldėjimas dažnai vadinamas baltos dėžės pakartotinis naudojimas. Kita vertus, su kompozicija yra uždaro objekto vidiniai nematomas į uždarą objektą (ir atvirkščiai); todėl kompozicija dažnai vadinama juodosios dėžės pakartotinis naudojimas. Jei viskas yra lygu, pirmenybė teikiama juodųjų dėžių pakartotiniam naudojimui (sudėčiai), o ne pakartotiniam baltųjų dėžių (paveldėjimui), nes dėl laisvo sujungimo atsiranda daugiau kaliojo ir lankstesnio sistemų.

Kadangi tarpinio serverio modelis yra toks svarbus, J2SE 1.3 („Java 2 Platform“, „Standard Edition“) ir ne tik palaiko jį tiesiogiai. Ši parama apima tris klases iš java.lang.reflect paketas: Įgaliojimas, Metodasir „InvocationHandler“. 5 pavyzdyje pateiktas paprastas pavyzdys, kuriame naudojamas JDK palaikymas pagalbiniam modeliui:

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