Title: PRACTICAL
1- PRACTICAL
- OBJECT-ORIENTED
- DESIGN WITH UML
- 2e
Chapter 14 Principles and Patterns
2Principles 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
3Valid 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.
4System 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
5Open 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
6The 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
7Interface 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
8Data 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
9Limitations
- 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)
10Abstract Interface Classes
- An approach based on generalization (not pure
interfaces) - Abstract classes can provide a complete or
partial implementation of a method(s).
11How the Interface Works
- Clients access different concrete suppliers
through the abstract supplier interface - This is enabled by features of the
object-oriented 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
12Dependencies
- The dependency structure indicates that the
client is independent of the concrete suppliers
13Open 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
14No 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
15A 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
16Refactoring the Design
- A better approach is to introduce an abstract
interface class - even if it initially seems unnecessary
17Decoupling Interfaces
- Clients can be protected from interface change by
defining separate interface and implementation
hierarchies - Make the abstract supplier an interface
18Separate Interface Hierarchy
- Extend the interface to add a new operation
- abstract supplier can be extended without
affecting existing clients
19Liskov 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
20Design 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
21Realizing Make a Call
- This interaction looks plausible
- But the associations based on the phone structure
do not support these messages
22Design Based on Interactions
- A better model of the phone is derived from the
interactions in the realization
23Design 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
24Recursive Structures
- Many data structures are recursive, eg
25The Composite Pattern
- Composite defines the essential properties of
this sort of situation
26Discussion 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
27Patterns in UML
- UML documents patterns as parameterized
collaborations
28Documenting Pattern Application
- When applying a pattern you must show what the
its classes correspond to
29The 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
30The State Solution
- A consequence of this pattern is that the state
classes need access to the internal details of
the context class
31The 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
32The Strategy Solution
- The structure is very similar to that of State
- treated as a different pattern because the
problem being solved is different
33Models, 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
34Models, Views and Controllers
35Interactions in MVC
- User input detected by a controller
- The model is notified
- The views are updated
36Document/View Architecture
- Widely used by Microsoft
- A simplification of MVC
- Views combine the functions of MVC views and
controllers
37Document/View Structure
38Document/View Interactions
- Compare this with the MVC interaction
39The 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)
40Observer Structure
41Observer Interactions
- This interaction is simpler because the initial
message is sent straight to the model class
42Parts 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
43Problems
- 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?
44The 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
45Finding Costs with Visitor
- This illustrates Visitor with a single operation
46The 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)
-
47Finding 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()
48Visitor Interactions
49Adding Part Explosions
- Extend the design by defining a visitor hierarchy
50Mediator 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.
51Mediator Pattern
52Mediator Pattern with Java
53Mediator 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.
54Mediator 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.
55Mediator 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.
56Mediator 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
57Mediator 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 cas 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.
58Mediator 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 cas 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.
59Mediator Example From Software Design Using Java
2 By Lano, Fiadeiro Andrade.
- interface WithdrawListener
- void withdraw(int ammount)
- interface CreditListener
- void credit(int ammount)
60Mediator 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 i)
-
- WithdrawListener wl (WithdrawListener)
withdrawListeners.get(i) - wl.withdraw(amount)
61Mediator 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 i)
-
- WithdrawListener wl (WithdrawListener)
withdrawListeners.get(i) - wl.withdraw(amount)
-
62Mediator Example From Software Design Using Java
2 By Lano, Fiadeiro Andrade.
- class Account
- private int accountNo // unique account
identifier - private int balance0
- 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 i)
- CreditListener cl (CreditListener)
creditListeners.get(i) - cl.credit(amount)
- public void debit(int amount)
- balance - amount
63Mediator 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)
64Mediator 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
65Mediator 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)
-
66Mediator 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)
67Mediator 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())
- System.out.println(da.getBalance())
68Patterns
- 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
others 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).
69Patterns
- 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.