Folien

Werbung
© Markus Knauß, 2008
Entwurfsmuster
Entwurfsmuster
Markus Knauß
[email protected]
1
© Markus Knauß, 2008
Motivation
Entwurfsmuster helfen nicht nur bei der Erstellung eines Entwurfs,
sie sind auch nützlich, um ein bestehendes Programm neu zu
strukturieren.
Entwurfsmuster
In den kommenden zwei Vorlesungsterminen wird ein
bestehendes Programm mit Entwurfsmustern neu strukturiert.
2

Praktische Anwendung eines Entwurfsmusters

Erkennen der Vorteile und Nachteile von Entwurfsmustern

Überblick über objektorientierte Konzepte und Entwurfsmuster
Entwurfsmuster
© Markus Knauß, 2008
Ziele
3
Nutzung einer Datenbank für die Speicherung der Eintragungen
eines Geburtstagskalenders.
Entwurfsmuster
© Markus Knauß, 2008
Geburtstagskalender
4
© Markus Knauß, 2008
Entwurfsmuster
Inhalt

Java Database Connectivity (JDBC)

Objektorientierte Konzepte

Template Method Pattern

Entwurfsmuster

Datenbankzugriff mit Entwurfsmustern

Zusammenfassung

Literatur und Links
5
© Markus Knauß, 2008
Java Database Connectivity (JDBC)
JDBC bietet eine plattformunabhängige Schnittstelle für die
Nutzung von Datenbanken in Java-Programmen.
Entwurfsmuster
Das JDBC-API definiert Interfaces, welche die zentralen
Datenbankfunktionen kapseln.

Verbinden mit einer Datenbank

Eine Anweisung ausführen

Ergebnisse einer Anweisung auswerten
6
© Markus Knauß, 2008
JDBC Übersicht
ResultSet
erzeugt
Statement
erzeugt
PreparedStatement
erzeugt
CallableStatement
Entwurfsmuster
erzeugt
Connection
erzeugt
DriverManager
implementiert
herstellerspezifischer
Datenbanktreiber
greift zu auf
java.sql.*
implementiert
JDBC-ODBC Brücke
Datenbank
ODBC Treiber
greift zu auf
7
© Markus Knauß, 2008
Entwurfsmuster
java.sql.Driver
Ein Datenbankanbieter, der eine JDBC-Implementierung anbieten
möchte, muss eine eigene Implementierung für das Interface
java.sql.Driver liefern.
Der JDBC DriverManager (java.sql.DriverManager)
verwaltet in einer JVM verfügbare Datenbanktreiber
(java.sql.Driver) und bietet Zugriff auf die Funktionen der
verfügbaren Treiber.
Um einen Treiber in der JVM verfügbar zu machen, muss dessen
implementierende Klasse mit dem Klassenlader geladen werden.
Hinweis: Der DriverManager ist ein Broker, der Zugriff auf die
Driver-Implementierungen erlaubt. Driver-Implementierungen sind
Factories für den Zugriff auf eine Datenbank.
8
© Markus Knauß, 2008
JDBC am Beispiel
// Datenbanktreiber laden
Class.forName(
"org.apache.derby.jdbc.EmbeddedDriver");
// Verbindung zur Datenbank herstellen
Connection con = DriverManager.getConnection(
"jdbc:derby:/Users/knaussms/tmp/address");
// Auszuführende Anweisung erstellen
Entwurfsmuster
Statement stmt = con.createStatement();
// Anweisung ausführen
ResultSet rs = stmt.executeQuery(
"SELECT * FROM persons");
// Ergebnisse auswerten
while (rs.next()) {
int id
= rs.getInt("id");
String firstName = rs.getString("first_name");
String lastName = rs.getString("last_name");
Date dateOfBirth = rs.getDate("date_of_birth");
DateFormat dateFormat =
DateFormat.getDateInstance(DateFormat.MEDIUM);
System.out.println(Integer.toString(id) +
": " + firstName + " " +
lastName + ", " +
dateFormat.format(dateOfBirth));
}
Die einzige herstellerspezifische
Anweisung ist das Laden des
Datenbanktreibers.
Konfigurationsspezifische
Anweisungen sind das
Verbinden mit der Datenbank
und der Zugriff auf Tabellen und
Spalten.
Alle weiteren Befehle sind
unabhängig von der
verwendeten Datenbank.
// Verbindung zur Datenbank schließen
con.close();
SimpleJDBC.java
9
© Markus Knauß, 2008
Einschub: PersonDB
<<interface>>
IPerson
+setFirstName(firstName:String)
+getFirstName():String
+setLastName(lastName:String)
+getLastName():String
+setDateOfBirth(dateOfBirth:Calendar)
+getDateOfBirth():Calendar
<<interface>>
IDBObject
+getId():int
Entwurfsmuster
PersonBean
Die Klasse PersonDB
implementiert alle Funktionen
für die Speicherung, das Laden,
das Ändern und das Löschen
von GeburtstagskalenderEinträgen in einer Datenbank.
-firstName:String
-lastName:String
-dateOfBirth:Calendar
PersonDB
-id:int
+create(person:IPerson):PersonDB
+read(id:int):PersonDB
+select(qbe:IPerson):List<PersonDB>
+read()
+update()
+delete()
implementiert
erbt von
10
© Markus Knauß, 2008
Entwurfsmuster
Aufgabe
Markieren Sie die einzelnen Schritte für den Datenbankzugriff in
den Methoden create, read, update, delete und select der
Klasse PersonDB.

