Programmering

Opbygning af et væld af bønner: Opret genanvendelige JavaBeans-komponenter

I denne korte serie undersøger vi udviklingen af ​​JavaBeans softwarekomponenter. I sidste ende vil de fleste bønner blive manipuleret i et udviklingsmiljø for bønner; men vi er kun bekymrede her for kildens aspekter af rammen. Fordelene ved at udvikle JavaBeans - det vil sige at udvikle sig til JavaBeans-specifikationen - er flere gange, blandt dem:

  • Bønner kan let manipuleres i visuelle udviklingsmiljøer af brugere, der ikke behøver at være teknisk dygtige til Java-udvikling på kildeniveau.

  • På grund af standardgrænsefladen kan bønner let distribueres, hvilket gør det lettere for tredjepartskomponenter at blive integreret i udviklingsindsatsen.

  • Udviklere kan nemt overføre kode, der er udviklet til et projekt, til et genanvendeligt bibliotek med komponenter, som kan tilgås i fremtidig udviklingsindsats.

Stormens øje

I

første del af denne serie

, vi udviklede to enkle bønner: en ikke-visuel alarmbønne og en grafisk venstrepil / højrepilbønne. Begge blev udvidet med visuelle

tilpasning

og

bønneoplysninger

klasser. I de bønner, vi dækker denne måned, leverer vi ikke tilpassere; i stedet koncentrerer vi os om at bruge eksisterende bønner og komponenter til at skabe større, bedre bønner.

Forudsætninger

Som fortsættelse af en todelt serie vil jeg antage kendskab til de spørgsmål, der blev diskuteret i den forrige del, inklusive supplerende artikler og ressourcer.

Bønnerne

Fra start til slut af denne serie udvikler vi følgende bønner:

AlarmBean En ikke-grafisk bønne, der affyrer en begivenhed efter en bestemt forsinkelse.
ArrowBean

En grafisk venstre-pil / højrepil bønne.

ProgressBean

En grafisk fremskridt-display bønne.

NumberFieldBean

Et grafisk tal Tekstfelt bønne med rulleknapper. Denne bønne bruger ArrowBean bønnen.

FontChooserBean

En grafisk bønner til fontvælger. Denne bønne bruger NumberFieldBean bønnen.

FontSelectorBean

En grafisk fontvælgerbønne, der viser den aktuelle skrifttype og indeholder OK / Annuller-knapper. Denne bønne bruger FontChooserBean bønnen.

FontDialogBean

En grafisk fontvælgerbønne, der popper fontvælgeren op i en separat dialog. Denne bønne bruger FontSelectorBean bønnen.

Vi diskuterede AlarmBean og ArrowBean bønner i detaljer sidste måned; i denne episode vil vi diskutere de resterende bønner i forskellige detaljeringsniveauer.

Du undrer dig måske over, hvorfor vi bygger tre fontbønner. Det ultimative mål er simpelthen at fremstille en skrifttypevælgerbønne, der popper op i en fontdialog, når brugeren klikker på en knap. Denne opgave opdeles meget naturligt i de tre bønner, vi producerer: Den første er brugergrænsefladen til skrifttypevalg, den anden tilføjer dialogkontrol og en skrifttypeprøve, og den tredje introducerer en knap til at poppe op i dialogen og indeholder den grundlæggende dialoghåndteringskode.

Uden bønner er vi nødt til at udvikle disse varer som specialiserede AWT-komponenter eller som en enkelt monolitisk klasse; ved hjælp af bønner kan vi udvikle de tre dele som uafhængige bønner, der kan genbruges i deres egen ret.

Vores anvendelsesområde

Som med den første del af denne serie er vi kun bekymrede over beanismerne i disse klasser og ikke de egentlige møtrikker og bolte, der får dem til at krydse. Som et resultat vil vi diskutere bønnerne i skeletform og fremhæve de fragmenter, der er særligt relevante i rødt, og efterlade de andre detaljer, som du kan læse i din fritid. Vi vil heller ikke beskæftige os med tilpassere, som vi dækkede tilstrækkeligt detaljeret med vores diskussion af de to første bønner.

For at se tvangsarbejde bag bønnerne skal du tjekke den komplette kildekode.

Opbygning af ProgressBean bønne

ProgressBean

er en simpel fremskridt display bønne. Det er en brugerdefineret AWT-komponent, der viser en procentværdi og grafisk stregrepræsentation af denne værdi, som vist i figuren nedenfor. Den udsætter to egenskaber: de aktuelle og maksimale barværdier.

Den aktuelle værdi eksponeres som en observerbar ejendom. Observerbare egenskaber er egenskaber, hvis ændringer kan observeres. Observatører registreres med bønnen på samme måde som begivenhedslyttere er, og de får besked, når en ejendom ændres. En bønnes individuelle egenskaber skal gøres eksplicit observerbar af bønnen; det er ikke muligt at observere ændringer i en hvilken som helst bønns ejendom.

Denne bønne er implementeret med følgende to klasser:

  • ProgressBean - Hovedbønneklassen

  • ProgressBeanBeanInfo - Bønneoplysningsklassen

