Software Architecture - Lecture 10
1
Chair of Software Engineering
Last update:3 May 2006
Software Architecture
Lecture 9:About design patterns
Software Architecture - Lecture 10
2
Chair of Software Engineering
Reading assignment
Chapter 20 & 21 of OOSC (Multi-panel & Undo-redo)
Componentization of the visitor pattern:http://se.ethz.ch/~meyer/publications/computer/visitor.pdf
Software Architecture - Lecture 10
3
Chair of Software Engineering
Topics
PatternsAbstract Factory PatternVisitorObserverChain of responsibilityCommand
From patterns to components
Software Architecture - Lecture 10
4
Chair of Software Engineering
Patterns in software development
Document that describes a general solution to a design problem that recurs in many applications.
Developers adapt the pattern to their specific application.
Software Architecture - Lecture 10
5
Chair of Software Engineering
Some design patterns
BehavioralChain of ResponsibilityCommandInterpreterIteratorMediatorMementoObserverStateStrategyTemplate MethodVisitor
Erich Gamma, Ralph Johnson, Richard Helms, John Vlissides: Design Patterns, Addison-Wesley, 1994
CreationalAbstract FactoryBuilderFactory MethodPrototypeSingleton
StructuralAdapterBridgeCompositeDecoratorFaçadeFlyweightProxy
Software Architecture - Lecture 10
6
Chair of Software Engineering
Benefits of design patterns
Capture the knowledge of experienced developersTeachable to newcomersYield a better structure of the software Facilitate discussions between programmers and
managers
Software Architecture - Lecture 10
7
Chair of Software Engineering
Abstract factory pattern
Software Architecture - Lecture 10
8
Chair of Software Engineering
Creational patterns
Hide the creation process of objectsHide the concrete type of these objectsAllow dynamic and static configuration of the
software system
Software Architecture - Lecture 10
9
Chair of Software Engineering
Some design patterns
CreationalAbstract FactoryBuilderFactory MethodPrototypeSingleton
StructuralAdapterBridgeCompositeDecoratorFaçadeFlyweightProxy
BehavioralChain of ResponsibilityCommandInterpreterIteratorMediatorMementoObserverStateStrategyTemplate MethodVisitor
Software Architecture - Lecture 10
10
Chair of Software Engineering
Abstract factory - Intent
“Provide an interface for creating families of related or dependent objects without specifying their concrete classes.” [Gamma et al.]
Software Architecture - Lecture 10
11
Chair of Software Engineering
Abstract Factory: example need
Widget toolkitDifferent look and feel, e.g. for Unix & WindowsFamily of widgets: Scroll bars, buttons, dialogs…Want to allow changing look & feel
Most parts of the system need not know what look & feel is usedCreation of widget objects should not be distributed
Software Architecture - Lecture 10
12
Chair of Software Engineering
Architecture for widget example
*FACTORY
*BUTTON
*CHECKBOX
new_button*
new_checkbox*
new_button+
+WIN_FACTORY
+WIN_BUTTON
+WIN_CHECKBOX
new_checkbox+
+UNX_BUTTON
+UNX_FACTORY
+UNX_CHECKBOX
new_button+
new_checkbox+
Software Architecture - Lecture 10
13
Chair of Software Engineering
Architecture of a general example
*FACTORY
+FACTORY_1
+FACTORY_2
*PRODUCT_A
+PRODUCT_A1
+PRODUCT_A2
+PRODUCT_B1
+PRODUCT_B2
*PRODUCT_B
new_product_a*
new_product_b*
new_product_a+
new_product_b+ new_product_b+
new_product_a+
Software Architecture - Lecture 10
14
Chair of Software Engineering
Sketch of class FACTORY
deferred classFACTORY
feature -- Basic operations
new_button: BUTTON is-- New button
deferredend
new_checkbox: CHECKBOX is-- New checkbox
deferredend
…end
Software Architecture - Lecture 10
15
Chair of Software Engineering
Sketch of class WIN_FACTORY
classWIN_FACTORY
inheritFACTORY
feature -- Basic operations
new_button: BUTTON is-- New windows button
docreate {WIN_BUTTON} Result
end
new_checkbox: CHECKBOX is-- New windows checkbox
docreate {WIN_CHECKBOX} Result
end…end
Software Architecture - Lecture 10
16
Chair of Software Engineering
Ancestor factory class
classSHARED_FACTORY
…feature -- Basic operations
factory: FACTORY is-- Factory used for widget instantiation
onceif is_windows_os then
create {WIN_FACTORY} Resultelse
create {UNX_FACTORY} Resultend
end
…end
Software Architecture - Lecture 10
17
Chair of Software Engineering
Usage of FACTORY
classWIDGET_APPLICATION
inheritSHARED_FACTORY
…feature -- Basic operations
some_feature is-- Generate a new button and use it.
localmy_button: BUTTON
do…my_button := factory.new_button…
end…end
Software Architecture - Lecture 10
18
Chair of Software Engineering
Reasons for using an abstract factory
Most parts of a system should be independent of how its objects are created, represented and collaborating
The system needs to be configured with one of multiple families
A family of objects is to be designed and only used together
You want to support a whole palette of products, but only want to show the public interface
Software Architecture - Lecture 10
19
Chair of Software Engineering
“Testat”
To take the exam, you must be part of a group that has submitted a project that
RunsHas a requirements document, or a user’s manual, or bothHas a design document
Software Architecture - Lecture 10
20
Chair of Software Engineering
Abstract factory: pattern properties
Isolates concrete classesMakes exchanging product families easyPromotes consistency among productsSupporting new kinds of products is difficult
Software Architecture - Lecture 10
21
Chair of Software Engineering
Visitor
Software Architecture - Lecture 10
22
Chair of Software Engineering
Visitor - Intent
“Represents an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.”
[Gamma et al., p 331]
Static class hierarchyNeed to perform traversal operations on
corresponding data structuresAvoid changing the original class structure
Software Architecture - Lecture 10
23
Chair of Software Engineering
Visitor application example
Set of classes to deal with XML documentsXML_NODEXML_DOCUMENTXML_ELEMENTXML_ATTRIBUTEXML_CONTENT
One parserMany formatters
Pretty-printCompressConvert to different encoding…
Software Architecture - Lecture 10
24
Chair of Software Engineering
Another example
AST of programNodes: Class, Feature, instruction, …Operations:
CompilePretty printGenerate documentationRefactor
Software Architecture - Lecture 10
25
Chair of Software Engineering
Library example
+BOOK
+DVD
*BORROWABLE
We want to add external functionality, for example:MaintenanceVisualization
Software Architecture - Lecture 10
26
Chair of Software Engineering
Maintenance
maintain (b: BORROWABLE) is-- Perform maintenance operations on n.
requireexists: b /= Void
localbook: BOOKdvd: DVD
dobook ?= bif book /= Void then
… Book maintenance …enddvd ?= bif dvd /= Void then
… DVD maintenance …end
endend
Software Architecture - Lecture 10
27
Chair of Software Engineering
Visualization
display (b: BORROWABLE) is-- Display b.
requireexists: b /= Void
localbook: BOOKdvd: DVD
dobook ?= bif book /= Void then
… Put book on display …enddvd ?= bif dvd /= Void then
… Put DVD on display …end
endend
Why is this approach bad ?
Software Architecture - Lecture 10
28
Chair of Software Engineering
Visitor: overall architecture
+BOOK
+DVD
*VISITOR
+MAINTENANCE
_VISITOR
+DISPLAY_VISITOR
accept*
accept+ accept+
visit_book*
visit_book+visit_book+
visit_dvd+visit_dvd+
visit_dvd*
*BORROWABLE
Software Architecture - Lecture 10
29
Chair of Software Engineering
Class MAINTENANCE_VISITORclass
MAINTENANCE_VISITORinherit
VISITORfeature -- Basic operations
visit_book (b: BOOK) is-- Perform maintenance operations on b.
dob.check_bindingif b.damaged then
b.repairend
endvisit_dvd (d: DVD) is
-- Perform maintenance operations on d.do
d.check_surfaceif d.damaged then
d.order_replacementend
endend
Software Architecture - Lecture 10
30
Chair of Software Engineering
Class BOOK
classBOOK
inheritBORROWABLE
featureaccept (v: VISITOR) is
-- Apply to v the book visit mechanism.do
v.visit_book (Current)end
end
Software Architecture - Lecture 10
31
Chair of Software Engineering
Class DVD
classDVD
inheritBORROWABLE
feature -- Visitor patternaccept (v: VISITOR) is
-- Apply to d the DVD visit mechanism.do
v.visit_dvd (Current)end
end
Software Architecture - Lecture 10
32
Chair of Software Engineering
Visitor - Usagelocal
item: BORROWABLEmaintainer: MAINTENANCE_VISITOR
do…
item.accept (maintainer)…end
accept**
BORROWABLE
+BOOK
+DVD
accept+accept+
Calls VISITOR.visit_book Calls VISITOR.visit_dvd
Software Architecture - Lecture 10
33
Chair of Software Engineering
Visitor - Participants
VisitorCommon ancestor for all concrete visitors.
Concrete VisitorRepresents a specific operation, applicable to all elements.
ElementCommon ancestor for all concrete elements.
Concrete ElementRepresents a specific element in class hierarchy.
Software Architecture - Lecture 10
34
Chair of Software Engineering
Visitor - Consequences
Makes adding new operations easyGathers related operations, separates unrelated onesAvoids assignment attempts
Better type checkingAdding new concrete element is hard
Software Architecture - Lecture 10
35
Chair of Software Engineering
Observer
Software Architecture - Lecture 10
36
Chair of Software Engineering
Observer
VIEW
A = 50%B = 30%C = 20%
Obs
erve
rsSu
bjec
t
Software Architecture - Lecture 10
37
Chair of Software Engineering
Observer pattern
“Define[s] a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.” [Gamma et al.]
Terminology:Objects being watched:
SUBJECTS or PUBLISHERSObjects that need to be notified of changes:
OBSERVERS or SUBSCRIBERS
Rest of this presentation uses “publish-subscribe” terminology
Software Architecture - Lecture 10
38
Chair of Software Engineering
Observer pattern
*SUBSCRIBER
*PUBLISHER
+MY_SUBSCRIBER
+MY_PUBLISHER
update*
update+publisher
subscribers
subscribers
add_subscriber+
remove_subscriber+
notify_subscribers+
Software Architecture - Lecture 10
39
Chair of Software Engineering
General publisher (1/2)
classPUBLISHER
feature -- Accesssubscribers: LINKED_LIST [SUBSCRIBER]
-- Observers subscribed to this publisherfeature – Element change
add_subscriber (s: SUBSCRIBER) is-- Register s as subscriber to this publisher.
dosubscribers.extend (s)
end
Software Architecture - Lecture 10
40
Chair of Software Engineering
General publisher (2/2)
feature – Observer patternnotify_subscribers is
-- Broadcast change to all registered subscribers.do
fromsubscribers.start
untilsubscribers.after
loopsubscribers.item.updatesubscribers.forth
endend
end
Software Architecture - Lecture 10
41
Chair of Software Engineering
Book library publisher
classLIBRARY
inheritPUBLISHER
redefinedefault_create
endfeature {NONE} -- Initialization
default_create is-- Create and initialize library with empty book list.
doPrecursor {PUBLISHER}create books.make
end
Software Architecture - Lecture 10
42
Chair of Software Engineering
Library publisher
feature -- Accessbooks: LINKED_LIST [BOOKS]
-- Books currently in libraryfeature -- Element change
add_book (b: BOOK) is-- Add b to the list of books and notify all library subscribers.
requireb_not_void: b /= Voidnot_yet_in_library: not books.has (b)
dobooks.extend (b)notify_subscribers
ensureone_more: books.count = old books.count + 1book_added: books.last = b
end...invariant
books_not_void: books /= Voidno_void_book: not books.has (Void)
end
Software Architecture - Lecture 10
43
Chair of Software Engineering
Library subscriber
classAPPLICATION
inheritSUBSCRIBER
renameupdate as display_book
redefinedefault_create
endfeature {NONE} -- Initialization
default_create is-- Initialize library and subscribe current application as-- library subscriber.
docreate librarylibrary.add_subscriber (Current)
end…
Software Architecture - Lecture 10
44
Chair of Software Engineering
Library subscriber
feature -- Observer patternlibrary: LIBRARY
-- Subject to observedisplay_book is
-- Display title of last book added to library.do
print (library.books.last.title)end
invariantlibrary_not_void: library /= Voidconsistent: library.subscribers.has (Current)
end
Software Architecture - Lecture 10
45
Chair of Software Engineering
Drawbacks of Observer structure
The publisher internally knows its subscribers
No information passing from publisher to subscriber when an event occurs
An subscriber can register with at most one publisher
Could pass the PUBLISHER as argument to update but would yield many assignment attempts to distinguish between the different PUBLISHERs.
Software Architecture - Lecture 10
46
Chair of Software Engineering
Chain of responsibility, Command
Software Architecture - Lecture 10
47
Chair of Software Engineering
Behavioral design patterns (1/2)
CreationalAbstract FactoryBuilderFactory MethodPrototypeSingleton
StructuralAdapterBridgeCompositeDecoratorFaçadeFlyweightProxy
BehavioralChain of ResponsibilityCommandInterpreterIteratorMediatorMementoObserverStateStrategyTemplate MethodVisitor
Software Architecture - Lecture 10
48
Chair of Software Engineering
Behavioral design patterns (2/2)
Deal with:AlgorithmsAssignment of responsibilities between objectsCommunication between objects
How:Through inheritance or composition
Software Architecture - Lecture 10
49
Chair of Software Engineering
Chain of Responsibility: Intent
“Avoid[s] coupling the sender of a request to its receiver by giving more than one object a change to handle the request. [It] chain[s]the receiving objects and pass[es] the request along the chain until an object handles it.” [Gamma et al.]
*HANDLER
+INTERMEDIATE_
HANDLER
+FINAL_HANDLER
next
can_handle+do_handle+
can_handle+do_handle+
handlecan_handle*do_handle*handledset_next
APPLICATION
Software Architecture - Lecture 10
50
Chair of Software Engineering
Class HANDLER
deferred classHANDLER
...feature -- Basic operation
handle is-- Handle request if can_handle otherwise forward it to next.-- If next is void, set handled to False.
doif can_handle then
do_handlehandled := True
elseif next /= Void then
next.handlehandled := next.handled
elsehandled := False
endend
ensurecan_handle implies handled(not can_handle and then next /= Void) implies handled = next.handled(not can_handle and then next = Void) implies not handled
end...end
Software Architecture - Lecture 10
51
Chair of Software Engineering
Chain of Responsibility
*HANDLER
[G]
+INTERMEDIATE_
HANDLER[G]
+FINAL_HANDLER
[G]
next
can_handle+do_handle+
can_handle+do_handle+
handlecan_handle*do_handle*handledset_next
APPLICATION
Software Architecture - Lecture 10
52
Chair of Software Engineering
Class HANDLER [G]
deferred classHANDLER [G]
feature {NONE} -- Initializationmake (n: like next) is
-- Set next to n.do
next := nensure
next_set: next = nend
feature -- Accessnext: HANDLER [G]
-- Successor in the chain of responsibilityfeature -- Status report
can_handle (r: G): BOOLEAN is deferred end-- Can this handler handle r?
handled: BOOLEAN-- Has request been handled?
Software Architecture - Lecture 10
53
Chair of Software Engineering
Class HANDLER [G]
feature -- Basic operationshandle (r: G) is
-- Handle r if can_handle otherwise forward it to next.-- If no next, set handled to False.
doif can_handle (r) then
do_handle (r)handled := True
elseif next /= Void then
next.handle (r)handled := next.handled
elsehandled := False
endend
ensurecan_handle (r) implies handled(not can_handle (r) and next /= Void)
implies handled = next.handled(not can_handle (r) and next = Void)
implies not handledend
Software Architecture - Lecture 10
54
Chair of Software Engineering
Class HANDLER [G]
feature -- Element changeset_next (n: like next) is
-- Set next to n.do
next := nensure
next_set: next = nend
feature {NONE} -- Implementationdo_handle (r: G) is
-- Handle r.require
can_handle: can_handle (r)deferredend
end
Software Architecture - Lecture 10
55
Chair of Software Engineering
Chain of Responsibility: feature handle
deferred classHANDLER [G]
…feature -- Basic operation
handle (r: G) is-- Handle r if can_handle otherwise forward it to next.-- If next is void, set handled to False.
doif can_handle (r) then
do_handle (r)handled := True
elseif next /= Void then
next.handle (r)handled := next.handled
elsehandled := False
endend
ensure…
end…end
require -- ???not handled
Would mean that a HANDLER that has handled a request cannot handle any other request; one would need to create another HANDLER object
⇒ Not very useful
Software Architecture - Lecture 10
56
Chair of Software Engineering
Command pattern
Software Architecture - Lecture 10
57
Chair of Software Engineering
Command pattern: Intent
Way to implement an undo-redo mechanism, e.g. in text editors. [OOSC, p 285-290]
“Way to encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.” [Gamma et al., p 233]
Software Architecture - Lecture 10
58
Chair of Software Engineering
Command pattern (history-executable)
APPLICATION HISTORYhistory *
COMMANDcommands
is_once_commandexecute*undo*redo*
executecan_undo, can_redoundo, redoundo_all, redo_allcommands, argumentsextend
+COMMAND_1
execute+undo+redo+
+COMMAND_2
execute+undo+redo+
Software Architecture - Lecture 10
59
Chair of Software Engineering
How to use the Command pattern
Create a descendant of COMMAND and effect its features execute, undo, and redoclass
COMMAND_1inherit
COMMANDcreate
makefeature {HISTORY} -- Command pattern
execute (args: TUPLE) is do … end-- Execute command with args.
feature {HISTORY} -- Undoundo (args: TUPLE) is do … end
-- Undo last action.feature {HISTORY} -- Redo
redo (args: TUPLE) is do … end-- Redo last undone action.
end
To be completed
Software Architecture - Lecture 10
60
Chair of Software Engineering
Example using the Command pattern (1/2)
classAPPLICATION
createmake
feature {NONE} -- Initializationmake is
-- Create a command and execute it. -- (Use the undo/redo mechanism.)
localcommand_1: COMMAND_1command_2: COMMAND_2
docreate command_1.make (True)create command_2.make (False)history.execute (command_1, [])history.execute (command_2, [])history.undohistory.redo
end
Software Architecture - Lecture 10
61
Chair of Software Engineering
Example using the Command pattern (2/2)
feature {NONE} -- Implementation
history: HISTORY is-- History of executed commands
oncecreate Result.make
ensurehistory_not_void: Result /= Void
end
end
Software Architecture - Lecture 10
62
Chair of Software Engineering
Command pattern (self-executable)
APPLICATION
HISTORY *COMMAND
commands
SHARED_HISTORY
history
hasexecutecan_undo, can_redoundo, redoundo_all, redo_allcommands,argumentsextend
+COMMAND_1
execute+undo+redo+
+COMMAND_2
execute+undo+redo+
is_once_commandexecute*undo*redo*
Software Architecture - Lecture 10
63
Chair of Software Engineering
Command: class SHARED_HISTORY
APPLICATION
HISTORY *COMMAND
commands
SHARED_HISTORY
history
hasexecutecan_undo, can_redoundo, redoundo_all, redo_allcommands, argumentsextend
+COMMAND_1
execute+undo+redo+
+COMMAND_2
execute+undo+redo+
is_once_commandexecute*undo*redo*
Common scheme in Eiffel: Inherit from a class containing the data to be shared among different objects
Not compulsory: COMMANDcould have an attribute historyinitialized at creation and one would always pass the same HISTORY object as argument; hence sharing.
Advantage: enables having several histories; e.g. keep 2 histories of commands corresponding to 2 editor windows)
Software Architecture - Lecture 10
64
Chair of Software Engineering
Observer pattern: some limitations
Each publisher object knows about its observers
Only one update procedure in SUBSCRIBER :At most one operationSubscribe to at most one publisher!
Not reusable — must be coded anew for each application
(This is the difference between patterns & components!)
Software Architecture - Lecture 10
65
Chair of Software Engineering
Design patterns
CreationalAbstract FactoryBuilderFactory MethodPrototypeSingleton
StructuralAdapterBridgeCompositeDecoratorFaçadeFlyweightProxy
BehavioralChain of ResponsibilityCommandInterpreterIteratorMediatorMementoObserverStateStrategyTemplate MethodVisitor
Software Architecture - Lecture 10
66
Chair of Software Engineering
Beyond patterns
A pattern is an architectural solutionEach programmer who needs the pattern has to learn it (externals and internals) and reimplement it for every application)Similar to traditional learning of algorithms and data structures
Can we do better: use components instead?
It’s better to reuse than do redo.
(if reuse occurs through an API)
Software Architecture - Lecture 10
67
Chair of Software Engineering
Components over patterns
Easier to learn
No need to learn implementation
Professional implementation will be better than manually crafted one
But: do we lose generality?
Software Architecture - Lecture 10
68
Chair of Software Engineering
Some references
Karine Arnout & Bertrand Meyer: Componentization, the Factory Pattern(Innovations in Systems and Software Engineering, 2006)
http://se.ethz.ch/~meyer/publications/nasa/factory.pdf
Bertrand Meyer & Karine Arnout: Pattern componentization, the Visitor example, IEEE Computer, to appear, 2006http://se.ethz.ch/~meyer/publications/computer/visitor.pdf
Karine Arnout: From Patterns to Components, PhD thesis, ETH, 2004 (see SE Web site)
Software Architecture - Lecture 10
69
Chair of Software Engineering
The key to pattern componentization
Genericity (unconstrained and constrained)ContractsOnce routinesInheritance, in particular multiple inheritanceTuplesAgents
Software Architecture - Lecture 10
70
Chair of Software Engineering
A refresher on agents
objects representing potential computations
b
∫ my_function (x) dx
a
my_integrator.integral (agent my_function, a, b)
Software Architecture - Lecture 10
71
Chair of Software Engineering
Normal call vs. agent call
Normal call
a0.f (a1, a2, a3)
Agent call (expression): preface it by keyword agent, yielding
agent a0.f (a1, a2, a3)
For example:
u := agent a0.f (a1, a2, a3)
This represents the routine, ready to be called. To call it:
u.call ([])-- For type of u, see next
Recall original name of agents: “delayed calls”.
Software Architecture - Lecture 10
72
Chair of Software Engineering
Agent types: Kernel library classes
*ROUTINE
[BASE, ARGS -> TUPLE]
*PROCEDURE
[BASE, ARGS -> TUPLE]
*FUNCTION
[BASE, ARGS -> TUPLE, RES]
item
Inherits from
* Deferredcall
Software Architecture - Lecture 10
73
Chair of Software Engineering
Creating vs. calling an agent
Writing:agent my_feature
creates an agent, i.e. an object of type ROUTINE.
To call an agent, one needs to execute call (with the proper arguments) to this ROUTINE object, e.g:
my_routine.call ([args])
Software Architecture - Lecture 10
74
Chair of Software Engineering
Iterators
In class LINEAR [G], ancestor to all classes for lists, sequences etc., you will find:
for_allthere_existsdo_alldo_ifdo_whiledo_until
Software Architecture - Lecture 10
75
Chair of Software Engineering
Iterating on either the target or an argument
all_positive := my_integer_list.for_all (agent is_positive (?))
all_married := my_employee_list.for_all
(agent {EMPLOYEE}. is_married)
This assumes
class C with:
is_positive (n : INTEGER): BOOLEAN
class EMPLOYEE with: is_married : BOOLEAN
Software Architecture - Lecture 10
76
Chair of Software Engineering
Applications of agents
Undo-redoIterationHigh-level contractsNumerical programmingReflection
Software Architecture - Lecture 10
77
Chair of Software Engineering
Keeping arguments open
An agent can have both “closed” and “open”arguments.
Closed arguments set at time of agent definition; open arguments set at time of each call.
To keep an argument open, just replace it by a question mark:
u := agent a0.f (a1, a2, a3)-- All closed (as before)
w := agent a0.f (a1, a2, ?)x := agent a0.f (a1, ?, a3)y := agent a0.f (a1, ?, ?)z := agent a0.f (?, ?, ?)
Software Architecture - Lecture 10
78
Chair of Software Engineering
Observer pattern: some limitations
Each publisher object knows about its observers
Only one update procedure in SUBSCRIBER :At most one operationSubscribe to at most one publisher!
Not reusable — must be coded anew for each application
(This is the difference between patterns & components!)
Software Architecture - Lecture 10
79
Chair of Software Engineering
Another approach: event-action table
Event_type – Action Table
More precisely: Event_type - Context – Action Table
Left_click Save_file
Event type
Reset
Right_click Display_Menu
Action
… …
Yes_button
Context
…
…
Left_click
Left_click
Cancel_button
…
Software Architecture - Lecture 10
80
Chair of Software Engineering
Action-event tableSet of triples
[Event, Context, Action]
Event: any occurrence we trackExample: a mouse click
Context: object for whichthe event is interesting
Example: a particular button
Action: what we want to do when the event occurs in the contextExample: save the file
Action-event table may be implemented as e.g. a hash table.
Software Architecture - Lecture 10
81
Chair of Software Engineering
Mechanisms in other languages
C and C++: “function pointers”
C#: delegates (more limited form of agents)
Software Architecture - Lecture 10
82
Chair of Software Engineering
Problem scenario
One of your classes has a routine your_procedure
Your application has a GUI object known as Yes_button
Whenever the user clicks the mouse the underlying GUI library returns the mouse coordinates
You want to ensure that a mouse click at coordinates [h, v] in calls your_procedure (h, v)
Software Architecture - Lecture 10
83
Chair of Software Engineering
With .NET delegates: publisher (1)
P1. Introduce new class ClickArgs inheriting from EventArgs,repeating arguments types of yourProcedure:
public class Clickargs {... int x, y; …}
P2. Introduce new delegate type ClickDelegate based on Clickargs:
public void delegate ClickDelegate (Objectsender, e);
P3. Introduce new event type Click based on ClickDelegate:
public event ClickDelegate Click;
Software Architecture - Lecture 10
84
Chair of Software Engineering
With .NET delegates: publisher (2)
P4. Introduce new procedure OnClick to wrap handling:
protected void OnClick (Clickargs c)
{if (Click != null) {Click (this, c);}}
P5. For every event occurrence, create new object(instance of ClickArgs), passing arguments to constructor:
ClickArgs yourClickargs = new Clickargs (h, v);
P6. For every event occurrence, trigger event:OnClick (yourClickargs);
Software Architecture - Lecture 10
85
Chair of Software Engineering
With .NET delegates: subscriber
D1. Declare a delegate myDelegate of type ClickDelegate.(Usually combined with following step.)
D2. Instantiate it with yourProcedure as argument:
ClickDelegate myDelegate =new ClickDelegate (yourProcedure);
D3. Add it to the delegate list for the event:
YES_button.Click += myDelegate;
Software Architecture - Lecture 10
86
Chair of Software Engineering
Event Library
Basically:One generic class: EVENT_TYPETwo features: publish and subscribe
For example: A button my_button that reacts in a way defined in my_procedure when clicked (event mouse_click):
Software Architecture - Lecture 10
87
Chair of Software Engineering
Using the Event Library
The publisher creates an event type object:
mouse_click: EVENT_TYPE [TUPLE [INTEGER, INTEGER]] is-- Mouse click event type
oncecreate Result
ensuremouse_click_not_void: Result /= Void
end
The publisher triggers the event:
mouse_click.publish ([x_positition, y_position])
The subscribers (“observers”) subscribe to events:
my_button.mouse_click.subscribe (agent my_procedure)
Software Architecture - Lecture 10
88
Chair of Software Engineering
Publisher, subscriber, subscribed object (2/2)
Subscriber(APPLICATION)
Subscribed objects Publishers
Subscribes objects to events
Observer Subject
Software Architecture - Lecture 10
89
Chair of Software Engineering
Book library example with the Event Library (1/2)
classLIBRARY
…feature -- Access
books: LINKED_LIST [BOOK]-- Books in library
feature -- Event type
book_event: EVENT_TYPE [TUPLE [BOOK]]-- Event associated with attribute books
Software Architecture - Lecture 10
90
Chair of Software Engineering
Book library example with the Event Library (2/2)
feature -- Element changeadd_book (b: BOOK) is
-- Add b to the list of books and -- publish book_event.
requireb_not_void: b /= Voidnot_yet_in_library: not books.has (b)
dobooks.extend (b)book_event.publish ([b])
ensureone_more: books.count = old books.count + 1book_added: books.last = b
endinvariant
books_not_void: books /= Voidbook_event_not_void: book_event /= Void
end
Software Architecture - Lecture 10
91
Chair of Software Engineering
Observer pattern vs. Event Library
In case of an existing class MY_CLASS:
With the Observer pattern:Need to write a descendant of SUBSCRIBERand MY_CLASS
⇒ Useless multiplication of classes
With the Event Library:Can reuse the existing routines directly as agents
Software Architecture - Lecture 10
92
Chair of Software Engineering
Observer pattern
*SUBSCRIBER
*PUBLISHER
+MY_SUBSCRIBER
+MY_PUBLISHER
update*
update+publisher
subscribers
subscribers
add_subscriber+
remove_subscriber+
notify_subscribers+
Software Architecture - Lecture 10
93
Chair of Software Engineering
Exercise
Investigate the use of agents to improve:VisitorUndo-redo