Welche Anweisungssequenzen können Sie identifizieren?

Welche Teile der Sequenzen sind gleich, wo unterscheiden sie
sich?
con = DriverManager.getConnection(DB_URL);
Mit Datenbank verbinden
PreparedStatement ps = con.prepareStatement(DELETE_STMT);
Statement erstellen
ps.setInt(1, getId());
ps.execute();
Statement intialisieren
und ausführen
con.close();
Verbindung schließen
PersonDB.java
11
© Markus Knauß, 2008
Entwurfsmuster
Beispiel einer Lösung:
Gleichbleibende Anweisungssequenzen
public void read() {
Connection con
= null;
try {
con = DriverManager.getConnection(DB_URL);
PreparedStatement ps = con.prepareStatement(READ_STMT);
ps.setInt(1, getId());
ResultSet rs = ps.executeQuery();
while (rs.next()) {
setFirstName(rs.getString("fist_name"));
setLastName(rs.getString("last_name"));
setDateOfBirth(toCalendar(rs.getDate("date_of_birth")));
}
} catch (SQLException e) {
log.log(Level.SEVERE, e.getMessage(), e);
}
finally {
if (con != null) {
try {
con.close();
} catch (SQLException e) {
log.log(Level.SEVERE, e.getMessage(), e);
}
}
}
}
Verbindung herstellen
Statement erstellen und initialisieren
Statement ausführen
Resultate auswerten
Verbindung schließen
12
© Markus Knauß, 2008
Entwurfsmuster
Beispiel einer Lösung:
Unterschiede
public void read() {
Connection con
= null;
try {
con = DriverManager.getConnection(DB_URL);
PreparedStatement ps = con.prepareStatement(READ_STMT);
ps.setInt(1, getId());
ResultSet rs = ps.executeQuery();
while (rs.next()) {
setFirstName(rs.getString("fist_name"));
setLastName(rs.getString("last_name"));
setDateOfBirth(toCalendar(rs.getDate("date_of_birth")));
}
} catch (SQLException e) {
log.log(Level.SEVERE, e.getMessage(), e);
}
finally {
if (con != null) {
try {
con.close();
} catch (SQLException e) {
log.log(Level.SEVERE, e.getMessage(), e);
}
}
}
}
Statements
Initialisierung
Auswertung
13
© Markus Knauß, 2008
Entwurfsmuster
Inhalt

Java Database Connectivity (JDBC)

Objektorientierte Konzepte

Template Method Pattern

Entwurfsmuster

Datenbankzugriff mit Entwurfsmustern

Zusammenfassung

