Professional Documents
Culture Documents
Matthew Dailey
Computer Science and Information Management Asian Institute of Technology
Design Patterns I
1 / 50
Readings
Readings for these lecture notes: - Larman (2005), Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development, 3rd edition, Chapter 17. Some material c Larman (2005).
Design Patterns I
2 / 50
Outline
Introduction
Responsibility-Driven Design
Wrap-Up
Design Patterns I
3 / 50
Introduction
Getting started with design modeling
Object-oriented design is not about UML. It is primarily about assigning responsibilities to objects. Design modeling normally begins on the rst elaboration iteration. The situation: A two-day requirements workshop has been completed. 10%20% of the requirements have been detailed. The large-scale architecture has been dened. We have use case text, system sequence diagrams, operation contracts, and a domain model. We organize a one-day modeling workshop.
Design Patterns I
4 / 50
Introduction
Design guidelines
Some guidelines for the design process: For OOD we use the metaphor of responsibility-driven design. We attempt to determine how responsibilities should be divvied up between software objects. During design modeling, we focus on the dicult and/or creative parts of the design. We create models for communication and understanding, not for documentation.
Design Patterns I
5 / 50
Introduction
Design outputs
Possible outputs of the design process: Interaction diagrams Class diagrams Package diagrams UI sketches Database design Report sketches
Design Patterns I
6 / 50
Introduction
Artifact relationships
Sample UP Artifact Relationships Domain Model
We will begin realizing our use cases by assigning system operations from SSD analysis to software objects. We might derive the software classes from the domain model or create new classes. Then we will determine how those objects collaborate with other objects to implement the system operation including operation contract postconditions.
Matthew Dailey (CSIM-AIT)
Business Modeling
1..*
...
1. Customer arrives ... 2. ... 3. Cashier enters item identifier. Use Case Text system events : System
Supplementary Specification
Requirements
: Cashier
system operations
Design Model
: ProductCatalog
: Sale
Design
ProductCatalog
getProductDescription(...) ...
Outline
Introduction
Responsibility-Driven Design
Wrap-Up
Design Patterns I
8 / 50
Responsibility-Driven Design
Introduction
Responsibility-driven design concerns object responsibilities, roles, and collaborations. There are two types of responsibilities: Doing responsibilities concern performing a task such as creating an object, performing a calculation, coordinating activities, and so on. Knowing responsibilities concern knowing about private data, related objects, data needed for calculations, and so on. We say that responsibilties are fullled by object methods.
Design Patterns I
9 / 50
Responsibility-Driven Design
Example: Knowing responsibilities
Design Patterns I
10 / 50
Responsibility-Driven Design
Collaborations
Collaborations mean the objects that cooperate to get work done. Collaboration example: a Sale object might invoke the getSubtotal method on multiple SaleLineItem objects to fulll the responsibility of calculating a total.
Design Patterns I
11 / 50
Responsibility-Driven Design
GRASP
GRASP: General Responsibility Assignment Software Patterns or Principles. GRASP provides basic patterns or principles for assignment of responsibilities to objects. When drawing interaction diagrams, you are implicitly assigning responsibilities to particular objects. Use GRASP when drawing interaction diagrams and coding.
Design Patterns I
12 / 50
Responsibility-Driven Design
Fundamental GRASP principles
Design Patterns I
13 / 50
Outline
Introduction
Responsibility-Driven Design
Wrap-Up
Design Patterns I
14 / 50
The Creator pattern: who should be responsible for creating instances of class A?
B creates A if: B contains A B records A B closely uses A B has the information needed to create A
Design Patterns I
15 / 50
Example: in Monopoly, who should create the Square objects? First, consider the domain model:
Example: in the POS system, who should create the SalesLineItem objects? First, consider the domain model:
Sale time 1 Contains 1..* Sales LineItem quantity
Described-by
Design Patterns I
18 / 50
We see that Sale contains SalesLineItem, so we give the responsibility to Sale in the dynamic model:
: Register : Sale
When object creation is suciently complex, involving recycling, polymorphism, and so on, it may be useful to separate the creation responsibility into a Factory helper class (GoF, Larman Ch. 26).
Matthew Dailey (CSIM-AIT) Design Patterns I 19 / 50
The Information Expert pattern: who should be responsible for knowing about instances of a class?
We assign knowing responsibilities to the class having the information needed to fulll the responsibility. When assigning knowing responsibilities, rst look in the design model for an appropriate class. If not found in the design model, look in the domain model.
Design Patterns I
20 / 50
Example: in the Monopoly game, Board should have the responsibility to know about Square instances.
Design Patterns I
21 / 50
Example: who should have the responsibility to know the total price for a sale? Domain model:
Sale time 1 Contains 1..* Sales LineItem quantity
Described-by
Design Patterns I
22 / 50
We see that Sale already has the SalesLineItem objects needed to calculate the total:
t = getTotal :Sale time ... New method getTotal() Sale
Design Patterns I
23 / 50
But to get the price of a SalesLineItem, we also need the ProductDescriptions price attribute. SalesLineItem has the needed information:
this notation will imply we are iterating over all elements of a collection time ... t = getTotal : Sale 1 *: st = getSubtotal lineItems[ i ] : SalesLineItem getTotal() Sale
Design Patterns I
24 / 50
To fulll the responsibility to know its subtotal, the SalesLineItem needs to collaborate with ProductDescription:
Sale time ... t = getTotal : Sale 1 *: st = getSubtotal lineItems[ i ] : SalesLineItem getTotal()
1.1: p := getPrice()
SalesLineItem quantity
:Product Description
New method
getPrice()
Design Patterns I
25 / 50
Design Patterns I
26 / 50
Note that Information Expert reduces coupling. Consider an alternative design for the responsibility of knowing about Square objects:
Design Patterns I
27 / 50
Example: how to create a Payment object and associate it with a Sale? On the one hand, we might give Register the responsibility to create the Payment:
makePayment() : Register 1: create() p : Payment
2: addPayment(p)
:Sale
Design Patterns I
28 / 50
On the other hand, we might give Sale the responsibility to create the Payment:
makePayment() : Register 1: makePayment() :Sale
1.1. create()
:Payment
Which is better? It is unavoidable that Sale is coupled to Payment. But the rst design creates an unnecessary coupling of Sale to Register. All else being equal, we prefer the second.
Design Patterns I
29 / 50
Common kinds of coupling between TypeX and TypeY: TypeX has an attribute that refers to a TypeY instance or TypeY itself. A TypeX object calls on the services of a TypeY object. TypeX has a method referencing (via parameters, local variables, or return values) a TypeY instance. TypeX is a direct or indirect subclass of TypeY. TypeY is an interface, and TypeX implements that interface. Avoiding coupling is not always necessary. It is most important at points of instability. Therefore coupling to stable APIs like java.util is generally OK.
Design Patterns I
30 / 50
The Controller pattern: who should be responsible for receiving and coordinating a system operation?
We create controller objects to handle system operation messages. In most systems, actors will generate UI events. UI objects react to these elements then delegate to objects in the domain layer (or the intermediate application layer, if you have one). The rst object in the domain layer is called the controller for the system operation.
Design Patterns I
31 / 50
There are two main types of controller: A controller representing an entire system, root object, device, or subsystem is called a facade controller. Use a class name such as the name of the SuD. A controller responsible for one use case scenario is called a session controller. Use names such as <UseCaseName>Handler or <UseCaseName>Session. Note that the GRASP controller is not the same as the C in MVC!
Design Patterns I
32 / 50
Example: for the Monopoly game, there are few system operations:
For playGame(), we need to identify the recipient of the system operation message:
Design Patterns I
34 / 50
In this case, since there are so few operations, we use the root object controller pattern:
Design Patterns I
35 / 50
presses button
UI Layer
Domain Layer
: ???
Which class of object should be responsible for receiving this system event message? It is sometimes called the controller or coordinator. It does not normally do the work, but delegates it to other objects. The controller is a kind of "facade" onto the domain layer from the interface layer.
enterItem(id, quantity)
:ProcessSaleHandler
Design Patterns I
37 / 50
Combining with the other system operations, we can see the consequences of each design alternative:
System endSale() enterItem() makeNewSale() makePayment() makeNewReturn() enterReturnItem() ... ... endSale() enterItem() makeNewSale() makePayment() makeNewReturn() enterReturnItem() ... Register
HandleReturns Handler
allocation of system operations during design, using several use case controllers
Some tips about controllers: The controller should be seen as a facade into the domain layer. Use the same controller for all system events involved in a use case. Controllers will often be stateful, maintaining information about the current progress of the use case. For purposes of cohesion, controllers should primarily delegate, (forward responsibility to other objects) wherever possible. In Java EE, controllers will oftentimes be stateful session Enterprise Java Beans. The controller may delegate directly to domain layer objects, or if it is in a separate application logic layer, it may make requests to other controllers in the pure domain layer.
Design Patterns I
39 / 50
Some controller antipatterns: A single controller with too many system events. No delegation. Duplication of information found elsewhere in the domain layer.
Design Patterns I
40 / 50
Dont allow direct manipulation of domain objects in the UI layer! Example (good design):
presses button
UI Layer
:SaleJFrame
1: enterItem(itemID, qty)
controller
Domain Layer
:Register
:Sale
presses button
Cashier actionPerformed( actionEvent ) It is undesirable for an interface layer object such as a window to get involved in deciding how to handle domain processes. Business logic is embedded in the presentation layer, which is not useful.
UI Layer
:SaleJFrame
Domain Layer
1: makeLineItem(itemID, qty)
:Sale
In message processing systems, rather than a use case controller, we would most likely use the Command pattern in which we have one object for each possible type of incoming command (see Larman Ch. 37 for details).
Design Patterns I
43 / 50
The High Cohesion principle: how to keep objects focused, understandable, and manageable?
We assign responsibilities so that cohesion remains high, i.e., so that similar responsibilities are grouped into the same class. High cohesion is a principle used to evaluate competing designs.
Design Patterns I
44 / 50
Design Patterns I
45 / 50
Example: for the POS system, when we design for the makePayment() system operation:
: Register : Sale
addPayment( p )
We already saw that this creates an unnecessary coupling between Register and Payment. But it also reduces the cohesion of Register.
Matthew Dailey (CSIM-AIT) Design Patterns I 46 / 50
By delegating Payment creation to Sale, we not only decrease coupling, but we also increase the cohesion of Register.
: Register : Sale
Cohesion and coupling often go together: you will often see cases where increased coupling also causes low cohesion, and vice versa.
Design Patterns I
48 / 50
Outline
Introduction
Responsibility-Driven Design
Wrap-Up
Design Patterns I
49 / 50
Wrap-Up
Next step
Now that we know the basic principles of responsibility assignment, were ready to do detailed designs for some of our use cases. Later, well look at more advanced design patterns.
Design Patterns I
50 / 50