Klasse ProgressBean

Det

ProgressBean klasse er hovedbønneklassen, en simpel brugerdefineret AWT-komponent og Java-bønne.

offentlig klasse ProgressBean udvider komponent ... 

Denne bønne er en let komponent, så vi forlænger Komponent i stedet for Lærredog give en passende maling() metode. Den lette komponentramme er mere effektiv end den traditionelle brugerdefinerede komponentramme, hvilket kræver færre ressourcer i det lokale vinduessystem. Som en komponent arver vi automatisk den seriabilitet, der kræves af JavaBeans, og vi leverer standard no-arg-konstruktøren.

public void setBarground (Color c) ... public Color getBarground () ... public synchronized void setMaximum (int m) ... public int getMaximum () ... 

Her afslører vi Farve ejendom bargrund (farven på den viste bjælke) og int ejendom maksimum (den maksimale søjleværdi).

offentlig synkroniseret ugyldig setValue (int v) {if (værdi! = v) {værdi = v; genmaling (); fireValueChange (); }} offentlig int getValue () ... 

Det int ejendom værdi er observerbar, hvilket betyder, at vi skal informere alle interesserede lyttere, når dens værdi ændres. Til dette formål kalder vi vores fireValueChange () metode til at informere lytterne når som helst setValue () Hedder.

beskyttede PropertyChangeSupport lyttere = nye PropertyChangeSupport (dette); offentlig ugyldig addPropertyChangeListener (PropertyChangeListener l) {listeners.addPropertyChangeListener (l); } offentlig tomrum removePropertyChangeListener (PropertyChangeListener l) {listeners.removePropertyChangeListener (l); } 

Her opretholder vi en liste over objekter, der er registreret til at blive underrettet, hver gang en observerbar ejendom ændres. Vi bruger klassen PropertyChangeSupport fra java.bønner pakke for at vedligeholde denne liste. Konstruktøren til denne klasse kræver, at vi specificerer den bønne, der vil være oprindelsen til egenskabsændringshændelser; i dette tilfælde er det det herog de metoder, den giver, giver os mulighed for at vedligeholde listen.

Ved at udsætte metoderne addPropertyChangeListener () og removePropertyChangeListener (), angiver vi automatisk, at denne bønne har observerbare egenskaber. Vi angiver dog ikke hvilken egenskaber er observerbare. Disse oplysninger skal dokumenteres korrekt med bønnen.

beskyttet heltalværdi = nyt heltal (værdi); beskyttet ugyldigt fireValueChange () {listeners.firePropertyChange ("værdi", oValue, oValue = nyt heltal (værdi)); } 

Vi kalder denne metode for at underrette lyttere om en ændring i vores værdi ejendom; vi bruger firePropertyChange () metode på vores liste til at udbrede denne meddelelse. Den første parameter er navnet på ejendommen, som skal matche navnet på en eksponeret ejendom; den anden parameter er den gamle værdi af ejendommen; og den tredje egenskab er den nye værdi. Det PropertyChangeSupport klasse vender tilbage uden at gøre noget, hvis de gamle og nye værdier er de samme.

Klasse ProgressBeanBeanInfo

Det

ProgressBeanBeanInfo klasse beskriver simpelthen ProgressBean bønne, tilslørede arvelige oplysninger, som vi ønsker at skjule.

Opbygning af NumberFieldBean bønne

Denne bønne implementerer en fælles brugergrænsefladekomponent, det rullbare nummerindtastningsfelt - et numerisk tekstfelt, der giver stignings- og nedbrydningspile, som vist i nedenstående figur. Denne bønne bringer et vigtigt JavaBeans-koncept op:

programmatisk manipulation af bønner

.

Programmatisk manipulation af bønner henviser til de mekanismer, som JavaBeans giver for programmatisk oprettelse og adgang til bønner. Selv om det er muligt at få adgang til bønner ved hjælp af standard oprettelse af Java-objekter (ny X ()) og type støbemekanismer ((Y) x) anbefales det, at du bruger de medfølgende JavaBeans-mekanismer til at muliggøre fremtidig udvidelse af JavaBeans-rammen.

Denne bønne er implementeret med følgende to klasser:

  • NumberFieldBean - Hovedbønneklassen

  • NumberFieldBeanBeanInfo - Bønneoplysningsklassen

Klassenummer FieldBean

Det NumberFieldBean klasse, den vigtigste bønneklasse, er en AWT-beholder, der tilføjer tre komponenter: to ArrowBean bønner og en Tekstfelt. Programmatisk adgang til ArrowBean klasse kræver, at vi bruger de mekanismer til manipulation af bønner, jeg nævnte for et øjeblik siden.

Den aktuelle numeriske værdi eksponeres som en observerbar egenskab. Selvom det er en normal egenskab, der kan tilgås og manipuleres gennem de sædvanlige metoder til anvendelse af bønner, er det også observerbar, så lyttere kan registrere sig for at blive underrettet, når dens værdi ændres. Vi affyrer ikke en begivenhed, når brugeren trykker på Return, selvom det ville være en åbenbar udvidelse til denne klasse.