Literatur und Links
14
© Markus Knauß, 2008
Klassen
ModelFactory
-instance:ModelFactory
+getInstance():ModelFactory
Eine Klasse ist eine Schablone
für Objekte, die aus der Klasse
erzeugt werden können.
Entwurfsmuster
Jede Klasse existiert nur einmal
in einem laufenden Programm.
Eine Klasse kann einen Zustand
haben und Methoden anbieten.
15
© Markus Knauß, 2008
Entwurfsmuster
Objekte
Person
-firstName:String
-lastName:String
-dateOfBirth:Calendar
+getFirstName():String
+setFirstName(firstName:String)
+getLastName():String
+setLastName(lastName:String)
+getDateOfBirth():Calendar
+setDateOfBirth(dateOfBirth:Calendar)
JaggerMick:Person
RichardsKeith:Person
-firstName=“Mick“
-lastName=“Jagger“
-dateOfBirth='26.7.1943'
-firstName=“Keith“
-lastName=“Richards“
-dateOfBirth='18.12.1943'
Objekte werden aus Klassen
erzeugt (instantiiert).
Aus jeder Klassen können
beliebig viele Objekte erzeugt
werden.
Jedes Objekt hat eine Identität
und einen Zustand.
16
© Markus Knauß, 2008
Entwurfsmuster
Vererbung
Vererbung drückt eine „ist ein“Beziehung aus.
Person
-firstName:String
-lastName:String
-dateOfBirth:Calendar
+getFirstName():String
+setFirstName(firstName:String)
+getLastName():String
+setLastName(lastName:String)
+getDateOfBirth():Calendar
+setDateOfBirth(dateOfBirth:Calendar)
Objekte von erbenden Klassen
können an Stelle von Objekten
der vererbenden Klasse
verwendet werden.
List<Person> persons = new ArrayList<Person>();
-id:int
public void store(Person person) {
persons.add(person);
}
+create(person:IPerson):PersonDB
+read(id:int):PersonDB
+select(qbe:IPerson):List<PersonDB>
+read()
+update()
+delete()
public static void main(String[] args) {
PersonBean personBean = new PersonBean();
PersonDB personDB = new PersonDB();
store(personBean);
store(personDB);
}
PersonBean
PersonDB
17
© Markus Knauß, 2008
Polymorphie
Erbende Klassen können Methoden überschreiben.
Durch das Überschreiben kann das Verhalten einer Methode
verändert werden.
Entwurfsmuster
Polymorphie = Vielgestaltigkeit, Verschiedengestaltigkeit
18
© Markus Knauß, 2008
Polymorphie
Person
-firstName:String
Entwurfsmuster
+getFirstName():String
+setFirstName(firstName:String)
public String getFirstName() {
read();
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
update();
}
PersonBean
PersonDB
+getFirstName():String
+setFirstName(firstName:String)
+getFirstName():String
+setFirstName(firstName:String)
+read()
+update()
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
19
© Markus Knauß, 2008
Abstrakte Klassen, abstrakte Methoden
Person
DBObject
Entwurfsmuster
+getFirstName():String
+setFirstName(firstName:String)
+getLastName():String
+setLastName(lastName:String)
+getDateOfBirth():Calendar
+setDateOfBirth(dateOfBirth:Calendar)
PersonBean
-firstName:String
-lastName:String
-dateOfBirth:Calendar
+getId():int
+read()
+update()
+delete()
PersonDB
-id:int
+create(person:IPerson):PersonDB
+read(id:int):PersonDB
+select(qbe:IPerson):List<PersonDB>
Von abstrakten Klassen können
keine Objekte erzeugt werden.
Abstrakte Methoden haben
keine Implementierung, sie
müssen in der erbenden Klasse
überschrieben werden.
Abstrakte Methoden können nur
in abstrakten Klassen deklariert
werden.
20
© Markus Knauß, 2008
Entwurfsmuster
Aufgabe

Kapseln Sie die spezifischen Anweisungsteile der readMethode in eigenen Methoden.

Skizzieren Sie die Klasse DBStatement, in der die Methoden,
in denen die spezifischen Anweisungsteile der read-Methode
zusammengefasst sind, mit einer Standardimplementierung
realisiert sind.

Skizzieren Sie die von DBStatement erbende Klasse
ReadStatement, in der die Methoden mit den spezifischen
Anweisungsteilen der read-Methode enthalten sind.

