Implementation

Download Report

Transcript Implementation

Practical Object-Oriented Design with UML 2e
PRACTICAL
OBJECT-ORIENTED
DESIGN WITH UML
2e
Chapter 14:
Principles and Patterns
©The McGraw-Hill Companies, 2004
Slide 1/1
Practical Object-Oriented Design with UML 2e
Principles and Patterns
● The activity of design can be informed by
– principles: general statements of what properties
a design ought to have
– patterns: concrete examples of successful
designs for particular purposes
©The McGraw-Hill Companies, 2004
Slide 1/2
Practical Object-Oriented Design with UML 2e
Valid or Correct Models
• A model is said to be valid (or legal) if it conforms to the
UML rules. A model is correct if it faithfully represents
reality. Assuming that the UML is correct, we can state
that all correct models are valid models. However, the
converse may not true – valid models are not necessarily
correct models. For example, imagine that a hospital is
being modeled, but the modeler fails to include a critical
state, such as a WardFull state. In this case, the UML
class diagram is valid (UML does not require a WardFull
state , but merely allows it), but is incorrect, since it does
not represent reality. However, if the UML required every
model to include the a WardFull state, the model would
be invalid. We can now consider good configurations or
designs of valid models.
©The McGraw-Hill Companies, 2004
Slide 1/3
Practical Object-Oriented Design with UML 2e
System Evolution
● How can we insulate modules from change?
● We would like to be able to change modules
without affecting their clients
– this will increase the maintainability of the
system
©The McGraw-Hill Companies, 2004
Slide 1/4
Practical Object-Oriented Design with UML 2e
Open and Closed Modules
● A module is said to be closed if it is not
subject to further change
– clients can then rely on the services the module
provides
● A module is said to be open if it is still
available for extension
– this will make it possible to extend and modify
the system
©The McGraw-Hill Companies, 2004
Slide 1/5
Practical Object-Oriented Design with UML 2e
The Open-Closed Principle
● Open and closed modules both have
advantages
● The open-closed principle states that
developers should try to produce modules
that are both open and closed
● This sounds like a paradox
– to resolve it we need a way of making a module
extendible without having to change it
©The McGraw-Hill Companies, 2004
Slide 1/6
Practical Object-Oriented Design with UML 2e
Interface and Implementation
● The interface of a module is what is visible or
available to clients
● The implementation is the internal details of
the module that support the interface
● One approach to open-closed modules is to
ensure that clients only depend on the
interfaces of the modules they use
– and make it possible to change the
implementations freely
©The McGraw-Hill Companies, 2004
Slide 1/7
Practical Object-Oriented Design with UML 2e
Data Abstraction
● Data abstraction assigns an access level to
each feature in a class
● Clients can use only the public interface
● Private features - eg method bodies - can be
freely changed
©The McGraw-Hill Companies, 2004
Slide 1/8
Practical Object-Oriented Design with UML 2e
Limitations
● Even with data abstraction, Java classes are
technically not closed
– changes to method bodies affect the source
code and entail recompilation of clients
● The interface actually used by clients is left
implicit (no actual interface just concrete
supplier or server)
©The McGraw-Hill Companies, 2004
Slide 1/9
Practical Object-Oriented Design with UML 2e
Abstract Interface Classes
● An approach based on generalization (not
pure interfaces)
● Abstract classes can provide a complete or
partial implementation of a method(s).
©The McGraw-Hill Companies, 2004
Slide 1/10
Practical Object-Oriented Design with UML 2e
How the Interface Works
● Clients access different concrete suppliers
through the abstract supplier interface
● This is enabled by features of the objectoriented programming paradigm
– polymorphism: a reference to the interface class
can actually refer to any implementation class
– dynamic binding: messages to the interface are
passed on the appropriate implementation class
©The McGraw-Hill Companies, 2004
Slide 1/11
Practical Object-Oriented Design with UML 2e
Dependencies
● The dependency structure indicates that the
client is independent of the concrete
suppliers
©The McGraw-Hill Companies, 2004
Slide 1/12
Practical Object-Oriented Design with UML 2e
Open and Closed
● The abstract supplier class is
– open in the sense that its functionality can be
extended by adding further subclasses
– closed in that this can be done without affecting
clients
● However, the client is not protected against
changes in the interface exported by the
abstract supplier class
©The McGraw-Hill Companies, 2004
Slide 1/13
Practical Object-Oriented Design with UML 2e
No Concrete Superclasses
● It has sometimes been recommended that all
superclasses in a system should be abstract
● Often subclasses are added to concrete
classes as a system evolves
©The McGraw-Hill Companies, 2004
Slide 1/14
Practical Object-Oriented Design with UML 2e
A Dependency Problem
● The savings account class is now dependent
on the current account class
– changes to the current account - altering
functionality or adding and removing operations will affect savings accounts
● This leads to problems
– the changes may not apply to savings accounts
– the code may become cluttered with checks for
special cases
©The McGraw-Hill Companies, 2004
Slide 1/15
Practical Object-Oriented Design with UML 2e
‘Refactoring’ the Design
● A better approach is to introduce an abstract
interface class
– even if it initially seems unnecessary
©The McGraw-Hill Companies, 2004
Slide 1/16
Practical Object-Oriented Design with UML 2e
Decoupling Interfaces
● Clients can be protected from interface
change by defining separate interface and
implementation hierarchies
● Make the abstract supplier an interface:
©The McGraw-Hill Companies, 2004
Slide 1/17
Practical Object-Oriented Design with UML 2e
Separate Interface Hierarchy
● Extend the interface to add a new operation
– abstract supplier can be extended without
affecting existing clients
©The McGraw-Hill Companies, 2004
Slide 1/18
Practical Object-Oriented Design with UML 2e
Liskov Substitution Principle
● States the conditions under which references
to superclasses can safely be converted to
references to subclasses
– “it must be possible to substitute an instance of a
subclass for an instance of a superclass without
affecting client classes or modules”
– this defines what generalization means in UML
©The McGraw-Hill Companies, 2004
Slide 1/19
Practical Object-Oriented Design with UML 2e
Design Based on Structure
● It is sometimes tempting to base a design on
the physical structure of the artefact being
modelled
– for example, a mobile phone
©The McGraw-Hill Companies, 2004
Slide 1/20
Practical Object-Oriented Design with UML 2e
Realizing ‘Make a Call’
● This interaction looks plausible:
● But the associations based on the phone
structure do not support these messages
©The McGraw-Hill Companies, 2004
Slide 1/21
Practical Object-Oriented Design with UML 2e
Design Based on Interactions
● A better model of the phone is derived from
the interactions in the realization
©The McGraw-Hill Companies, 2004
Slide 1/22
Practical Object-Oriented Design with UML 2e
Design Patterns
● Solutions to common design problems
● Catalogued and published to aid reuse
● A pattern consists of:
– a name, for easy reference
– a description of the problem being solved
– a description of the solution proposed
– a discussion of the consequences of adopting
the pattern
©The McGraw-Hill Companies, 2004
Slide 1/23
Practical Object-Oriented Design with UML 2e
Recursive Structures
● Many data structures are recursive, eg
©The McGraw-Hill Companies, 2004
Slide 1/24
Practical Object-Oriented Design with UML 2e
The ‘Composite’ Pattern
● ‘Composite’ defines the essential properties
of this sort of situation
©The McGraw-Hill Companies, 2004
Slide 1/25
Practical Object-Oriented Design with UML 2e
Discussion of Composite
● The problem is how to implement tree-like
structures
● The diagram shows only the solution
– ‘Leaf’ and ‘Composite’ classes share a common
interface, defined in ‘Component’
– ‘Composite’ implements this by iterating through
all its components
©The McGraw-Hill Companies, 2004
Slide 1/26
Practical Object-Oriented Design with UML 2e
Patterns in UML
● UML documents patterns as parameterized
collaborations
©The McGraw-Hill Companies, 2004
Slide 1/27
Practical Object-Oriented Design with UML 2e
Documenting Pattern Application
● When applying a pattern you must show
what the its classes correspond to
©The McGraw-Hill Companies, 2004
Slide 1/28
Practical Object-Oriented Design with UML 2e
The ‘State’ Pattern
● Problem: how to ‘allow an object to alter its
behaviour when its internal state changes’
– applicable if a class is described by a statechart
● Solution: represent each state by a separate
class
– each state class will implement the behaviour
appropriate for each operation in that state only
©The McGraw-Hill Companies, 2004
Slide 1/29
Practical Object-Oriented Design with UML 2e
The ‘State’ Solution
● A consequence of this pattern is that the
state classes need access to the internal
details of the context class
©The McGraw-Hill Companies, 2004
Slide 1/30
Practical Object-Oriented Design with UML 2e
The ‘Strategy’ Pattern
● Problem: how to allow different instances of a
class to support different implementations of
an operation
● Solution: separate out the implementation of
the operation into a new class hierarchy
– link each instance to a particular implementation
object
©The McGraw-Hill Companies, 2004
Slide 1/31
Practical Object-Oriented Design with UML 2e
The ‘Strategy’ Solution
● The structure is very similar to that of ‘State’
– treated as a different pattern because the
problem being solved is different
©The McGraw-Hill Companies, 2004
Slide 1/32
Practical Object-Oriented Design with UML 2e
Models, Views and Controllers
● MVC: a design proposal put forward for the
Smalltalk language
– to design programs with graphical interfaces
– separates manipulation and presentation of data
● Now widely used in a variety of contexts
– the model stores and maintains data
– views display data in specific ways
– controllers detect and forward user input
©The McGraw-Hill Companies, 2004
Slide 1/33
Practical Object-Oriented Design with UML 2e
Models, Views and Controllers
©The McGraw-Hill Companies, 2004
Slide 1/34
Practical Object-Oriented Design with UML 2e
Interactions in MVC
● User input detected by a controller
● The model is notified
● The views are updated
©The McGraw-Hill Companies, 2004
Slide 1/35
Practical Object-Oriented Design with UML 2e
Document/View Architecture
● Widely used by Microsoft
● A simplification of MVC
– ‘Views’ combine the functions of MVC views and
controllers
©The McGraw-Hill Companies, 2004
Slide 1/36
Practical Object-Oriented Design with UML 2e
Document/View Structure
©The McGraw-Hill Companies, 2004
Slide 1/37
Practical Object-Oriented Design with UML 2e
Document/View Interactions
● Compare this with the MVC interaction
©The McGraw-Hill Companies, 2004
Slide 1/38
Practical Object-Oriented Design with UML 2e
The ‘Observer’ Pattern
● Problem: to define a dependency between
objects so that when one object changes
state all its dependants are notified
● Solution: like MVC, separate ‘subject’ (ie
model) from ‘observer’ (ie view)
©The McGraw-Hill Companies, 2004
Slide 1/39
Practical Object-Oriented Design with UML 2e
‘Observer’ Structure
©The McGraw-Hill Companies, 2004
Slide 1/40
Practical Object-Oriented Design with UML 2e
‘Observer’ Interactions
● This interaction is simpler because the initial
message is sent straight to the ‘model’ class
©The McGraw-Hill Companies, 2004
Slide 1/41
Practical Object-Oriented Design with UML 2e
Parts Explosion
● New requirement for the stock control
program
– print a listing of all the parts and subassemblies
in an assembly
● Simple approach:
– add an ‘explode’ operation to each class
– call it recursively, like the existing ‘cost’ operation
©The McGraw-Hill Companies, 2004
Slide 1/42
Practical Object-Oriented Design with UML 2e
Problems
● There are a number of problems with this
– this approach involves changes to every class in
the hierarchy
– the code that controls the recursion is repeated
in both ‘cost’ and ‘explode’
– model classes like ‘Part’ should not produce
output
● Is there a pattern that can help?
©The McGraw-Hill Companies, 2004
Slide 1/43
Practical Object-Oriented Design with UML 2e
The ‘Visitor’ pattern
● Problem: Visitor lets you define a new
operation without changing the classes of the
elements on which it operates
● Solution: define a ‘visitor’ class and an
operation in each class to be visited to
‘accept’ a visitor
● Consequence: the design becomes more
complex, but more extendible
©The McGraw-Hill Companies, 2004
Slide 1/44
Practical Object-Oriented Design with UML 2e
Finding Costs with Visitor
● This illustrates Visitor with a single operation
©The McGraw-Hill Companies, 2004
Slide 1/45
Practical Object-Oriented Design with UML 2e
The ‘CostVisitor’ Class
● ‘CostVisitor’ gets ‘called’ for each component
and keeps track of the total cost of parts
public class CostVisitor
{
private int total ;
public void visit(Part p) {
total += p.cost() ;
}
public void visit(Assembly a) {}
}
©The McGraw-Hill Companies, 2004
Slide 1/46
Practical Object-Oriented Design with UML 2e
Finding the Cost
● We no longer call a cost function belonging
to an assembly
● Instead, we pass a cost visitor to it
Assembly a ;
CostVisitor visitor = new CostVisitor() ;
a.accept(visitor) ;
int cost = visitor.getTotal() ;
©The McGraw-Hill Companies, 2004
Slide 1/47
Practical Object-Oriented Design with UML 2e
‘Visitor’ Interactions
©The McGraw-Hill Companies, 2004
Slide 1/48
Practical Object-Oriented Design with UML 2e
Adding Part Explosions
● Extend the design by defining a visitor
hierarchy
©The McGraw-Hill Companies, 2004
Slide 1/49
Practical Object-Oriented Design with UML 2e
Mediator Pattern
● The intent is to define an object that
encapsulates how a set of objects interact.
Mediator promotes loose coupling by keeping
objects from referring to each other explicitly,
and it lets you vary their interaction
independently. The purpose of a Mediator is
to manage the relationships between
numerous objects so that they can each
focus on their own behaviour independently
of the others.
©The McGraw-Hill Companies, 2004
Slide 1/50
Practical Object-Oriented Design with UML 2e
Mediator Pattern
©The McGraw-Hill Companies, 2004
Slide 1/51
Practical Object-Oriented Design with UML 2e
Mediator Pattern with Java
©The McGraw-Hill Companies, 2004
Slide 1/52
Practical Object-Oriented Design with UML 2e
Mediator Pattern in Java
● An Example From “Software Design Using Java 2” By Lano, Fiadeiro &
Andrade.
● The mediator pattern centralises
dependencies between objects. Instead of
code being written in one (dependent) object
to update the state of that object when
another object that it depends on changes
state, there is a separate mediator object
which links them and performs the necessary
logic to compute the change needed by the
dependent object.
©The McGraw-Hill Companies, 2004
Slide 1/53
Practical Object-Oriented Design with UML 2e
Mediator Pattern in Java
● An Example From “Software Design Using Java 2” By Lano, Fiadeiro &
Andrade.
● This reduces the complexity of the objects
and increases flexibility. For example, if rules
connecting that objects need to change
without the objects themselves changing.
©The McGraw-Hill Companies, 2004
Slide 1/54
Practical Object-Oriented Design with UML 2e
Mediator Pattern in Java
● An Example From “Software Design Using Java 2” By Lano, Fiadeiro &
Andrade.
● Aim: to simplify complex connections and
dependencies between a set of objects by
defining Mediator objects which centralize
information about these dependencies.
● Implementation: based on the idea of event
sources and event targets.
©The McGraw-Hill Companies, 2004
Slide 1/55
Practical Object-Oriented Design with UML 2e
Mediator Pattern in Java
● An Example From “Software Design Using Java 2” By Lano, Fiadeiro & Andrade.
● The Mediator is more general than the Observer in
that objects may be both event sources and event
targets. Also the code for updating event targets on
notification of an event is separated out from these
targets.
● The Mediator enhances maintainability and
flexibility because it removes knowledge of
dependencies and the detail of the dependency
management code from collaborating objects and
puts it in the mediator object instead. When the
rules of dependency change, only the mediator
object needs rewriting
©The McGraw-Hill Companies, 2004
Slide 1/56
Practical Object-Oriented Design with UML 2e
Mediator Pattern in Java
● An Example From “Software Design Using Java 2” By Lano, Fiadeiro & Andrade.
● In the following program the first action
ca.credit(600), causes credit of 600 to be
added to the current account, resulting in ca’s
credit listener being activated, and this then trims
as 100 from the current account balance and adds
this to the deposit account. In the second action,
cust.withdraw(550), the withdraw listener of
the customer is activated and removes 500 units
from the current account and 50 from the deposit.
©The McGraw-Hill Companies, 2004
Slide 1/57
Practical Object-Oriented Design with UML 2e
Mediator Pattern in Java
● An Example From “Software Design Using Java 2” By Lano, Fiadeiro & Andrade.
● In the following program the first action
ca.credit(600), causes credit of 600 to be
added to the current account, resulting in ca’s
credit listener being activated, and this then trims
as 100 from the current account balance and adds
this to the deposit account. In the second action,
cust.withdraw(550), the withdraw listener of
the customer is activated and removes 500 units
from the current account and 50 from the deposit.
©The McGraw-Hill Companies, 2004
Slide 1/58
Practical Object-Oriented Design with UML 2e
Mediator Example From “Software Design Using Java
2” By Lano, Fiadeiro & Andrade.
● interface WithdrawListener
● { void withdraw(int ammount); }
● interface CreditListener
● { void credit(int ammount); }
©The McGraw-Hill Companies, 2004
Slide 1/59
Practical Object-Oriented Design with UML 2e
Mediator Example From “Software Design Using Java
2” By Lano, Fiadeiro & Andrade.
class Customer
{
private String name;
private Vector withdrawListeners = new Vector();
public Customer(String nme) {
name = nme;
}
public void addWithdrawListener(WithdrawListener w)
{ withdrawListeners.add(w);}
public void withdraw(int amount) {
for (int i = 0; i < withdrawListeners.size(); i++)
{
WithdrawListener wl = (WithdrawListener) withdrawListeners.get(i);
wl.withdraw(amount); }}}
©The McGraw-Hill Companies, 2004
Slide 1/60
Practical Object-Oriented Design with UML 2e
Mediator Example From “Software Design Using Java
2” By Lano, Fiadeiro & Andrade.
class Customer
{
private String name;
private Vector withdrawListeners = new Vector();
public Customer(String nme) {
name = nme;
}
public void addWithdrawListener(WithdrawListener w)
{ withdrawListeners.add(w);}
public void withdraw(int amount) {
for (int i = 0; i < withdrawListeners.size(); i++)
{
WithdrawListener wl = (WithdrawListener) withdrawListeners.get(i);
wl.withdraw(amount); }
}
}
©The McGraw-Hill Companies, 2004
Slide 1/61
Practical Object-Oriented Design with UML 2e
Mediator Example From “Software Design Using Java
2” By Lano, Fiadeiro & Andrade.
class Account {
private int accountNo; // unique account identifier
private int balance=0;
private Vector creditListeners = new Vector();
public Account (int ac) { accountNo = ac;}
public void addCreditListener(CreditListener cl)
{ creditListeners.add(cl);}
public int getBalance()
{return balance;}
public void credit(int amount)
{ balance += amount;
for (int i = 0; i < creditListeners.size(); i++)
{ CreditListener cl = (CreditListener) creditListeners.get(i);
cl.credit(amount); }}
public void debit(int amount)
{ balance -= amount; } }
©The McGraw-Hill Companies, 2004
Slide 1/62
Practical Object-Oriented Design with UML 2e
Mediator Example From “Software Design Using Java
2” By Lano, Fiadeiro & Andrade.
class CurrentAccount extends Account
{ public CurrentAccount(int ac)
{ super(ac);}
}
class DepositAccount extends Account
{ public DepositAccount(int ac)
{ super(ac);}
}
©The McGraw-Hill Companies, 2004
Slide 1/63
Practical Object-Oriented Design with UML 2e
Mediator Example From “Software Design Using Java
2” By Lano, Fiadeiro & Andrade.
class Mediator implements WithdrawListener, CreditListener {
private CurrentAccount caccount;
private DepositAccount daccount;
public void registerCurrentAccount(CurrentAccount ac)
{ caccount = ac; }
public void registerDepositAccount(DepositAccount ad)
{ daccount = ad; }
©The McGraw-Hill Companies, 2004
Slide 1/64
Practical Object-Oriented Design with UML 2e
Mediator Example From “Software Design Using Java
2” By Lano, Fiadeiro & Andrade.
/* business rule */
public void withdraw(int amount){
int caBal = caccount.getBalance();
int daBal = daccount.getBalance();
if (caBal >= amount)
{ caccount.debit(amount); }
else if (caBal + daBal >= amount)
{caccount.debit(caBal);
daccount.debit(amount-caBal);}
}
©The McGraw-Hill Companies, 2004
Slide 1/65
Practical Object-Oriented Design with UML 2e
Mediator Example From “Software Design Using Java
2” By Lano, Fiadeiro & Andrade.
/* business rule */
public void credit(int amount){
int caBal = caccount.getBalance();
if (caBal > 500)
{ caccount.debit(caBal - 500);
daccount.credit(caBal - 500);
}}
©The McGraw-Hill Companies, 2004
Slide 1/66
Practical Object-Oriented Design with UML 2e
Mediator Example From “Software Design Using Java
2” By Lano, Fiadeiro & Andrade.
public class MediatorTest {
public static void main (String args[]) {
Mediator med = new Mediator();
CurrentAccount ca = new CurrentAccount(1022);
DepositAccount da = new DepositAccount(7565);
Customer cust = new Customer("Felix");
cust.addWithdrawListener(med);
ca.addCreditListener(med);
med.registerCurrentAccount(ca);
med.registerDepositAccount(da);
ca.credit(600);
System.out.println(ca.getBalance());
System.out.println(da.getBalance());
cust.withdraw(550);
System.out.println(ca.getBalance());
©The McGraw-Hill Companies, 2004
System.out.println(da.getBalance()); }}
Slide 1/67
Practical Object-Oriented Design with UML 2e
Patterns
● The use of patterns is essentially the reuse of well established good
ideas. A pattern is a named well understood good solution to a common
problem in context. Patterns describe how objects communicate without
becoming entangled in each other’s data models and methods. Keeping
this separation has always been an objective of good OO programming,
objects should mind their own business, but obviously need the services
of other objects as well. Definition from Gamma, et al., 1993 “Patterns
identify and specify abstractions that are above the level of single
classes and instances, or of components”. Patterns can exist at many
levels from very low level specific solutions to broadly generalized
system issues. Patterns are often described using UML together with a
pattern template A template describes a pattern. Typical template may
contain: Name, Intent, AKA, Motivation, Application, Structure,
Participation, Collaborations, Consequences, Implementation, Sample
Code, Known Uses, Related Patterns. Template not usually enough ned
context and understanding (see Priestley).
©The McGraw-Hill Companies, 2004
Slide 1/68
Practical Object-Oriented Design with UML 2e
Patterns
● Main advantages capture best practice,
reuse, fairly standard way of describing
patterns.
● Disadvantages: advanced topic, learning
design patterns is a long multiple step
process; Acceptance, Recognition,
Internalisation, on the other hand they are
worth learning. Role of experience. More
geared to OO than other computing
paradigms.
©The McGraw-Hill Companies, 2004
Slide 1/69