offentlig klasse NumberFieldBean udvider Container implementerer ActionListener ... 

Vi strækker os ud Beholder og implementere ActionListener for at modtage begivenheder fra de bønner og AWT-komponenter, som vi bruger. Forlænger Beholder i stedet for det mere traditionelle Panel betyder, at denne bønne, ligesom ProgressBean bønne er en letvægtskomponent.

offentlig NumberFieldBean () ... 

Som en bønne skal vi levere en offentlig konstruktør uden argumenter. Bemærk, at vi ikke skal levere andre konstruktører til programmatisk brug; dette ville gå imod JavaBeans-adgangsmekanismen.

prøv {down = (ArrowBean) Beans.instantiate (getClass () .getClassLoader (), "org.merlin.beans.arrow.ArrowBean"); } fange (Undtagelse ex) {ex.printStackTrace (); } 

Her opretter vi en ArrowBean ved hjælp af den programmatiske mekanisme til instantiering af bønner. Vi bruger ikke standard Java ny operatør; i stedet bruger vi instantiere () metode til klasse Bønner. Vi specificerer ClassLoader at bruge til lastning af bønneklassen; i dette tilfælde bruger vi vores egne ClassLoader og det fuldt kvalificerede navn på bønneklassen ("org.merlin.beans.arrow.ArrowBean"), og støb den resulterende Objekt til den relevante klasse.

Bemærk, at instantiere () metoden kan kaste en række undtagelser (for eksempel hvis den angivne bønne ikke kunne findes). Vi fanger og viser simpelthen sådanne undtagelser, som forresten ikke skulle forekomme, hvis bønnen er installeret korrekt.

add ("East", (Component) Beans.getInstanceOf (down, Component.class)); 

Her kaster vi ArrowBean til en Komponent og tilføj det som en normal Komponent. Vi bruger ikke standarden (Komponent) type-casting mekanisme, og vi bruger ikke det faktum, at vores AlarmBean er en underklasse af Komponent; i stedet bruger vi getInstanceOf () metode til klasse Bønner. Vi specificerer den bønne, vi ønsker at kaste, og Klasse objekt, som vi ønsker at kaste det (i dette tilfælde Komponent.klasse).

Selvom denne tilgang ikke giver mening lige nu, vil fremtidige versioner af JavaBeans understøtte bønner, der består af flere klassefiler, såvel som bønner, der kan eksponere forskellige aspekter af sig selv som de forskellige klasser. For eksempel kan en bønne synes at underklasse begge dele Komponent og RemoteObject ved at tilvejebringe to sammenkoblede klasser: a Komponent og en RemoteObject. Ved hjælp af JavaBeans-casting-mekanismen kan det relevante bønneobjekt returneres automatisk, så bønner kan have tilsyneladende flere arv, selvom Java ikke understøtter dette. For detaljer, se JavaBeans-specifikationen "Glasgow". (Et link til denne spec findes i afsnittet Ressourcer i denne artikel.)

Det er nødvendigt for os at bruge disse adgangsmekanismer for bønner nu, så vi kan overføre vores bønner til fremtidige JavaBeans-teknologier uden problemer.

down.setDirection (ArrowBean.LEFT); down.addActionListener (dette); 

Her konfigurerer vi ArrowBean bruger setDirection () ejendomsadgang og addActionListener () registreringsmetode. Vi kan bruge disse ejendomsadgangere og lytterregistreringsmetoder direkte på den bønne, vi lige har oprettet; det er kun nødvendigt at bruge JavaBeans-casting-funktionen, når vi får adgang til et aspekt af en bønne, der arves fra en anden klasse.

offentlig synkroniseret ugyldig setValue (int v) {field.setText (String.valueOf (v)); fireValueChange (getValue ()); } offentlig synkroniseret int getValue () ... 

Her afslører vi int ejendom værdi, som er værdien af ​​dette felt. Denne egenskab kan observeres, så vi skal underrette lyttere, når den ændres. Vi gør dette ved at kalde vores fireValueChange () metode.

public void setColumn (int c) ... public int getColumns () ... public synchronized void setMinimum (int m) ... public int getMinimum () ... public synchronized ugyldig setMaximum (int m) ... public int getMaximum () ... offentligt synkroniseret ugyldigt sætStep (int s) ... public int getStep () ... 

Her afslører vi int ejendomme kolonner, minimum, maksimumog trin, som henholdsvis er antallet af kolonner, der vises i Tekstfelt, minimums- og maksimumværdier, som dette felt skal indeholde, og det beløb, hvormed pileknapperne skal ændre værdien. Disse egenskaber kan ikke observeres.

Bemærk, at vi bruger synkronisering for at sikre trådsikkerhed, hvor det er relevant.

offentlig synkroniseret ugyldig handlingPerformeret (ActionEvent e) {int værdi = getValue (); hvis (e.getSource () == ned) {hvis (værdi> minimum) {værdi = (værdi - trin> værdi)? minimum: klemme (værdi - trin); setValue (værdi); }} ...