Überarbeiten Sie die Implementierung der read-Methode so,
dass nur die Methoden mit den spezifischen Anweisungsteilen
aus der Klasse ReadStatement verwendet werden.
21
© Markus Knauß, 2008
Beispiel einer Lösung:
Klasse DBStatement
public abstract class DBStatement {
public abstract String getStatement();
public void initParameter(PreparedStatement stmt)
throws SQLException {
}
Entwurfsmuster
public void evaluateResults(ResultSet rs)
throws SQLException {
}
}
DBStatement.java
22
© Markus Knauß, 2008
Beispiel einer Lösung:
Klasse ReadStatement
public class ReadStatement extends DBStatement {
private
private
private
private
int id;
String firstName;
String lastName;
Calendar dateOfBirth;
Entwurfsmuster
@Override
public String getStatement() {
return "SELECT * FROM persons WHERE id = ?";
}
@Override
public void initParameter(PreparedStatement stmt) throws SQLException {
stmt.setInt(1, id);
}
@Override
public void evaluateResults(ResultSet rs) throws SQLException {
firstName = rs.getString("fist_name");
lastName = rs.getString("last_name");
dateOfBirth = CalendarUtils.toCalendar(rs.getDate("date_of_birth"));
}
// Get and set methods for attributes.
}
ReadStatement.java
23
© Markus Knauß, 2008
Entwurfsmuster
Beispiel einer Lösung:
read()-Methode
private ReadStatement readStatement = new ReadStatement();
public void read() {
Connection con = null;
try {
con = DriverManager.getConnection(DB_URL);
PreparedStatement ps = con.prepareStatement(readStatement.getStatement());
readStatement.setId(getId());
readStatement.initParameter(ps);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
readStatement.evaluateResults(rs);
}
} catch (SQLException e) {
log.log(Level.SEVERE, e.getMessage(), e);
}
finally {
if (con != null) {
try {
con.close();
} catch (SQLException e) {
log.log(Level.SEVERE, e.getMessage(), e);
}
}
}
}
PersonDB.java
24
© Markus Knauß, 2008
Was wurde erreicht?
Die Implementierung der speziellen Teile einer DatenbankAnweisung können in eigenen Klassen gekapselt werden.
Entwurfsmuster
Der Algorithmus für die Ausführung einer Anweisung ist in allen
Methoden gleich!
DBStatement
+getStatement():String
+initParameter(stmt:PreparedStatement)
+evaluateResults(rs:ResultSet)
CreateStatement
ReadStatement
UpdateStatement
DeleteStatement
25
© Markus Knauß, 2008
Entwurfsmuster
Inhalt

Java Database Connectivity (JDBC)

Objektorientierte Konzepte

Template Method Pattern

Entwurfsmuster

Datenbankzugriff mit Entwurfsmustern

Zusammenfassung

Literatur und Links
26
© Markus Knauß, 2008
Entwurfsmuster
Beobachtungen
Die Abfolge der Schritte für den Datenbankzugriff via JDBC ist
immer gleich.

Verbindung zur Datenbank öffnen

Anweisung erstellen

Parameter initialisieren

Anweisung ausführen

Ergebnisse auswerten

Verbindung zur Datenbank schließen
Die Schritte unterscheiden sich in der ausgeführten Anweisung,
den Parametern und der Auswertung der Ergebnisse.
27
© Markus Knauß, 2008
Template Method
Zweck
Definiere einen Algorithmus in einer Methode. Delegiere einzelne
Schritte an erbende Klassen.
Entwurfsmuster
Die Verwendung einer Template Method ermöglicht es erbenden
Klassen, bestimmte Schritte eines Algorithmus zu überschreiben,
ohne die Struktur des Algorithmus zu ändern.
28
© Markus Knauß, 2008
Entwurfsmuster
Template Method
Motivation
Zum Beispiel Datenbankzugriff via JDBC:

Die Abfolge der Schritte für den Datenbankzugriff mit JDBC ist
immer gleich.

Die Inhalte der einzelnen Schritte, zum Beispiel die konkrete
Anweisung oder die Auswertung der Ergebnisse, sind
verschieden.
29

Invariante Teile eines Algorithmus sollen genau einmal
implementiert werden.

Gemeinsames Verhalten soll in einer Klasse zusammengefasst
werden.

