Title: Design Patterns
1Design Patterns
2Overview
- The need to manage complexity
- Place of data structures and algorithms
- Class diagrams in UML
- Beyond objects to patterns
- Example pattern
- Reference Gamma et.al. chapter 1
- http//hillside.net/patterns
- http//www.cs.wustl.edu/schmidt/patterns-info.htm
l
3Managing software complexity
- There is a desperate need to be able to generate
complex, reliable software. - increasing functionality
- increasing machine capacity
- decreasing software quality
- Examples of poor software quality?
4How can you manage complexity?
- Software? Filing system? Building a house?
- structure?
- components?
- techniques?
- processes?
- Lets concentrate on structure and see how we can
manage complexity there.
5We tend to learn programming bottom-up
- Start with simple values and variables
- integers, booleans, reals
- assignment, conditional statements, loops
- Work up to data structures
- sets of values in relationship
- commonly occurring abstractions
- arrays, linear lists, stacks, queues
- trees, graphs
- Examine interplay between data structures and
algorithms - choice of data structure affects efficiency of
algorithm
6Data structures and classes
- In object-oriented terms, data structures and
associated algorithms are usually described by
abstract data types and encapsulated in objects
or classes. - e.g. List, Tree, Graph, Trie, etc.
- Get the data structures right and everything
else will follow - How do you get the data structures right?
- How do you get the classes right?
- How do you get a broader view of a system?
Another level of abstraction? - consider classes as components
- What are good ways of combining classes?
- combine classes to give design patterns
7Abstraction given by class diagrams
- Can represent classes as nodes in a graph, with
edges giving the relationships between the
classes - Nodes can indicate state, behaviour (, identity)
of classes - State attributes associated such an object (the
instance variables). - Behaviour operations applicable to such an
object (the instance methods). - Identity unique value that differentiates one
object from another (usually implicit) - Examples
- Bank account
- University professor
8Nodes can indicate more detail
- Note included attributes do not include
references to other objects include these by
associations - Types
- e.g. balance real
- e.g. deposit(amount real) void
- Access control
- public balance real
- protected balance real
- private balance real
9Nodes can indicate more detail
- Identify class variables and methods by
underlining - Annotate special kinds of components with
stereotypes - e.g. constructor BankAccount()
- e.g. interface Graph
10Class relationships
- Classes are related to other classes
- a GraphBase class may implement a Graph interface
- a GraphImp class may use NodeImp and EdgeImp
classes - a SavingsAccount class may extend a BankAccount
class - These relationships are drawn as arcs in the
class diagram
11Edge annotations
- (Central) label indicates significance of
association - context determines which way to read the
association - e.g. an Edge joins two Nodes
- End-point labels indicate roles
- implications for implementation
- Multiplicity indicates number of participants
- e.g. optional 0..1
- e.g. zero or more 0..
- e.g. one or more 1..
Edge
Node
1
2
edge
node
label setLabel(lbl) getLabel()
label setLabel(lbl) getLabel()
joins
12Edge annotations
- Arrow heads indicate navigation direction
- bidirectional navigation
- unidirectional navigation
- implications for implementation
- Style of arrow
- e.g. inherits A inherits B
- e.g. implements A implements B
- e.g. aggregates A aggregates B
- e.g. composite A is a composite of B
13Aggregates vs composites
- Aggregates and composites indicate a special
association - their use is optional
- Aggregates indicate a part-whole relationship
- Composites indicate a part-whole relationship
where the whole strongly owns the parts - Copy/delete the whole ? copy/delete the parts
- E.g. student enrolled in a degree no
aggregation - E.g. degree includes compulsory course
aggregation - not composite courses may belong to multiple
degree - E.g. building consists of 4 floors composite
- floors cannot belong to more than one building
14Specializing BankAccount
- Inheritance and software reuse
- A bank account with an overdraft facility
- A tenured vs contract University teacher
- Reuse state and behaviour
- Fundamental to the provision of
- Graphical User Interfaces.
15Relating BankAccount and Custome
- Objects can use other objects to accomplish their
tasks - A bank account could have an associated customer
- The customer object could be notified about
overdrafts - Reuse state and behaviour
- Maintains encapsulation
16Inheritance vs Composition
- Inheritance has been promoted as the reuse
mechanism - Experience shows that composition is a cleaner
mechanism - Inheritance hierarchies can become overly complex
- Inheritance breaks encapsulation (at least
partially) - Inheritance is a static compile-time mechanism,
while composition can be a dynamic run-time
mechanism (added flexibility may be good or bad) - Implementation of parent will affect that of the
child
17Unified Modeling Language (UML)
- Previous class diagram notation is part of the
Unified Modelling Language (UML) - arose out of other notations OMT, Booch,
Jacobsen - UML also addresses other models
- Use Case diagrams for capturing external
interactions - State diagrams for capturing the internal class
activity - Interaction diagrams for capturing interaction
between classes - Sequence diagrams for capturing more detailed
interaction between classes - Deployment diagrams for relating software to
available hardware - ...
18Beyond objects
- Object-oriented software construction is not
enough - Typical systems have a large number of
objects/classes - Relationships between classes can be very complex
- Becomes unmanageable
- Consider commonly occurring sets of classes
patterns - E.g. contract for house sale speaks in terms of
Vendors, Purchasers, Premises, Chattels, etc. - A set of objects is required for such a contract
19Beyond patterns
- Patterns may not be enough to structure complex
software - You may require a higher level view of the system
- This leads to the topic of software architecture
...
20Example the Adapter (class) pattern
- Consider wanting to use a prebuilt component
which does not match the interface you assumed - very common when you try to reuse software
21Example the Adapter (class) example
- Consider supplying a bank account (as above) in
terms of an account which has a single method for
changes
22Example the Adapter (object) pattern
- Consider wanting to use a prebuilt component
which does not match the interface you assumed - Adaptee is used, not inherited
23Example the Adapter (object) pattern
- Consider needing a bank account (as above) in
terms of an account which has a single method for
changes.
24Where next?
- Describing and classifying patterns
- Creational patterns for more flexible object
creation - Reference Gamma et.al. chapters 3-4
- http//hillside.net/patterns
- http//www.cs.wustl.edu/schmidt/patterns-info.htm
l
25Reminder
- Patterns capture solutions to commonly occurring
problems - Many problems arise in the context of GUIs
- Authors need to identify 3 distinct uses/contexts
before classifying the solution as a pattern - Patterns consist of a number of classes which
interact in a certain way (to solve the problem) - Patterns may or may not be applicable in a given
context - Many patterns introduce extra levels of
indirection - Most problems in Computer Science can be solved
with an extra level of indirection
26Description of patterns
- Name succinct indication of patterns purpose
- Synopsis short description of the pattern (for
experienced users) - Context problem description example problem
- Forces considerations leading to the solution
- Solution describes the general-purpose solution
- Consequences trade-offs and results
- Implementation pitfalls, hints, techniques
- Sample code
- Related patterns similar sorts of situations
27Example description Adapter pattern
- Name Adapter Class, Object Structural
- Synopsis implements an interface known to the
clients via a class which is not known to the
clients - Context the class interfaces derived from the
design of a system may not match the class
interface available in a reusable library. E.g.
BankAccount class with two methods
deposit(amount) and withdraw(amount) to be
adapted to a class Account which has a single
method change(amount) which accepts positive and
negative amounts. - Forces
- You want to use an existing class, and its
interface does not match the one you need - You do not have the option of changing the
interface of the existing class maybe the
source isnt available, or the class is part of a
reusable library
28Example description Adapter pattern
- Solution A class adapter uses multiple
inheritance to adapt one interface to another. An
object adapter relies on object composition - Target defines the domain-specific interface that
Client uses - Client collaborates with objects conforming to
the Target interface - Adaptee defines an existing interface that needs
adapting - Adapter adapts the interface of Adaptee to the
Target interface
29Example the Adapter (class) pattern
- Reuse a prebuilt class which does not match the
interface you assumed - very common when you try to reuse software
30Java-line code for Adapter class pattern
- abstract class Target // Maybe an interface
-
- public abstract ResultType request()
-
-
- class Adaptee // An existing class
-
- public ResultType req()
-
-
-
-
31Java-line code for Adapter class pattern
- class Adaptor extends Target, Adaptee
-
- public ResultType request()
-
- return req() // Use Adaptee version
-
-
- Note that Java does not support multiple
inheritance - the above would be possible in C, Eiffel
- the above would be possible if Target were an
interface, in which case Adaptor would inherit
Adaptee and implement Target
32The Adapter (object) pattern
- Consider wanting to use a prebuilt component
which does not match the interface you assumed
33Java-like code for Adapter object pattern
- Target and Adaptee classes as before
- class Adaptor extends Target // Does not inherit
Adaptee -
- Adaptee adpt new Adaptee()
-
- public ResultType request()
-
- return adpt.req() // Use Adaptee version
-
-
- Note that this works directly in Java
34Example description Adapter pattern
- Consequences Class and object adapters have
different trade-offs. A class adapter - adapts Adaptee to Target by committing to a
concrete Adapter class. As a consequence, a class
adapter wont work when we want to adapt a class
and all its subclasses. - lets Adapter override some of Adaptees
behaviour, since Adapter is a subclass of Adaptee - introduces only one object, and no additional
pointer indirection is needed to get to the
Adaptee.
35Example description Adapter pattern
- Consequences Class and object adapters have
different trade-offs. An object adapter - lets a single Adapter work with many Adaptees,
i.e. the Adaptee itself and all of its subclasses
(if any). The Adapter can also add functionality
to all Adaptees at once. - makes it harder to override Adaptee behaviour. It
will require subclassing Adaptee and making
Adapter refer to the subclass rather than the
Adaptee itself. - Related patterns Facade, Proxy, Strategy
36Classification of patterns
- There are two basic dimensions of classification
- Scope
- application primarily to classes or objects?
- Purpose
- creational for creating (and deleting) objects
- structural for composing classes or objects
- behavioural interaction of classes or objects
37Example classification Adapter pattern
- Adapter is of scope class or object
- Adapter is of purpose structural
38Creational patterns
- These patterns provide alternatives to creation
of objects by using the new function which - fixes the class of object being created
- i.e. lacks flexibility / configurability
- is independent of other calls to new
- i.e. does not relate creation of different kinds
of objects - Suppose we have a situation where a number of
related objects (or products) need to be created - e.g. set of graphical components with similar
look-and-feel - e.g. set of bank accounts with matching audit
provisions - A common problem!
39Abstract factory object creational
- Synopsis Provides a way to create instances of
abstract classes from a matched set of concrete
subclasses - Context Consider building a GUI framework which
should work with multiple windowing systems (e.g.
Windows, Motif, MacOS) and should provide
consistent look-and-feel. - Forces Use the Abstract Factory pattern when
- a system should be independent of how its
products are created, composed and represented - a system should be configured with one of
multiple families of products - a family of related products is designed to be
used together, and you need to enforce this
constraint - you want to provide a class library of products,
and only reveal their interfaces, not their
implementations
40Abstract factory object creational
- Solution Define an abstract factory class which
has methods to generate the different kinds of
products. (For a windowing system this could
generate matched buttons, scroll bars, fields).
The abstract factory is subclassed for a
particular concrete set of products - AbstractFactory declares an interface for
operations that create abstract product objects - ConcreteFactory implements the operations to
create concrete product objects - AbstractProduct declares an interface for a
type of product object - ConcreteProduct implement the AbstractProduct
interface - Client uses only the interfaces declared by
AbstractFactory and AbstractProduct classes
41Abstract factory object creational
42Abstract factory object creational
- Consequences
- It isolates concrete classes
- clients are isolated from implementation classes
- clients manipulate instances through their
abstract interfaces - It makes exchanging product families easy
- It promotes consistency among products
- Supporting new kinds of product is difficult
- the AbstractFactory interface fixes the set of
products that can be created - extending the AbstractFactory interface will
involve changing all of the subclasses - The hierarchy of products is independent of the
client
43Lexi consistent look-and-feel
44Java code for Abstract Factory pattern
- abstract class Product1 // Some kind of object
-
-
-
- abstract class Product2 // Another kind of
object - // - related to Product1
-
-
- abstract class AbstractFactory
-
- public abstract Product1 createProduct1()
- public abstract Product2 createProduct2()
-
-
45Java code for Abstract Factory pattern
- class version1Product1 extends Product1 //
Specific kind - // of Product1
-
-
- class version1Product2 extends Product2 //
Specific kind - // of Product2
-
-
- class version2Product1 extends Product1 //
Another kind - // of Product1
-
-
- class version2Product2 extends Product2 //
Another kind - // of Product2
-
-
46Java code for Abstract Factory pattern
- class version1Factory extends AbstractFactory
- // Factory for version1 products
- public Product1 createProduct1()
-
- return new version1Product1()
-
- public Product2 createProduct2()
-
- return new version1Product1()
-
-
-
- Similarly for a class version2Factory
47Java code for Abstract Factory pattern
- class client
-
- static void main()
-
- AbstractFactory fact new version1Factory()
-
- ... fact.createProduct1() // version1 products
- ... fact.createProduct2()
-
-
-
- With the one line fact new version2Factory(),
you would end up with version2 products
48Creational patterns
- In the abstract factory the family of related
products was independent of the client(s) - A GUI framework needs to generate related
products, but the products depend on the
structure of the client classes - e.g. a word-processor application needs to
generate word-processor documents, and
word-processor documents need to be displayed in
word-processor views - Solution is to define methods in the (generic)
client classes to create (generic) objects - then override these methods in a specific
application
49Sample generic application and documents
50Factory method class creational
- Synopsis Define an interface for creating an
object, but let subclasses decide which class to
instantiate. Factory Method lets a class defer
instantiation to subclasses - Context Example is that of a GUI framework. The
generic Application class will have a method
createDocument to create a generic document. A
specific use of the framework for, say,
word-processing GUI would subclass the generic
Application class and override the createDocument
method to generate word-processing documents. - Forces Use the Factory Method pattern when
- a class cant anticipate the class of objects it
must create - a class wants its subclasses to specify the
objects it creates - the set of classes to be generated may be dynamic
51Factory method class creational
- Solution Use a factory method to create the
instances - Product (e.g. Document) defines the interface
of objects the factory method creates - ConcreteProduct (e.g. MyDocument) implements
the Product interface - Creator (e.g. Application) declares the factory
method which returns an object of type Product
(possibly with a default implementation) may
call the factory method to create a Produce
object - ConcreteCreator (e.g. MyApplication) overrides
the factory method to return an instance of
ConcreteProduct
52Factory method class creational
53Factory method class creational
- Consequences
- It eliminates the need to bind application-specifi
c classes into your code. The code only deals
with the Product interface and therefore can work
with any user-defined ConcreteProduct classes. - A client will have to subclass the Creator class
just to create a particular ConcreteProduct
instance. - Provides hooks for subclasses to provide extended
versions of objects - Connects parallel class hierarchies, e.g.
Application Document vs MyApplication
MyDocument - The set of product classes that can be
instantiated may change dynamically
54Structural patterns
- Reference Gamma et al. Chapter 4.
- These patterns allow you to achieve different
relationships between classes or objects - Adapter is a structural pattern
- Consider a situation where you have some
recursive composition of objects - e.g. consider a document formatting program that
formats characters into lines, lines into
columns, columns into pages - suppose that columns can contain frames which can
contain columns - the recursive structure can get rather
complicated
55Structural patterns
56Composite object structural
- Synopsis Allows you to build complex objects by
recursively composing similar objects in a
treelike manner, representing whole-part
hierarchies - Context In a document-formatting program (such
as described previously), the complex inclusion
relationships can lead to complex code. This is
made worse if you try to handle primitive and
container objects differently. The key to the
pattern is to define an abstract class which
represents both primitive and composite
components - Forces
- you have a complex object that needs to be
decomposed into a part-whole hierarchy - you want to minimise the complexity of the
part-whole hierarchy by minimising the number of
different kinds of child objects
57Composite- object structural
- Solution Provide an abstract superclass for all
objects in the hierarchy and an abstract
superclass for all composites in the hierarchy - AbstractComponent the common superclass for all
objects in the hierarchy - AbstractComposite the common superclass for all
composite objects in the hierarchy. It inherits
from AbstractComponent and has additional methods
to add and remove components - ConcreteComponent specific component in the
hierarchy - ConcreteComposite specific composite in the
hierarchy
58Composite object structural
59Composite object structural
- Consequences
- The tree-like composite object can be treated as
consisting of AbstractComponents (whether they
are simple or composite) - Clients of AbstractComponent can ignore whether
it is actually a composite or not - An operation performed on an AbstractComposite
treated as an AbstractComponent can be delegated
to the component objects - Any AbstractComponent object can be a child of an
AbstractComposite. More restrictive policies can
be enforced. - Related patterns Chain of responsibility
60Composite object structural
61Glyph interface for Lexi
- All graphics, whether simple or composite, will
have a common interface of a Glyph - interface Glyph
- void Draw(Window) // to display itself
- Rect Bounds() // return the bounding rectangle
- Boolean Intersects(Point) // determine if the
point is in the - // bounding rectangle (and the glyph
- // needs to respond to some event)
- void Insert(Glyph, int) // add a component
glyph - void Remove(Glyph) // remove a glyph
- Glyph Child(int) // return a component glyph
- Glyph Parent() // return the parent glyph
-
62Structural patterns
- Consider a situation where you want to control
access to an object - e.g. a distributed system where the application
needs to interact with an object but it should
not need to know whether the object is local or
remote - e.g. a word processor where you do not wish to
open and display a (large) image unless it is
required
63Example- text document with large images
64Proxy object structural
- Synopsis Provide a surrogate or placeholder for
another object to control access to it - Context A proxy object receives method calls
from clients on behalf of another object. The
proxy object does not provide the services
directly but calls the methods of the object.
Proxy is applicable whenever there is a need for
a more versatile or sophisticated reference to an
object than a simple pointer, such as - a remote proxy provides a local representative
for an object in a different address space - a virtual proxy creates expensive objects on
demand - a protection proxy controls access to the
original object - a smart reference is a replacement for a bare
pointer that performs additional actions when an
object is accessed
65Proxy object structural
- Forces
- the service-providing object cannot provide the
service at a convenient time and place - gaining visibility to an object is non-trivial
and you want to hide the complexity - you want to control access to the
service-providing object
66Proxy object structural
- Solution Proxy forwards requests to RealSubject
when appropriate, depending on the kind of proxy - Subject (e.g. Graphic) defines the common
interface for RealSubject and Proxy so that Proxy
can be used anywhere that RealSubject is expected - RealSubject (e.g. Image) defines the real
object that the proxy represents - Proxy (e.g. ImageProxy) maintains a reference
that lets the proxy access the real subject
provides an interface identical to Subjects so
that a proxy can be substituted for the real
subject controls access to the real subject
67Proxy object structural
68Proxt object structural
- Consequences
- The additional level of indirection in accessing
an object can have many uses - a remote proxy can hide the fact that an object
resides in a different address space - a virtual proxy can perform optimisations such as
creating an object on demand - protection proxies and smart references allow
additional housekeeping tasks when an object is
accessed - A Proxy can also be used to defer duplication of
a (large) object until the duplicate is actually
changed (and the copy needs to be generated) - Related patterns Facade, Decorator
69Structural patterns
- Consider a situation where you want to vary the
implementation of an abstraction at run time - e.g. given a fixed GraphBase you may want to vary
the GraphImp at run-time (to suit particular
algorithms) - Consider a situation where you want to allow a
number of related abstractions each with a number
of different implementations - it is then desirable for the abstractions and
implementations to vary independently
70Example variety of windows and systems
71Bridge object structural
- Synopsis Decouple an abstraction from its
implementation so that they can vary
independently - Context You can have hierarchies of windowing
abstractions and hierarchies of windowing
systems. If you combine the two, you will end up
with too many classes. - Forces
- you want to avoid a permanent binding between an
abstraction and its implementation - both the abstractions and the implementations
should be extensible by subclassing - changes in the implementation of an abstraction
should have no impact on clients - you have a proliferation of classes (as in the
example) - you want to share an implementation among
multiple objects
72Bridge object structural
- Solution Abstractions have reference to the
implementation and forward client requests as
required - Abstraction (e.g. Window) defines the
abstractions interface maintains a reference to
an object of type Implementor - RefinedAbstraction (e.g. IconWindow) extends
the interface defined by Abstraction - Implementor (e.g. WindowImp) defines the
interface for the implementation classes. This
interface doesnt need to correspond exactly to
the Abstractions interface (but it may) - ConcreteImplementor (e.g. XWindowImp)
implements the Implementors interface
73Bridge object structural
74Example variety of windows and systems
75Bridge object structural
- Consequences
- Decoupling abstraction and implementation
- an implementation is not bound permanently to a
abstraction - eliminates compile-time dependencies on the
implementation, i.e. can change implementation
class without necessarily recompiling - Improved extensibility
- the Abstraction and Implementation hierarchies
can be extended independently - Hiding implementation details from clients
- e.g. clients dont need to know if
implementations are shared - Related patterns Adapter, Factory method
76Where next?
- Structural patterns for more flexible object
relationships - Decorator
- Behavioral patterns for more flexible object
interaction - Strategy
- Iterator
- Reference, Gamma et.al. chapter 5
- http//hillside.net/patterns
- http//www.cs.wustl.edu/schmidt/patterns-info.htm
l
77Structural patterns
- Sometimes you want to add capabilities/responsibil
ities to an individual object and not to a whole
class - e.g. you may want to display some objects in a
GUI with embellishments like a border or drop
shadow - e.g. you may want to add scroll bars to a
component only when it cannot be fully displayed
in the window - Using inheritance to add the capability means
that all objects will have the additional
properties (e.g. border) - Another approach is to define a class to act as a
filter - it encloses the object to be embellished
- it adds the capability required
- such a filter can be added as required
78Decorator object structural
- Synopsis Add functionality (dynamically) to an
object in a way which is transparent to its
clients - Context In a GUI, you may want to add and
retract embellishments of displayed objects, such
as a border or shading or some highlight. It is
not appropriate to add this to every displayed
object, and further, you may wish to retract the
embellishment without discarding the original
object. - Forces
- You want to extend the functionality of a number
of objects of a given class, but you do not want
to add this to every instance - There is a need to dynamically extend or withdraw
the capabilities of objects
79Decorator object structural
- Solution Define a class to act as a
wrapper/filter for the original object and which
adds the necessary functionality. Such a wrapper
instance can be added or removed at runtime. - Component defines the interface for objects
which can have capabilities added dynamically - ConcreteComponent defines the objects to which
additional capabilities can be attached - Decorator includes the Component interface,
holds a reference to a component - ConcreteDecorator adds the required
capabilities to a Decorator
80Decorator object structural
81Decorator object structural
- Consequences
- Decorator allows for dynamic change in the
capabilities of components, by adding and
removing wrappers - You can mix and match with a number of wrappers
achieving a large number of possible combinations - Flexibility of wrappers makes them more error
prone, e.g. using incompatible wrappers or
getting circular references - Use of decorators reduces the number of classes,
but increases the number of objects (which can
hinder debugging) - The use of decorators makes it difficult to
distinguish objects by their object identities - Related patterns Delegation, Filter, Strategy
82Behavioral patterns
- Consider a system that needs to break a stream of
text into lines. There are many algorithms for
doing this hardwiring a particular algorithm
may be undesirable - clients will be more complex if they include the
algorithm - different algorithms will be appropriate at
different times or in different contexts - it is difficult to add new algorithms
- The solution is to define classes which
encapsulate different line-breaking algorithms - the so-called Strategy pattern
83Strategy object behavoral
- Synopsis Define a family of algorithms,
encapsulate each one, and make them
interchangeable. Strategy lets the algorithm vary
independently from clients that use it - Context In a document editor you may want to
vary the choice of line-breaking strategies,
possibly on-the-fly - Forces Use the Strategy pattern when
- many related classes differ only in their
behavior, in which case the Strategy provides a
way of configuring a class with one of many
behaviors - you need different variants of an algorithm
- an algorithm uses data that clients shouldnt
know about Strategy avoids exposing complex,
algorithm-specific data structures - a class defines multiple alternative behaviors
84Strategy object behavoral
- Solution Encapsulate the algorithm in an object
- Strategy (e.g. Compositor) declares an
interface common to all supported algorithms.
Context uses this interface to call the
algorithms defined by a ConcreteStrategy - ConcreteStrategy (e.g. SimpleCompositor)
implements the algorithm using the Strategy
interface - Context (e.g. Composition) is configured with a
ConcreteStrategy object, and may define an
interface that lets Strategy access its data.
85Structural of strategy pattern
86Example breaking test into lines
- Composition maintains line breaks in displayed
text it uses a Compositor to determine those
line breaks - Compositor determines line breaks
SimpleCompositor for plain text, TexCompositor
for Tex algorithm, etc.
87Strategy object behavoral
- Consequences The Strategy pattern has the
following benefits and drawbacks - families of related algorithms can be defined
using a class hierarchy, thus allowing common
functionality of the algorithms to be factored
out - an alternative to subclassing for providing a
variety of algorithms or behaviours. Subclassing
for modifying behaviour hard-wires the behaviour
into Context. Further, subclassing does not
support dynamic modification of the algorithm - Strategies can eliminate conditional statements
used to select the particular algorithm - Strategies provide a choice of implementations,
depending for example, on different time and
space tradeoffs
88Strategy object behavoral
- Consequences The Strategy pattern has the
following benefits and drawbacks - families of related algorithms can be defined
using a class hierarchy, thus allowing common
functionality of the algorithms to be factored
out - an alternative to subclassing for providing a
variety of algorithms or behaviours. Subclassing
for modifying behaviour hard-wires the behaviour
into Context. Further, subclassing does not
support dynamic modification of the algorithm - Strategies can eliminate conditional statements
used to select the particular algorithm - Strategies provide a choice of implementations,
depending for example, on different time and
space tradeoffs
89Behavioral patterns
- Suppose we have an aggregate data structure and
we wish to access the components without
revealing the structure of the aggregate - e.g. it would be nice to be able to write
something like - for (Iterator i s.iterator() i.hasNext())
- xi.next()
- ...
- e.g. we may have a Set data structure and wish to
examine the elements of the set without revealing
whether they are stored as an array, linked list,
etc. - Solution is to define an Iterator
90Iterator object behavoral
- Synopsis Provide a way to access the elements of
an aggregate object sequentially without exposing
its underlying representation - Context useful for accessing the components of
any data structure, e.g. set, list, tree - Forces Use the Iterator pattern
- to access an aggregate objects contents without
exposing its internal representation - to support multiple traversals of aggregate
objects - to provide a uniform interface for traversing
different aggregate structures (i.e. to support
polymorphic iteration)
91Iterator object behavoral
- Solution
- Iterator defines an interface for accessing and
traversing elements - ConcreteIterator (e.g. PTListIterator)
implements the Iterator interface keeps track of
the current position in the traversal of the
aggregate - Aggregate defines an interface for creating an
Iterator object - ConcreteAggregate (e.g. PTList) implements the
Iterator creation interface to return an instance
of the proper ConcreteIterator
92Example a list iterator
- PTListIterator will need to have a reference to
the list (as indicated by the arrow in the
diagram) - For scoping reasons (in Java), the PTListIterator
will be declared as a public inner class of
PTListonly then will the hidden components of
PTList be accessible to the iterator, cf. friend
in C
93Iterator object behavoral
- Consequences There are 3 important consequences
- It supports variations in the traversal of an
aggregate. Complex data structures may be
traversed in many ways. Different iterators can
be defined for different kinds of traversal - Iterators simplify the Aggregate interface. The
Aggregate does not need to supply extra functions
for iteration, since they are now available in a
separate class. - More than one traversal can be pending on an
aggregate. This is because each iterator keeps
track of its own traversal state. The same effect
would be more difficult if the aggregate stored
the traversal state. - You should query the robustness of the iterator
what happens if the aggregate is changed during
traversal?
94Java code for an iterator
- Code added to the PTSet class
- import java.util.Iterator
- import java.util.Set
- class PTSet implements Set // class definition
-
- public class ElementIterator implements Iterator
- // use the Iterator interface
- int currelt 0
- public boolean hasNext() // part of the
Iterator interface - return currelt lt numElements()
-
- public Object next() // part of the Iterator
interface - Object result null // result will require
coercion - if (hasNext())
- result item(currelt)
- currelt currelt1
-
- return result
-
Use iterator Interface of Java
Generate iterator
95Java code for an interator
- Code added to the client class
- import java.util.Iterator
- class Client // class definition for some
client -
- PTSet s new PTSet() // will process elements
of set s -
- for (Iterator iter s.makeElementIterator()
iter.hasNext() ) // generate the iterator - Element e(Element)iter.next()
-
-
-
96Behavoral patterns
- In a GUI, it is common to support undoable
operations - you choose a graphical component and perform some
operation on it - After that you wish to be able to undo/redo it
- Alternatively, you may wish to have the facility
for queuing operations, or scheduling them for
later execution. - The common way to support this functionality is
with the Command pattern
97Command object behavoral
- Synopsis Encapsulates a request as an object,
thereby letting you parameterise clients with
different requests, queue or log requests, and
support undoable operations - Context support for undoable commands such as
Cut, Copy and Paste in a GUI. - Forces Use the Command pattern when you want to
- parameterise objects by an action to perform.
(Commands are an object-oriented replacement for
callbacks in procedural languages.) - specify, queue, and execute requests at different
times. The Command object can have a lifetime
independent of the original request - support undo, since a Command can store relevant
state for reversing the effects of the command
98Command object behavoral
- Forces (ctd) Use the Command pattern when you
want to - support logging changes so that they can be
reapplied in case of a system crash - structure a system around high-level operations
built on primitive operations. Such a structures
is common in information systems that support
transactions. A transaction encapsulates a set of
changes to data. The Command pattern offers a way
to model transactions.
99Command object behavoral
- Solution The requested operation is encapsulated
in an object with sufficient data to be able to
perform and undo it - Command declares an interface for executing an
operation - ConcreteCommand (e.g. PasteCommand) defines a
binding between a Receiver object and an action
implements commit() by invoking the corresponding
operation(s) on Receiver - Client (e.g. Application) creates a
ConcreteCommand object and sets its Receiver - Invoker (e.g. MenuItem) asks the command to
carry out the request - Receiver (e.g. Document) knows how to perform
the operations associated with carrying out a
request
100Structure of command pattern
101Example GUI commands
102Command object behavoral
- Consequences
- Command decouples the object that invokes the
operation from the one that knows how to perform
it - Commands are first-class objects they can be
manipulated and extended like any other object - You can assemble commands into a composite
command - You can add new commands without changing
existing classes - Related patterns Strategy
103Motivating example for design patterns
- Graphical user interfaces (GUIs) are quite
pervasive - they are complex pieces of software
- their development relies heavily on
object-orientation - Much of the initial motivation for design
patterns arose in the context of GUI development - no coincidence that Gamma developed key GUI
frameworks - there are common problems in the GUI context
- there are standard solutions design patterns
- A GUI case study provides the context for
demonstrating a number of design patterns
104Essential features of a GUI
- Graphical display
- windows
- icons
- menus
- User interaction via pointing device (mouse)
keyboard - select window, navigate within a window
- select object as target for operation
- select operation via menus (or keyboard)
- Event-driven paradigm
- activity is determined by user interaction, not
predetermined by program
105Event-driven paradigm
- Typically GUI style program
- read a graph if the user selects appropriate menu
item - modify display of graph in response to mouse
activity - perform analysis in response to menu item
- produce results if requested
- Structure of program is based around a central
event loop - repeatedly wait for an event and then process it
106Requirements for a document editor
- A significant design problem
- What are the issues to be addressed?
- Can we formulate the big picture?
- How effective are patterns for capturing the
design choices? - Document editor (called Lexi) in the style of
Word, etc. - Documents consist of text graphics
- Manipulate individual or groups of components
- See fig 2.1 (Gamma et al) for sample screen image
- Want flexibility in many areas
- structure, algorithms, interface
107Design issues
- Document structure
- lexible composition of document components
- Formatting
- flexible, configurable formatting policies
- Embellishing the user interface
- scroll bars, borders, drop shadows, etc.
- Multiple look-and-feel standards
- cant be hard-wired into the application
- Multiple windowing systems for portability
- User operations which are undoable
- Spell checking and hyphenation
- wont be considered
108Document structure
- A document consists of graphical components such
as characters, lines, polygons, other shapes - The author will view the document as groups of
components rows, columns, figures, tables, etc. - Lexi should allow the author to manipulate these
groups directly - The internal document structure should support
- maintaining the documents physical structure
- generating and presenting the document visually
- mapping positions on the display to document
components (in response to mouse activity)
109Document structure
- Proposal is to have a recursive structure for
graphical components
110Document structure
- Internal structure corresponding to previous
slide will be tree-structured
111Formatting strategies
- Variety of issues could be addressed
- e.g. how to break up the components into lines
- what are the formatting policies?
- can they be configured on demand?
- Want to support a variety of strategies
independent of the document structure
112Embellishing the user interface
- Want to support scroll bars, borders, etc.
- Want to be able to do this uniformly and flexibly
- vary these as the user interface evolves
- even add and remove them on the fly
- therefore cant have a fixed inheritance
structure - Set up a structure for transparent enclosures
(like a filter) - each enclosure has one component
- drawing interface is the same as for the
component - clients dont know if they are dealing with the
component or the enclosure
113Multiple look-and-feel standards
- Look-and-feel is determined by a family of GUI
components - buttons, scroll bars, pop-up menus, etc.
- called widgets
- Need to be able to generate consistent sets of
widgets - suit a variety of styles, e.g. Motif, Windows,
MacOS,
114Multiple windowing systems
- Want to support multiple window systems for
portability - these vary in the level of functionality
- should we define an abstract windowing system and
then inherit it and override it to satisfy
specific cases? - support the minimum functionality? maximum?
- Simpler to define a windowing system that suits
our needs - allow this to have a variety of implementations
- each implementation decides how to implement the
required operations
115Undoable operations
- User can request operations from different
contexts - menu selection
- mouse operation
- palette
- Request need to encapsulate relevant state
information so that they can be undone
116GUI frameworks
- Even with object orientation, developing a GUI is
hard work - learning curves of 18 months used to be quoted
- Java APIs make it a lot easier
- Significant breakthrough came with GUI frameworks
- A framework is a set of cooperating classes that
make up a reusable design for a specific class of
software - It is a skeleton application which can be refined
by inheritance - There are frameworks for GUIs, compiler
construction, financial modelling
117GUI frameworks
- A GUI framework will include
- generic application which will include the
central event loop - central event loop will distribute events to
relevant graphical components - generic documents file with contents displayed
in a window - generic windows with title bar, close box, resize
control, scroll bar - generic dialog windows with the ability to
display check boxes, radio controls, buttons,
etc. - configurable menu manipulation
118Generic application
- The Generic Application is typically encoded in a
class called Application - this class is subclassed for a specific
application - The Application class typically
- includes the central event loop which is never
modifiable - is instantiated once for a given run of the
application - may handle multiple document types
- has method(s) to generate documents
- has method(s) to setup and respond to appropriate
menus
119Generic document
- The Generic Document is typically encoded in a
class called Document - this class is subclassed for different specific
documents - The Document class typically
- is instantiated once per document to be processed
- has methods for fetching and storing the document
as a file - has method(s) to display the document contents
- has method(s) to setup and respond to appropriate
menus
120Generic view
- The Generic View is typically encoded in a class
called View - this class is subclassed for different specific
graphical components - The View class typically
- corresponds to an arbitrarily large drawing
surface - contains functionality to render and print the
component - contains functionality to maintain the current
selection - supports various possible representations of the
same data, e.g. spreadsheet, graph, etc. - has method(s) to respond to mouse events
121Generic window
- The Generic Window is typically encoded in a
class called Window - this class is subclassed for different operating
systems - The Window class typically
- implements window-related methods like moving,
resizing, closing - contains methods to optimise screen updating
- may contain components to clip the display
- Note that a View is a logical entity which is
displayed in the physical entity of a Window
122Generic classes and relationships
- Application has multiple documents
- Document has multiple views
- View is displayed in a physical region
- Window contains multiple regions
123(No Transcript)