Upload
vulien
View
220
Download
4
Embed Size (px)
Citation preview
Software Architectures © Hans-Werner Sehring, STS. Alle Rechte vorbehalten.
Chapter 3 1
© Software Systems Department. All rights reserved.
Software Architectures2 SWS Lecture 1 SWS Lab Classes
Hans-Werner SehringMiguel GarciaArbeitsbereich Softwaresysteme (STS)TU [email protected]@tuhh.dehttp://www.sts.tu-harburg.de/teaching/ss-05/SWArch/entry.html
Summer term 2005
3.2Software Architectures: Design Patterns
3. Design Patterns
1. Motivation and Fundamental Concepts
2. Revisiting Object-Oriented Analysis, Design, and Implementation
3. Design Patterns
3.1 Design Pattern Rationale
3.2 Selected Design Patterns
4. Pipes & Filter Architectures
5. Event-based Architectures
6. Layered Architectures & Persistence Management
7. Framework Architectures
8. Component Architectures
Software Architectures © Hans-Werner Sehring, STS. Alle Rechte vorbehalten.
Chapter 3 2
3.3Software Architectures: Design Patterns
Learning Objectives of Chapter 3
Students should be able to …
understand how design patterns describe problem solutions in an abstract way,
recognize some of the most prominent design patterns,
apply those patterns patterns, and to combine them to achieve dense designs.
Required Reading:[GoF] Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides: Design Patterns, Elements of Reusable Object-Oriented Software, Addison-Wesley, 1995. The definite reference.
Additional Reading:John Vlissides: Pattern Hatching: Design Patterns Applied, Addison-Wesley, 1998.
Frank Buschmann, Regine Meunier, Hans Rohnert, Peter Somerlad, Michael Stal: Pattern-Oriented Software Architecture, John Wiley & Sons, 1996.
W. Brown, R. C. Malveau, H. W. McCormick, T. J. Mowbray: Anti Patterns: Refactoring Software, Architectures, and Projects in Crisis, Wiley & Sons, 1998. Quite funny for those with a little experience in larger software projects.
3.4Software Architectures: Design Patterns
3.1 Design Pattern Rationale
Design patterns:
Term originally coined by Christopher Alexander for the architecture of buildings and towns.
First efforts of sharing design knowledge for software development:
Donald Knuth: The Art of Computer Programming, vol. 1-3, 1973
“architecture handbook” (OOPSLA ´91)
James Coplien: Advanced C++ Programming Styles and Idioms, 1992
… and similar “best practices” books
Patterns taken to software engineering by the “Gang of Four” [GoF].Still the most influential work.
Christopher Alexander:“Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice.” (quoted in [GoF])
Software Architectures © Hans-Werner Sehring, STS. Alle Rechte vorbehalten.
Chapter 3 3
3.5Software Architectures: Design Patterns
Elements of Design Patterns
Design patterns consist of four essential parts:
Name:a name for a pattern adds to the design vocabulary
it allows design at a higher-level of abstraction
Problem:description of a problem and its context
sometimes enumeration of typical design flaws
Solution:elements that make up the design and their relationships
responsibilities and collaborations
Consequences:time and space trade-offs
eventually language and implementation concerns
3.6Software Architectures: Design Patterns
3.2 Selected Design Patterns
1. Motivation and Fundamental Concepts
2. Revisiting Object-Oriented Analysis, Design, and Implementation
3. Design Patterns
3.1 Design Pattern Rationale
3.2 Selected Design Patterns
4. Pipes & Filter Architectures
5. Event-based Architectures
6. Layered Architectures & Persistence Management
7. Framework Architectures
8. Component Architectures
9. Architecture-centric Software Construction
Software Architectures © Hans-Werner Sehring, STS. Alle Rechte vorbehalten.
Chapter 3 4
3.7Software Architectures: Design Patterns
Classification of Design Pattern
Following [GoF], we distinguish three categories of design patterns:
creational patterns,
structural patterns, and
behavioral patterns.
Creational Patterns Structural Patterns Behavioral PatternsPurpose
Factory Method Adapter (class) InterpreterTemplate Method
Abstract FactoryBuilder
PrototypeSingleton
Adapter (object)Bridge
CompositeDecorator
FacadeFlyweight
Proxy
Chain of ResponsibilityCommand
IteratorMediatorMementoObserver
StateStrategyVisitor
Class
ObjectScope
[GoF, p. 10]
handled in this chapterhandled in other chapters
3.8Software Architectures: Design Patterns
Singleton Pattern (1)
Category: creational.
Useful when
There must be only one instance of a class.Examples: resource manager objects, locks.java.awt.Toolkit.getDefaultToolkit ()
It has to be accessible from a well-known access point.Achieves less polluted namespaces, removes the need for a global variable.Examples: input and output streams, log manager.System.out (not exactly a Singleton)
Client code should remain stable even when the instance's class is refined.Example: localized versions of numbers, dates, …java.util.Calendar.getInstance ()(gets a calendar using the default time zone and locale)
Software Architectures © Hans-Werner Sehring, STS. Alle Rechte vorbehalten.
Chapter 3 5
3.9Software Architectures: Design Patterns
Singleton Pattern (2)
Structure:
Singleton classes …
define a method that delivers the one instance, and
are themselves responsible for creating that instance.
Singleton+ static getInstance () : Singleton... return uniqueInstance
- Singleton uniqueInstance...
3.10Software Architectures: Design Patterns
Singleton Pattern (3)
In Java (typically):
public class Singleton {
static private Singleton uniqueInstance ;
static public Singleton getInstance () {if (uniqueInstance == null)
uniqueInstance = new Singleton (…) ;return uniqeInstance ;
}// getInstance
private Singleton (…) {…
}// constructor
…
}// class Singleton
not callable from outsidenot callable from outside
Software Architectures © Hans-Werner Sehring, STS. Alle Rechte vorbehalten.
Chapter 3 6
3.11Software Architectures: Design Patterns
Singleton Pattern (4)
Sometimes there is a class managing singletons: registry of singletons.
Singletons are registered under keys (strings, numbers) and can be retrieved later.
Example: java.awt.color.ColorSpace.getInstance (int colorspace)
Especially in conjunction with the ability to deliver an instance of a subclass.
AbstractSingleton
ConcreteSingleton2ConcreteSingleton1 ConcreteSingleton2
+ getInstance (key : String) : AbstractSingleton
- registry : Map<String, AbstractSingleton>
{ (key1, new ConcreteSingleton1),(key2, new ConcreteSingleton2),(key3, new ConcreteSingleton3) }
return registry[key]
3.12Software Architectures: Design Patterns
Singleton Pattern (5)
In Java:public class Singleton {
static private Singleton uniqueInstance ;static private Hashtable instances ;static {
instances = new Hashtable (3) ;instances.put ("key1", new Singleton (x)) ;instances.put ("key2", new Singleton (y)) ;instances.put ("key3", new SpecialSingleton ()) ;
}// static constructorstatic private Singleton getInstance () {
if (uniqueInstance == null) {String key = System.getProperty ("SOME_SINGLETON") ;uniqueInstance = (Singleton)instances.get (key) ;
}return uniqueInstance ;
}// getInstance
private Singleton (…) {…
}// constructor}// class Singleton
initializationinitialization
variable set in environmentto either key1, key2, or key3variable set in environmentto either key1, key2, or key3
Software Architectures © Hans-Werner Sehring, STS. Alle Rechte vorbehalten.
Chapter 3 7
3.13Software Architectures: Design Patterns
Abstract Factory Pattern (1)
Category: creational.
To maximize code reuse it is desirable to abstract from concrete classes and instead only use the names of interfaces or abstract classes.
One point where concrete classes are needed is for object construction.
Example:
Create elements of a graphical user interface (GUI).
There are two variants of the GUI.
One is programmed in the Java AWT:Window win = new java.awt.Frame () ;Component txt = new java.awt.TextField () ;…
A variant of the GUI is programmed using Java Swing:Window win = new javax.swing.JFrame () ;Component txt = new javax.swing.JTextField () ;…
3.14Software Architectures: Design Patterns
Abstract Factory Pattern (2)
To abstract from concrete classes at the point of instantiation, factories are used:UIFactory uiFactory = new AWTUIFactory () ;
or = new SwingUIFactory ()Window win = uiFactory.createWindow () ;Component txt = uiFactory.createTextField () ;
Advantages:
An application can dynamically choose one implementation out of a family of possible implementations.
Client code does not directly use implementation classes. Thus, these can be changed.
Concrete classes can be added, e.g., new UI component types.
Software Architectures © Hans-Werner Sehring, STS. Alle Rechte vorbehalten.
Chapter 3 8
3.15Software Architectures: Design Patterns
Abstract Factory Pattern (3)
To choose an implementation, a hierarchy of factory classes is established in correspondence to the application class hierarchy.
UIFactory
AWTUIFactory SwingUIFactory
+ createWindow () : java.awt.Window+ createTextField () : java.awt.Component
+ createWindow () : java.awt.Window+ createTextField () : java.awt.Component
+ createWindow () : java.awt.Window+ createTextField () : java.awt.Component
Window(from java.awt)
Frame(from java.awt)
JFrame(from javax.swing)
<<creates>> <<creates>>
Component(from java.awt)
TextField(from java.awt)
JTextField(from javax.swing)
...<<creates>> <<creates>>
3.16Software Architectures: Design Patterns
Abstract Factory Pattern (4)
General structure:AbstractFactory
ConcreteFactory1 ConcreteFactory2
+ createA (…) : AbstractA+ createB (…) : AbstractB
+ createA (…) : AbstractA+ createB (…) : AbstractB
+ createA (…) : AbstractA+ createB (…) : AbstractB
AbstractA
ConcreteA1 ConcreteA2
<<creates>> <<creates>>AbstractB
ConcreteB1 ConcreteB2
<<creates>><<creates>>
Software Architectures © Hans-Werner Sehring, STS. Alle Rechte vorbehalten.
Chapter 3 9
3.17Software Architectures: Design Patterns
Factory Method Pattern (1)
Category: creational.
Often creator objects are used to instantiate classes. One example just seen: factories.
If a creator's class does not know the classes to instantiate, the creation can be deferred to subclasses.
Example: (graphical) UML editor.
The UML editor has a polymorphic “new node” menu to add elements to a diagram.
The type of node added depends on the currently selected diagram.
Naïve way:
UMLDiagramNode newNode ;if (currentDiagram instanceof UMLClassDiagramm)
newNode = new UMLClassNode (…) ;else if (currentDiagram instanceof UMLStateChart)
newNode = new UMLStateNode (…) ;else
…
3.18Software Architectures: Design Patterns
Factory Method Pattern (2)
Better solution: diagrams are creators of nodes:
UMLDiagramNode newNode = currentDiagram.newNode (…) ;
UMLDiagram
UMLClassDiagram UMLStateChart
+ newNode (...) : UMLDiagramNode
+ newNode (...) : UMLDiagramNode + newNode (...) : UMLDiagramNode
UMLDiagramNode
UMLClassNode UMLStateNode
<<creates>> <<creates>>
Software Architectures © Hans-Werner Sehring, STS. Alle Rechte vorbehalten.
Chapter 3 10
3.19Software Architectures: Design Patterns
Factory Method Pattern (3)
General structure:
Advantages:
a class doesn't have to know the concrete classes for which to create objects(in the example: UMLDiagram).
Because of this fact concrete classes can be added without changing the creator class (AbstractCreator).
Knowledge on object construction is localized in places where it belongs(in the example: class diagrams know about classes, state charts about states, …).
AbstractCreator
ConcreteCreator
+ factoryMethod (...) : AbstractProduct
+ factoryMethod (...) : AbstractProduct
AbstractProduct
ConcreteProduct<<creates>>
return new ConcreteProduct (...)
3.20Software Architectures: Design Patterns
Prototype Pattern (1)
Category: creational.
Sometimes objects have to be created and initialized without their class being known.
Example:A graphical editor framework can is able to handle shapes of different kinds – lines, rectangles, ellipses, … (Frameworks are discussed later in this lecture.)
The set of kinds of shapes is dynamically extendable by client code.
Therefore, the graphical editor framework cannot contain code to instantiate shapes itself.
Solution:Client code creates a prototype of a shape it wants the framework to use.The framework can create new shapes by cloning the prototype.
The clone is initialized with the same state as the original.
Advantages:Instances can be created without knowing their class.
New instances are initialized without knowing their interface.
This way, object creation is decoupled from the use of concrete classes.
Software Architectures © Hans-Werner Sehring, STS. Alle Rechte vorbehalten.
Chapter 3 11
3.21Software Architectures: Design Patterns
Prototype Pattern (2)
Each tool is initialized with an instance (a prototype) of the shape it is meant to create. When creating a new shape, the tool clones the prototype.
Prototype
prototype.clone()
Prototype
prototype.clone()
3.22Software Architectures: Design Patterns
Prototype Pattern (3)
Example:Framework:class EditorFramework {
private Hashtable shapesFromClient ;public EditorFramework () {
shapesFromClient = new Hashtable () ;}// constructorpublic void register (String shapeName, Shape s) {
shapesFromClient.put (shapeName, s) ;}// registerpublic void addShape (String shapeName) {
Object prototype = shapesFromClient.get (shapeName) ; Shape newShape = (Shape)prototype.clone () ;… (add newShape to drawing area etc.)
}// addShape}// class EditorFrameworkClient code:…EditorFramework editorFramework = new EditorFramework () ;…editorFramework.register ("my shape",
new SpecificShape (1, "xyz", 5.7));…editorFramework.addShape ("my shape") ;
Software Architectures © Hans-Werner Sehring, STS. Alle Rechte vorbehalten.
Chapter 3 12
3.23Software Architectures: Design Patterns
Bridge Pattern (1)
Category: structural.
When there are variants of an implementation, usually subclassing is used.This makes the addition of further classes difficult, esp. with single inheritance.
Example: persistent person objects (Person) are either stored in a relational database (JDBCPerson) or in an XML file (XMLPerson).
If you now want to refine Person to, say, Professor, you end up with:
Thus, the hierarchy is doubled, reuse is limited.
Person
JDBCPerson XMLPerson
Person
JDBCPerson XMLPerson
JDBCProfessor XMLProfessor
Professor
3.24Software Architectures: Design Patterns
Bridge Pattern (2)
A better solution is to separate the conceptual and the implementation hierarchy, and to connect them by a bridge.
PersonProfImpl
JDBCPersProfImpl XMLPersProfImpl
Person
Professor
impl
getName () : String
getName () : String
return "Prof. " +super.getName ()
impl.getName ()
getName () : String getName () : String
read name fromdatabase
read name fromXML file
getName () : String
Software Architectures © Hans-Werner Sehring, STS. Alle Rechte vorbehalten.
Chapter 3 13
3.25Software Architectures: Design Patterns
Bridge Pattern (3)
General structure:
Using the Bridge pattern subclassing forconceptual and technical reasons can be separated.Especially, if subclasses solely rely on the interface of the superclass.
Advantages:Implementation can be chosen dynamically.
Both conceptual abstractions and implementations can be extended by subclasses.
Changes to an implementation have no impact on client code.
The implementation classes are completely hidden from client code.
Implementation objects can be shared.
ImplementationBase
Implementation1 Implementation2
Abstraction
Refinement
impl
operation ()
impl.operation ()
operation () operation ()
operation ()
3.26Software Architectures: Design Patterns
Adapter Pattern (1)
Category: structural.
Example: Visualization of XML documents.
The Document Object Model (DOM) of an XML document is a tree.For trees exists a view in the standard Java class library: javax.swing.JTree.
But:The model of a JTree is a TreeModel (javax.swing.tree.TreeModel).
How to use a DOM (org.w3c.dom.Document)?
Solution: make a DOM look like a TreeModel.
Element
Element Element Parameter
Element Element
Software Architectures © Hans-Werner Sehring, STS. Alle Rechte vorbehalten.
Chapter 3 14
3.27Software Architectures: Design Patterns
Adapter Pattern (2)
Create a class DocumentTreeModel which
implements TreeModel and
delegates calls to a Document.TreeModel
<<interface>>(from javax.swing.tree)
+ addTreeModelListener (l : TreeModelListener) : void+ getChild (parent : Object, index : int) : Object+ getChildCount (parent : Object ) : int+ getIndexOfChild (parent : Object, child : Object ) : int+ getRoot () : Object+ isLeaf (node : Object ) : boolean+ removeTreeModelListener (l : TreeModelListener) : void+ valueForPathChanged (path:TreePath, newValue:Object ) : void
DocumentTreeModel...
Document<<interface>>
(from org.w3c.dom)getDocumentElement () : Element...
JTree(from javax.swing)
3.28Software Architectures: Design Patterns
Adapter Pattern (3)
In Java:public class DocumentTreeModel implements TreeModel {
private Document doc ; // the DOM to use
public DocumentTreeModel (Document document) {this.doc = document ;
}// constructor
public Object getRoot () {return doc.getDocumentElement () ;
}// getRoot
public boolean isLeaf (Object node) {if (node instanceof Node)
return ((Node)node).getChildNodes().getLength() == 0;else
throw new RuntimeException ("Something is wrong?") ;}// isLeaf
…
}// class DocumentTreeModel
Software Architectures © Hans-Werner Sehring, STS. Alle Rechte vorbehalten.
Chapter 3 15
3.29Software Architectures: Design Patterns
Adapter Pattern (4)
As in many cases, one can choose between delegation and subclassing.
Adapter class:
TreeModel<<interface>>
(from javax.swing.tree)+ getRoot () : Object…
DocumentTreeModel+ getRoot () : Object...
Document<<interface>>
(from org.w3c.dom)+ getDocumentElement () : Element...
JTree(from javax.swing)
return getDocumentElement ()
3.30Software Architectures: Design Patterns
Adapter Pattern (5)
Applications of the Adapter pattern:
Reuse a class with an interface that is not as needed(e.g., DOM in a JTree).
Create a class that interoperates with different other classes that do not share a common interface(e.g., tree model for DOM, file system, …).
Adapt multiple classes at once by adapting their parent interface, e.g., if number of subclasses would prohibitively high(e.g., adapt class Node from DOM instead of all Node subclasses separately).
Software Architectures © Hans-Werner Sehring, STS. Alle Rechte vorbehalten.
Chapter 3 16
3.31Software Architectures: Design Patterns
Adapter Pattern (6)
The general structure of Adapters is:
Class adapter:
Can adapt only one class.
Can override some of adaptee's behavior(since it is a subclass).
Consists of only one object.
Object adapter:
Can adapt more than one adaptee.
Adaptee can change dynamically.
Harder to override adaptee's behavior. Target
Adapter
Adaptee
Client
Target
Adapter
Adaptee
Client
if “two-way”adapter
if “two-way”adapter
3.32Software Architectures: Design Patterns
Decorator Pattern (1)
Category: structural.
Decorators dynamically attach new responsibilities to an object.
For extending functionality, decoration is a flexible alternative to subclassing.
Example: a graphics program with a drawing pane holding shape objects.
Various kinds of shapes can be added to the drawing pane.
For each kind of shape there one is a class (Square, Circle, …).
A shape object is drawn with handles when selected.
selection
Shape
Square Circle...
Software Architectures © Hans-Werner Sehring, STS. Alle Rechte vorbehalten.
Chapter 3 17
3.33Software Architectures: Design Patterns
Decorator Pattern (2)
Naïve solution:
Create subclasses SelectedSquare, SelectedCircle, … for each class Square, Circle, …
When selected, exchange a shape instance with an instance of the corresponding Selected… class.
Shape
Square Circle...
SelectedShape
draw () : void draw () : voiddrawHandles () : void
draw () : void
SelectedSquare
draw () : void
SelectedCircle
draw () : void
multiple inheritance!no “super”!super.draw () ;drawHandles () ;
3.34Software Architectures: Design Patterns
Decorator Pattern (3)
Instead of having a subclass for each class there is only one HandleDecorator for all kinds of shapes.
Making the HandleDecorator itself a Shape, it can be put on the drawing pane.
The HandleDecorator, upon redraw, lets the selected shape draw itself, and then adds the handles.(Note: This way handles can decorate handles. To avoid this one more class is needed.)
Shape
Square Circle...
HandleDecorator
draw () : void draw () : voiddraw () : voiddrawHandles () : voidselectedShape.draw () ;
drawHandles () ;
selectedShape
draw () : void
Software Architectures © Hans-Werner Sehring, STS. Alle Rechte vorbehalten.
Chapter 3 18
3.35Software Architectures: Design Patterns
Decorator Pattern (4)
General structure:
Component
Decorator
operation () : Object
operation () : Object
…comp.operation () ;…
ConcreteComponentoperation () : Object
ConcreteDecorator2operation () : ObjectaddedBehavior () : void
ConcreteDecorator1operation () : Object
comp
super.operation () ;addedBehavior () ;
3.36Software Architectures: Design Patterns
Decorator Pattern (5)
Advantages:
Add behavior to an object dynamically, without affecting other objects.
Change responsibilities.
Offers an alternative to subclassing when the latter is not practical because of:
explosion of the number of subclasses,
multiple inheritance with languages which do not have this feature,
changing behavior, or because
class definitions are hidden or otherwise not available for subclassing (final, …).
Software Architectures © Hans-Werner Sehring, STS. Alle Rechte vorbehalten.
Chapter 3 19
3.37Software Architectures: Design Patterns
Façade Pattern (1)
Category: structural.
Often several objects are used in conjunction, e.g., if
functionality is spread over several objects of a subsystem, or
one operation needs to be carried out by several objects concurrently.
Example: While processing, an application GUI marks some menu items inactive.
All menu items deactivated manually:void deactivate (MenuElement m) {
m.setActive (false) ;for (MenuElement me : m.getSubElements ())deactivate (me) ;
}// deactivate
Some menu items deactivated manually:menuItem1.setActive (false) ;…menuItemn.setActive (false) ;
Java 5Java 5
3.38Software Architectures: Design Patterns
Façade Pattern (2)
With naïve solution:
Behavior is spread over application.
Client code depends on implementation (here: Swing classes).
With a Façade (containing the code from the previous slide):public class MenuItemActivationFacade {
private JMenuItem menuItem1, …, menuItemn ;public MenuItemActivationFacade (MenuElement m1, …, MenuElement mn) {
this.menuItem1 = m1 ;…this.menuItemn = mn ;
}// constructorpublic void setActive (boolean active) {
menuItem1.setActive (active) ;…menuItemn.setActive (active) ;
}// setActive}// class MenuItemActivationFacade
Client code then:MenuItemActivationFacade miaf = new MenuItemActivationFacade (m1,…,mn) ;miaf.setActive (false) ;
Software Architectures © Hans-Werner Sehring, STS. Alle Rechte vorbehalten.
Chapter 3 20
3.39Software Architectures: Design Patterns
Façade Pattern (3)
General structure:
Advantages:
Provides a simple interface to a complex subsystem.
Decouples clients from implementation classes.
Defines a layering of subsystems with Façades as entry points.
Facade
…
…
…
…
…
3.40Software Architectures: Design Patterns
Observer Pattern (1)
Category: behavioral.
Good design breaks down a system into a set of cooperating classes.
For cooperation, objects have to know each other.
For reusability you want to decouple classes as much as possible.
Example: user interfaces.
There are distinct visualizations of the same set of data (compare MVC).
The views on the data have to be consistent.
UI components should be reusable separately of each other.
keep values consistent
Software Architectures © Hans-Werner Sehring, STS. Alle Rechte vorbehalten.
Chapter 3 21
3.41Software Architectures: Design Patterns
Observer Pattern (2)
Naïve object-oriented solution:
This way, the classes for textfields and sliders depend on each other.
For other UI setups, different classes would be needed.
TextFieldForUseWithSlider SliderForUseWithTextField
+ setText (t : String) : void + setValue (v : Object) : void
slidertextField
set the textslider.setValue (…) ;
set the valuetextField.setText (…) ;
3.42Software Architectures: Design Patterns
Observer Pattern (3)
With Observer:
ObservableTextField ObservableSlider
+ setText (t : String) : void+ register (o : TextFieldObserver) : void
+ setValue (v : Object) : void+ register (o : SliderObserver) : void
SyncingTextFieldObserver SyncingSliderObserver
+ update () : void + update () : void
o o
set the texto.update () ;
set the valueo.update () ;
slidertextField
TextFieldObserver
textField.getText () ;slider.setValue (…) ;
slider.getValue () ;textField.setText (…) ;
SliderObserver
Software Architectures © Hans-Werner Sehring, STS. Alle Rechte vorbehalten.
Chapter 3 22
3.43Software Architectures: Design Patterns
Observer Pattern (4)
In Java (both Observer classes implemented in one):class SliderTextFieldListener
implements ActionListener, ChangeListener{
private JSlider g ;private JTextField t ;public SliderTextFieldListener (JSlider g, JTextField t) {
this.g = g ;this.t = t ;g.addChangeListener (this) ;t.addActionListener (this) ;
}// constructorpublic void stateChanged (ChangeEvent e) {
t.setText (Integer.toString (g.getValue ())) ;}// stateChangedpublic void actionPerformed (ActionEvent event) {
int val ;try { val = Integer.parseInt (t.getText ()) ; }catch (NumberFormatException exc) { val = 0 ; }g.setValue (val) ;
}// actionPerformed}// class SliderTextFieldListener
3.44Software Architectures: Design Patterns
Observer Pattern (5)
General structure:
For further decoupling, e.g., event objects in Java.
AbstractSubject
ConcreteSubject
AbstractObserver
ConcreteObserver
+ getState () : Object + update () : void
+ register (o : AbstractObserver) : void+ deregister (o : AbstractObserver) : voidnotify () : void
+ update () : void
for each o∈observerso.update () ;
observers
... subject.getState () ...
subject
Software Architectures © Hans-Werner Sehring, STS. Alle Rechte vorbehalten.
Chapter 3 23
3.45Software Architectures: Design Patterns
Observer Pattern (6)
Interactions:
: ConcreteSubject c1 : ConcreteObserver
setState (v) notify ()
getState ()
update ()
c2 : ConcreteObserver
getState ()
update ()
register (c1)register (c2)
3.46Software Architectures: Design Patterns
Observer Pattern (7)
Advantages:
Encapsulates behavioral aspects.
Changes of behavior can be done regardless of the subjects.
Establishes lose coupling of objects (no direct method calls).
Disadvantage:
Subjects have to expose inner state to observer (ex.: getState() is public).
State of the subject while notifying observer may differ from the state when observer analyzes it.
Better with event objects: pass event objects which encapsulate the state needed for usual applications at the time of notification.
Software Architectures © Hans-Werner Sehring, STS. Alle Rechte vorbehalten.
Chapter 3 24
3.47Software Architectures: Design Patterns
Observer Pattern (8)
In Java: Event-Listener-Model (Java 2).
Provides (part of) the information in event objects passed to the udpate() method.
Example:
Component
MouseListener
+ addMouseListener (l : MouseListener) : void+ removeMouseListener (l : MouseListener) : void
+ void mouseClicked (e : MouseEvent ) : void+ void mouseEntered (e : MouseEvent) :void+ void mouseExited (e : MouseEvent ) : void+ void mousePressed (e : MouseEvent ) : void+ void mouseReleased (e : MouseEvent ) : void
MouseEvent
+ int getButton () : void+ int getClickCount () : void+ getPoint () : Point+ getX () : int+ getY () : int+ paramString () : String…
3.48Software Architectures: Design Patterns
Visitor Pattern (1)
Category: behavioral.
Example: let the following classes be given.
The task is to handle collections of persons, e.g., printing out the names of persons.
Person{abstract}
Professor Assistant Student
ResearchAssistant TeachingAssistant
getFirstName ()getLastName ()
getId ()
Software Architectures © Hans-Werner Sehring, STS. Alle Rechte vorbehalten.
Chapter 3 25
3.49Software Architectures: Design Patterns
Visitor Pattern (2)
Imperative approach, naïve:Set<Person> personSet = … a set of PersonsIterator<Person> i = personSet.iterator () ;while (i.hasNext ()) {
Person p = i.next () ;String name = p.getFirstName () + " " + p.getLastName () ;if (p instanceof Professor)
System.out.println("Prof. " + name) ;else if (p instanceof Assistant)
System.out.println (name) ;else if (p instanceof Student) {
Student s = (Student)p ;System.out.println (name + "," + s.getId ()) ;
}else
; // what to do???}// while
Problems:hard-coded subtypes ⇒ hard to add new Person types
hard-coded behavior ⇒ what to do if there are different output formats?
3.50Software Architectures: Design Patterns
Visitor Pattern (3)
More object-oriented approach: use the toString() method of java.lang.Object.
Set personSet = … a set of PersonsIterator i = personSet.iterator () ;while (i.hasNext ())
System.out.println (i.next ().toString ()) ;
Problem: hard-coded behavior ⇒ what if there are different output formats?
Person
Professor Assistant Student
ResearchAssistant TeachingAssistant
+ toString () : String + toString () : String
+ toString () : String + toString () : String
Software Architectures © Hans-Werner Sehring, STS. Alle Rechte vorbehalten.
Chapter 3 26
3.51Software Architectures: Design Patterns
Visitor Pattern (4)
Object-oriented approach:use methods defined in Person+ dynamic dispatch.
Set<Person> personSet = … a set of PersonsIterator<Person> i = personSet.iterator () ;while (i.hasNext ())
System.out.println (i.next ().asString1 ()) ;
Problem: fixed set of behaviors ⇒ adding new behaviors requires to
change class Person and thus to
recompile all classes
Person
Professor Assistant Student
ResearchAssistant TeachingAssistant
+ asString1 () : String+ asString2 () : String
+ asString1 () : String+ asString2 () : String
+ asString1 () : String+ asString2 () : String
+ asString1 () : String+ asString2 () : String
Connection(from java.sql)
…Connection(from com.oracle…)
…Connection(from com.ibm…)
…Connection(from org.gjt…)
+ asString1 () : String+ asString2 () : String
it’s not always possible to change all classes
3.52Software Architectures: Design Patterns
Visitor Pattern (5)
Solution: encapsulate behaviors in classes of their own ⇒ Visitors.
Double dispatch: behavior depends on type of object and on Visitor.Behavior given by subclass of PersonVisitor⇒ extendable by introducing new ones.
Person
Professor
Assistant
Student
+ accept (v : PersonVisitor) : Object
PersonVisitor+ visit (p : Professor) : Object+ visit (a : Assistant) : Object+ visit (s : Student) : Object
PrintNamePersonVisitor+ visit (p : Professor) : Object+ visit (a : Assistant) : Object+ visit (s : Student) : Object
PrintAddressPersonVisitor+ visit (p : Professor) : Object+ visit (a : Assistant) : Object+ visit (s : Student) : Object
+ accept (v : PersonVisitor) : Object
+ accept (v : PersonVisitor) : Object
+ accept (v : PersonVisitor) : Object
return v.visit (this) ;
Software Architectures © Hans-Werner Sehring, STS. Alle Rechte vorbehalten.
Chapter 3 27
3.53Software Architectures: Design Patterns
Visitor Pattern (6)
Visitor definition:
class PrintNamePersonVisitor implements PersonVisitor {private String printName (Person p) {
return p.getFirstName () + " " + p.getLastName () ;}// printNamepublic Object visit (Professor p) {System.out.println ("Prof. " + printName (p)) ;return null ;
}// visitpublic Object visit (Assistant a) {System.out.println (printName (a)) ;return null ;
}// visitpublic Object visit (Student s) {System.out.println (printName (s) + ", " + s.getId ()) ;return null ;
}// visit}// class PrintNamePersonVisitor
3.54Software Architectures: Design Patterns
Visitor Pattern (7)
Usage of a visitor (client code):
Print names:Set<Person> personSet = … a set of PersonsIterator<Person> i = personSet.iterator () ;PersonVisitor pnpv = new PrintNamePersonVisitor () ;while (i.hasNext ())
i.next ().accept (pnpv) ;
Print addresses:Set<Person> personSet = … a set of PersonsIterator<Person> i = personSet.iterator () ;PersonVisitor papv = new PrintAddressPersonVisitor () ;while (i.hasNext ())
i.next ().accept (papv) ;
Software Architectures © Hans-Werner Sehring, STS. Alle Rechte vorbehalten.
Chapter 3 28
3.55Software Architectures: Design Patterns
Visitor Pattern (8)
General structure:
Element
ConcreteElement1
ConcreteElement2
ConcreteElement3
+ accept (v : AbstractVisitor) : Object
AbstractVisitor+ visitE1 (e : ConcreteElement1) : Object+ visitE2 (e : ConcreteElement2) : Object+ visitE3 (e : ConcreteElement3) : Object
ConcreteVisitor2+ visitE1 (e : ConcreteElement1) : Object+ visitE2 (e : ConcreteElement2) : Object+ visitE3 (e : ConcreteElement3) : Object
ConcreteVisitor1+ visitE1 (e : ConcreteElement1) : Object+ visitE2 (e : ConcreteElement2) : Object+ visitE3 (e : ConcreteElement3) : Object
+ accept (v : AbstractVisitor) : Object
+ accept (v : AbstractVisitor) : Object
+ accept (v : AbstractVisitor) : Object
return v.visitE3 (this) ;
return v.visitE2 (this) ;
return v.visitE1 (this) ;
3.56Software Architectures: Design Patterns
Visitor Pattern (9)
Interactions:
e : ConcreteElement1 v : ConcreteVisitor1
accept (v)visitE1 (e)
someOperation (...) “double dispatch”“double dispatch”
Software Architectures © Hans-Werner Sehring, STS. Alle Rechte vorbehalten.
Chapter 3 29
3.57Software Architectures: Design Patterns
Visitor Pattern (10)
Advantages:
Visitors make it easy to add new operations.
This is possible even for existing code not available in source format.
Just the accept() method has to be included.
Visitors encapsulate related operations and separate unrelated ones.
They avoid interfaces becoming to “broad”.
They allow different implementations of a functionality.
Visitors can add a state for visiting processes.
Therefore, no parameter or similar has to be added to the elements.
This allows algorithms to walk structures, compute cumulative values, etc.
3.58Software Architectures: Design Patterns
Visitor Pattern (11)
Disadvantages:
With Visitors the addition of new classes becomes harder. When adding a new subclass it is required to …
add a visit method in the Visitor interface and
adjust all Visitor implementations accordingly.
Still, with visitors …- you get compile time errors for missing operations
(in contrast to cascades of conditional statements), and
- you can supply a standard method for all Visitors(if base visitor type is given by an abstract class).
A visitor breaks up encapsulation. Often, methods have to be exposed (made public) to be accessible by a visitor, which should not be called otherwise.
Software Architectures © Hans-Werner Sehring, STS. Alle Rechte vorbehalten.
Chapter 3 30
3.59Software Architectures: Design Patterns
Visitor Pattern (12)
With languages like Java up to version 1.4 (without class parameters, type parameters, and overloading) there is a problem determining the type of objects returned by accept() / visit().
String name = (String)person.accept (new PersonVisitor () {public Object visit (Professor p) ) {
return "Prof. " + printName (p) ;}// visitpublic Object visit (Assistant a) {
return printName (a) ;}// visitpublic Object visit (Student s) {
return printName (s) + ", " + s.getId () ;}// visit
}) ;
type cast needed⇒ another visitor??type cast needed⇒ another visitor??
3.60Software Architectures: Design Patterns
Visitor Pattern (13)
With class or type parameters, e.g. in Java 5, this can be avoided:
Visitor definition:abstract class interface PersonVisitor<T> {
private String printName (Person p) {return p.getFirstName () + " " + p.getLastName () ;
}// printNameabstract public T visit (Professor p) ;abstract public T visit (Assistant a) ;abstract public T visit (Student s) ;
}// class PersonVisitor<T>
Client code:String name = person.accept (new PersonVisitor<String> () {
public String visit (Professor p) ) {return "Prof. " + printName (p) ;
}// visitpublic String visit (Assistant a) {
return printName (a) ;}// visitpublic String visit (Student s) {
return printName (s) + ", " + s.getId () ;}// visit
}) ;
PersonVisitor+ visit (p : Professor) : T+ visit (a : Assistant) : T+ visit (s : Student) : T
T
Software Architectures © Hans-Werner Sehring, STS. Alle Rechte vorbehalten.
Chapter 3 31
3.61Software Architectures: Design Patterns
Design Pattern Relationships (1)
Memento
Adapter
Proxy
BridgeIterator
Builder
Composite
Flyweight
Decorator
Strategy
Interpreter
Visitor
Command
Chain of Responsibility
Mediator
State
Template Method
Observer
PrototypeFactory Method
FacadeSingletonAbstract Factory
saving state of iteration
avoiding hysteresis
creating composites
enumerating children
adding responsibilities to objects
composed using
changing skin versus
guts sharing strategies sharing
states
sharing terminal symbols
adding operations
defining the chain
adding operationsdefining
grammar
complex dependency management
often uses
single instance
single instance
configure factory dynamically
defining algorithm's steps
implemented using
[GoF]
3.62Software Architectures: Design Patterns
Design Pattern Relationships (2)
Abstract Factory using Prototypes:class UIFactory {
private Object winProto, txtProto ;
public UIFactory (Window winProto, Component txtProto) {this.winProto = winProto ;this.txtProto = txtProto ;
}// constructor
public Window createWindow () {return (Window)winProto.clone () ;
}// createWindow
public Component createTextField () {return (Component)txtProto.clone () ;
}// createTextField
}// class UIFactory
Software Architectures © Hans-Werner Sehring, STS. Alle Rechte vorbehalten.
Chapter 3 32
3.63Software Architectures: Design Patterns
Design Pattern Relationships (3)
Combinations with Singleton:
Abstract Factory as Singleton:Window win = UIFactory.getInstance ().createWindow () ;Component txt = UIFactory.getInstance ().createTextField () ;
Façade as Singleton:MenuItemActivationFacade.getInstance ().setActive (false) ;
3.64Software Architectures: Design Patterns
Design Pattern Relationships (4)
Pattern combinations not discussed in [GoF]:Bridge to Flyweights:PersonImpl personImpl = new JDBCPersonImpl (4711) ;Person peter = new Person (personImpl) ;Professor peterTheProfessor = new Professor (personImpl) ;…
Decoration to observe objects not designed for Observer patternclass ObservableC extends C {
private Set observers ;…public void setX (T x) {
super.setX (x) ;notify () ;
}// setXprivate void notify () {
Iterator i = observers.iterator () ;while (i.hasNext ())
((Observer)i.next ()).update () ;}// notify
…
}// class ObservableC
Software Architectures © Hans-Werner Sehring, STS. Alle Rechte vorbehalten.
Chapter 3 33
3.65Software Architectures: Design Patterns
Applicability of Patterns
Design Patterns are usually thought as a programming guideline.
The basic principles can also be found on more abstract levels of design:
The Mediator Architecture [Wiederhold] consists of
Mediators (see Mediator pattern) and
Wrappers (see Adapter pattern).
Wrapping of legacy applications (e.g., by stubs defined in CORBA IDL) corresponds to the Adapter pattern.
Proxies are also found as components
Network proxies
Proxy web servers
…