Kontrolle der Erweiterungen durch Vererbung
Entwurfsmuster
© Markus Knauß, 2008
Template Method
Anwendbarkeit
30
© Markus Knauß, 2008
Template Method
Lösung
CreateStatement
Entwurfsmuster
DBStatement
+getStatement():String
+initParameter(stmt:PreparedStatement)
+evaluateResults(rs:ResultSet)
+execute()
PersonDB
ReadStatement
-id:int
UpdateStatement
DeleteStatement
SelectStatement
+create(person:IPerson):PersonDB
+read(id:int):PersonDB
+select(qbe:IPerson):List<PersonDB>
+read()
+update()
+delete()
NextPrimaryKeyStatement
31
© Markus Knauß, 2008
Entwurfsmuster
Template Method
Lösung
public final void execute() {
Connection con = null;
try {
con = DriverManager.getConnection(DB_URL);
PreparedStatement ps = con.prepareStatement(getStatement());
initParameter(ps);
ps.execute();
ResultSet rs = ps.getResultSet();
if (rs != null) {
while (rs.next()) {
evaluateResults(rs);
}
}
} catch (SQLException e) {
log.log(Level.SEVERE, e.getMessage(), e);
}
finally {
if (con != null) {
try {
con.close();
} catch (SQLException e) {
log.log(Level.SEVERE, e.getMessage(), e);
}
}
}
}
DBStatement.java
32
public class PersonDB extends PersonBean implements IPerson, IDBObject {
private static final CreateStatement createStatement = new CreateStatement();
private static final ReadStatement readStatement = new ReadStatement();
private static final NextPrimaryKeyStatement nextPrimaryKeyStatement = new NextPrimaryKeyStatement();
//...
public static PersonDB create(IPerson person) {
nextPrimaryKeyStatement.execute();
int nextPK = nextPrimaryKeyStatement.getNextPrimaryKey();
createStatement.setId(nextPK);
createStatement.setFirstName(person.getFirstName());
createStatement.setLastName(person.getLastName());
createStatement.setDateOfBirth(person.getDateOfBirth());
createStatement.execute();
return new PersonDB(nextPK, person);
}
Entwurfsmuster
© Markus Knauß, 2008
Template Method
Lösung
public static PersonDB read(int id) {
readStatement.setId(id);
readStatement.execute();
return new PersonDB(
id, readStatement.getFirstName(),
readStatement.getLastName(), readStatement.getDateOfBirth());
}
//...
}
PersonDB.java
33

Gemeinsames Verhalten wird in einer Klasse gekapselt.

Der Kontrollfluss wird invertiert, die vererbende Klasse ruft
Methoden der erbenden Klasse auf.

Es muss klar sein, welche Methoden überschrieben werden
dürfen bzw. überschrieben werden müssen.
Entwurfsmuster
© Markus Knauß, 2008
Template Methode
Konsequenzen
34

Factory, Factory Method: nutzt Template Method zur
Objekterzeugung

Strategy: Kapselung eines Algorithmus
Entwurfsmuster
© Markus Knauß, 2008
Template Methode
Ähnliche und Verwandte Muster
35
© Markus Knauß, 2008
Entwurfsmuster
Inhalt

Java Database Connectivity (JDBC)

Objektorientierte Konzepte

Template Method Pattern

Entwurfsmuster

Datenbankzugriff mit Entwurfsmustern

Zusammenfassung

Literatur und Links
36
© Markus Knauß, 2008
Entwurfsmuster
Inhalt

Java Database Connectivity (JDBC)

Objektorientierte Konzepte

Template Method Pattern

Entwurfsmuster

Datenbankzugriff mit Entwurfsmustern

Zusammenfassung

Literatur und Links
37
© Markus Knauß, 2008
Literatur und Links
Das Buch der „Gang of Four“ mit den bekanntesten
Entwurfsmuster:
Entwurfsmuster

Gamma, E., R. Helm, R. Johnson und J. Vlissides (1995):
Design Patterns: Elements of Reusable Object-Oriented
Software. Addison-Wesley.
Wikipedia Artikel mit Links und Hintergrundinformationen für den
Einstieg ins Themengebiet (25.6.2008):

http://de.wikipedia.org/wiki/Entwurfsmuster
38
© Markus Knauß, 2008
Entwurfsmuster
Inhalt

Java Database Connectivity (JDBC)

Objektorientierte Konzepte

Template Method Pattern

Entwurfsmuster

Datenbankzugriff mit Entwurfsmustern

Zusammenfassung

Literatur und Links
39
Herunterladen