einseitig

Werbung
Zentrale Aspekte der Komponentenorientierung
Komponentenbasierte
Software- Entwicklung
Prof. Dr.
Stephan Kleuker
42
2. JavaBeans als Komponenten
•
•
•
•
•
Java-GUI-Elemente sind Beans
Typischer Aufbau von Beans
Bound properties
Constrained Properties
Speichern
Literatur:
• Sun, JavaBeans 1.01 Specification, http://java.sun.com/
javase/technologies/desktop/javabeans/docs/spec.html
• C. Ullenboom, Java ist auch eine Insel, 8. Auflage, Galileo
Press [Abschnitt 7.4]
Komponentenbasierte
Software- Entwicklung
Prof. Dr.
Stephan Kleuker
53
Hintergrund und Motivation
• JavaBeans sind als frühes Komponentenmodell entstanden
• Objekte einfach serialisierbar (damit einfach im Netz
austauschbar)
• Beans-Framework ermöglicht einfache Kommunikation
unter Beans
• Haupteinsatz: GUI-Komponenten, Swing nutzt Technologie
(ermöglicht u. a. GUI-Builder [gute/schlechte])
• Aktuelle Spezifikation: JavaBeans 1.01
• Ideen für JavaBeans Spec 2.0 (JSR-273) existieren
• Zitat: “A Java Bean is a reusable software component that
can be manipulated visually in a builder tool.”
• Achtung: nicht mit Enterprise JavaBeans verwechseln
Komponentenbasierte
Software- Entwicklung
Prof. Dr.
Stephan Kleuker
54
Erinnerung : JButton ( Nutzung )
public class ButtonFrame extends JFrame {
public ButtonFrame() {
setSize(200, 100);
JButton rot = new JButton("rot");
rot.addActionListener(new MeineAction(getContentPane(),
Color.RED));
add(rot, BorderLayout.EAST);
JButton blau = new JButton("blau");
blau.addActionListener(new MeineAction(getContentPane(),
Color.BLUE));
add(blau, BorderLayout.WEST);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {new ButtonFrame().setVisible(true);}
});
}
}
Komponentenbasierte
Software- Entwicklung
Prof. Dr.
Stephan Kleuker
55
Erinnerung : JButton ( ActionListener )
import
import
import
import
java.awt.Color;
java.awt.Component;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
public class MeineAction implements ActionListener {
private Component komponente;
private Color farbe;
public MeineAction(Component komponente, Color farbe){
this.komponente = komponente;
this.farbe = farbe;
}
}
public void actionPerformed(ActionEvent e) {
komponente.setBackground(farbe);
}
Komponentenbasierte
Software- Entwicklung
Prof. Dr.
Stephan Kleuker
56
Typische Beanmethoden ( 1 / 2 )
public class Knopf {
public static void main(String[] s){
JButton jb= new JButton();
jb.addPropertyChangeListener(new PCL());
jb.setText("touch me");
jb.setToolTipText("bin ne Bean");
jb.setBackground(Color.red);
jb.setBorderPainted(false);
JFrame jf = new JFrame();
jf.addPropertyChangeListener(new PCL());
jf.add(jb);
jf.setSize(200, 100);
jf.setTitle("Knopf");
jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
jf.setVisible(true);
}
}
Komponentenbasierte
Software- Entwicklung
Prof. Dr.
Stephan Kleuker
57
Typische Beanmethoden ( 2 / 2 )
public class PCL implements PropertyChangeListener{
public PCL() {}
public void propertyChange(PropertyChangeEvent evt) {
System.out.println(evt.getPropertyName()
+" alt:"+evt.getOldValue()
+" neu:"+evt.getNewValue());
} text alt: neu:touch me
}
ToolTipText alt:null neu:bin ne Bean
background alt:javax.swing.plaf.ColorUIResource[r=238,...
borderPainted alt:true neu:false
title alt: neu:Knopf
defaultCloseOperation alt:1 neu:3
foreground alt:null neu:java.awt.Color[r=0,g=0,b=0]
font alt:null neu:java.awt.Font[family=Dialog,name=Dia...
neu:java.awt.Font[family=Dialog,name=Dia...
ancestor alt:null neu:javax.swing.JPanel[null.contentP...
neu:javax.swing.JPanel[null.contentP...
Komponentenbasierte
Software- Entwicklung
Prof. Dr.
Stephan Kleuker
58
Elementare Anforderungen an JavaBean
• Leerer Konstruktor
• Alle Exemplarvariablen (Properties, Attribute) über get- und
set-Methoden erreichbar
• Variable private <Typ> xx;
public void setXx(<Typ> xx) {
this.xx = xx;
}
public <Typ> getXx() {
return xx;
}
• Methoden können weiteren Code enthalten
• Jedwede Typen von Variablen sind serialisierbar
Komponentenbasierte
Software- Entwicklung
Prof. Dr.
Stephan Kleuker
59
Minimales Beispiel
import java.io.Serializable;
public class Student implements Serializable{
private String name;
private int cp;
public Student(){}
public int getCp() {
return cp;
}
public void setCp(int cp) {
this.cp = cp;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Komponentenbasierte
Software- Entwicklung
Prof. Dr.
Stephan Kleuker
60
Indizierte Eigenschaften
• Für Eigenschaften, die in Arrays gespeichert werden,
besteht zusätzlich folgende Möglichkeit (Ausschnitt)
private String[] vorlesung;
public String[] getVorlesung() { //bekannt
return vorlesung;
}
public void setVorlesung(String[] vorlesung) { //bekannt
this.vorlesung = vorlesung;
}
public String getVorlesung(int index) {
return vorlesung[index];
}
public void setVorlesung(String vl, int index) {
vorlesung[index]=vl;
}
Komponentenbasierte
Software- Entwicklung
Prof. Dr.
Stephan Kleuker
61
Einschub : typischer schlechter Stil
• Arrays sind für dynamische Datenmengen unflexibel
• Collections sind zum Glück serialisierbar
private Set<String> vorlesung= new HashSet<String>();
• In JavaBeans können weitere Methoden ergänzt werden
public void weitereVorlesung(String v){
vorlesung.add(v);
}
• Leider nicht unüblich der Stil „Innereien herausreißen,
verändern, Innereien wieder hinschieben“ (verletzt
eigentlich Geheimnisprinzip)
Student st = new Student();
st.getVorlesung().add("KomSE");
Komponentenbasierte
Software- Entwicklung
Prof. Dr.
Stephan Kleuker
62
Gebundene Eigenschaften
• Bound properties sind Exemplarvariablen, die Änderungen
interessierten Beans mitteilen (Observer-Observable)
• Wer Änderungen mitteilen will,
– benötigt Objekt der Klasse PropertyChangeSupport
– muss Methoden add/removePropertyChangeListener
implementieren
• Interessenten für Änderungen müssen sich mit add…
anmelden
• Bei Anmeldung muss Objekt übergeben werden, das das
Interface PropertychangeEvent implementiert
Komponentenbasierte
Software- Entwicklung
Prof. Dr.
Stephan Kleuker
63
Beispiel- Erweiterung in Student ( 1 / 2 )
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
…
private PropertyChangeSupport pcs=new PropertyChangeSupport(this);
public void setCp(int cp) {
int alt=this.cp;
this.cp = cp;
pcs.firePropertyChange("cp", alt, cp);
}
public void addPropertyChangeListener(PropertyChangeListener l){
pcs.addPropertyChangeListener(l);
}
public void removePropertyChangeListener(
PropertyChangeListener l){
pcs.removePropertyChangeListener(l);
}
Komponentenbasierte
Software- Entwicklung
Prof. Dr.
Stephan Kleuker
64
Beispiel- Erweiterung in Student ( 2 / 2 )
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
public class Studentnutzer {
public static void main(String[] args) {
Student s = new Student();
s.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent e) {
System.out.println("Eigenschaft "+e.getPropertyName()
+" alt:"+e.getOldValue()+" neu:"+e.getNewValue());
}
});
s.setCp(42);
s.setCp(s.getCp()+5);
s.setCp(47);
Eigenschaft cp alt:0 neu:42
}
Eigenschaft cp alt:42 neu:47
}
Komponentenbasierte
Software- Entwicklung
Prof. Dr.
Stephan Kleuker
65
Veto - Eigenschaften
• Spezielle Möglichkeit von JavaBeans: Vetoable (constrained)
– Bean meldet angemeldeten Beans, dass eine
Exemplarvariable geändert wird
– Jede Bean kann „Einspruch“ gegen die Änderung
(PropertyVetoException) einlegen
• Konkretes Szenario: Kundenbestellung soll durchgeführt
werden, Kontoverwaltung und Lagerverwaltung lauschen und
können Einspruch einlegen
• Schwierig, Daten konsistent zu halten (wer kein Veto einlegt,
rechnet weiter); deshalb erst nach Vetos fragen (keiner
rechnet weiter), dann als gebundene Eigenschaft propagieren
• Nach Einspruch werden alle angemeldeten Beans erneut mit
altem Wert informiert
Komponentenbasierte
Software- Entwicklung
Prof. Dr.
Stephan Kleuker
66
Beispiel ohne Bound Property ( 1 / 3 )
private VetoableChangeSupport vcs=new VetoableChangeSupport(this);
public void setVorlesung(Set<String> vorlesung) {
Set<String> old = this.vorlesung;
in Student
try {
vcs.fireVetoableChange("vl", old, vorlesung);
this.vorlesung = vorlesung;
} catch (PropertyVetoException ex) {
System.out.println("abgelehnt: "+ex.getMessage());
}
}
public void addVetoableChangeListener(VetoableChangeListener l){
vcs.addVetoableChangeListener(l);
}
public void removeVetoableChangeListener(
VetoableChangeListener l) {
vcs.removeVetoableChangeListener(l);
}
Komponentenbasierte
Software- Entwicklung
Prof. Dr.
Stephan Kleuker
67
Beispiel ohne Bound Property ( 2 / 3 )
public class MeinVeto implements VetoableChangeListener{
private String schlecht;
private int aenderung;
public MeinVeto(String schlecht) {
this.schlecht = schlecht;
}
@Override
public void vetoableChange(PropertyChangeEvent evt)
throws PropertyVetoException {
Set<String> neu = (Set<String>) evt.getNewValue();
if (neu.contains(schlecht))
throw new PropertyVetoException("nicht "+schlecht, evt);
System.out.println("für "+schlecht+": "+(++aenderung));
}
}
Komponentenbasierte
Software- Entwicklung
Prof. Dr.
Stephan Kleuker
68
Beispiel ohne Bound Property ( 3 / 3 )
public static void main(String[] args) {
Student stu = new Student();
Set<String> vls = new HashSet();
vls.add("C");
vls.add("Java");
stu.addVetoableChangeListener(new MeinVeto("BWL"));
stu.addVetoableChangeListener(new MeinVeto("C++"));
stu.setVorlesung(vls);
Set<String> tmp = (Set<String>)vls.clone();
für BWL: 1
tmp.add("C++");
für C++: 1
stu.setVorlesung(tmp);
System.out.println(stu.getVorlesung()); für BWL: 2
}
für BWL: 3
für C++: 2
abgelehnt: nicht C++
[C, Java]
Komponentenbasierte
Software- Entwicklung
Prof. Dr.
Stephan Kleuker
69
Einfaches Speichern ( von JavaBeans )
public static void main(String[] args) {
Student stu = new Student();
HashSet<String> vls = new HashSet();
vls.add("C");
vls.add("Java");
stu.setVorlesung(vls); stu.setName("Erwin");
try {
XMLEncoder out = new XMLEncoder(new BufferedOutputStream(
new FileOutputStream("stu.xml")));
out.writeObject(stu);
out.close();
XMLDecoder in= new XMLDecoder(new BufferedInputStream(
new FileInputStream("stu.xml")));
Student st= (Student)in.readObject();
System.out.println(st.getVorlesung());
in.close();
} catch (FileNotFoundException ex) { }
[C, Java]
}
Komponentenbasierte
Software- Entwicklung
Prof. Dr.
Stephan Kleuker
70
stu.xml
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.6.0_12" class="java.beans.XMLDecoder">
<object class="beans.Student">
<void property="name">
<string>Erwin</string>
</void>
<void property="vorlesung">
<void method="add">
<string>C</string>
</void>
<void method="add">
<string>Java</string>
</void>
</void>
</object>
</java>
Komponentenbasierte
Software- Entwicklung
Prof. Dr.
Stephan Kleuker
71
Analyse des Beispiels
• Wesentliche Funktionalität wurde an Java (genauer die
Virtual Machine VM) abgegeben; diese arbeitet als
Container
• VM kann direkt auf Exemplarvariablen zugreifen (Ansätze
mit Introspection, Reflection evtl. später)
– Gib mir Exemplarvariablen
– Gib mir Exemplarmethoden
– (Textanalyse, Beginn mit get/set)
– Rufe auf Objekt mit Methode mit Namen … und
Parametern … auf
Komponentenbasierte
Software- Entwicklung
Prof. Dr.
Stephan Kleuker
72
Weiterführend
• Zu jeder Bean kann es eine
BeanInfo-Klasse geben, die
die Bean beschreibt
• Ursprünglich sind Beans für
visuelle Komponenten
entwickelt worden; GUIBuilder erlauben die direkte
Bearbeitung von Properties
• Java-Bean für GUI-Builder in jar-Datei mit Manifest-Datei
(.mf)
• Es gibt eigene Werkzeuge zur Entwicklung mit Beans
Komponentenbasierte
Software- Entwicklung
Prof. Dr.
Stephan Kleuker
73
Herunterladen