The document discusses software design patterns and how they can help address common problems that arise during design. It describes three main categories of patterns - creational, structural, and behavioral - and provides examples of specific patterns like Singleton, Factory, Adapter, and Bridge. The key benefits of design patterns are that they provide proven, reusable solutions to general problems and help create flexible, modular designs that can more easily adapt to changes.
3. The Pattern Name
The Problem it solves
The Solution it provides
The Consequences (good and bad) of using it
3
4. 4
CHANGES…
Patterns should be able to deal with changes.
Changes can come from many different sources:
- New vendor
- New Technology
- New views
-New complexity
of the application domain.
- Errors
5. There are 3 types of pattern …
Creational: address problems of creating an object
in a flexible way. Separate creation, from
operation/use.
Structural: address problems of using O-O
constructs like inheritance to organize classes and
objects
Behavioral: address problems of assigning
responsibilities to classes. Suggest both static
relationships and patterns of communication
(use cases)
6. A modifiable design enables
• An iterative and incremental development cycle,
which allows
Concurrent (aka simultaneous) development
Risk management
Flexibility to change
• The software developer to minimize the
introduction of new problems when fixing old
ones.
• The software developer to deliver more
functionality after initial delivery.
6
7. Low coupling and high cohesion
Clear dependencies between classes
Explicit assumptions.
How do design patterns help?
They are generalized from existing, i.e. proven,
systems.
They provide a shared vocabulary to designers.
They provide examples of modifiable designs.
They use, principally,
Abstract classes
Delegation & inheritance
7
10. Name: Singleton
Problem:
How can we guarantee that one and only one
instance of a class can be created?
Context: In some applications it is important
to have exactly one instance of a class, e.g. sales of
one company.
11. Forces: Can make an object globally accessible as a
global variable, but this violates encapsulation.
Could use class (static) operations and attributes, but
polymorphic redefinition is not always possible.
Solution:
Create a class with a class operation getInstance().
When class is first accessed, this creates relevant
object instance and returns object identity to client.
On subsequent calls of getInstance(), no new
instance is created, but identity of existing object is
returned.
12. Singleton
-uniqueInstance
-singletonData
+getInstance( )
+getSingletonData( )
+singletonOperation( )
-Singleton( )
Object identifier for singleton
instance, class scope or static
Returns object identifier for
unique instance, class-scope
or static
Private constructor only accessible
via getInstance()
getInstance( ) {
if ( uniqueInstance == null )
{ uniqueInstance = new Singleton( ) }
return uniqueInstance
}
14. To specify a class has only one instance, we
make it inherit from Singleton.
+ controlled access to single object instance
through Singleton encapsulation
+ Can tailor for any finite number of instances
+ namespace not extended by global variables
- access requires additional message passing
- Pattern limits flexibility, significant redesign if
singleton class later gets many instances
16. Name: Façade
Problem:
How can we access a large number of classes
with a complex internal interaction in a simple
but safe way?
Solution: Introduce a dedicated interface class
that simplifies the view of the class collection.
17. Provides a unified interface to a set of objects in a
subsystem.
A façade defines a higher-level interface that makes the
subsystem easier to use (i.e. it abstracts out all the
“messy” details)
Façades allow us to provide a closed architecture.
17
Bad!
Good!
23. 23
Example – Home Theater
Lots of classes
and interactions,
plus many interfaces.
24. Clients communicate with the subsystem by sending
requests to Façade which forwards them to the
appropriate subsystem object(s).
Although subsystem objects perform actual work,
Façade may have to translate its interface to subsystem
interfaces.
Clients that use the Façade don’t have to access its
subsystem objects directly.
25. Usually only one Façade object is required. Thus a
Façade object is often a singleton.
Factory pattern can be used with Façade to provide an
interface for creating subsystem objects in a subsystem
independent way.
Factory can also be used as an alternative to Façade to
hide platform-specific classes.
Mediator pattern is similar to Façade in abstracting
functionality of classes.
26. Name: (Abstract) Factory
Problem: Provide an interface for creating
families of related or dependent objects
without specifying their concrete classes.
Control instantiation
Singleton is a special case of Factory
where
only one object can be created.
28. Normally, a single instance of a
ConcreteFactory class is created at
runtime.
This creates product objects having a
particular implementation.
To create different product objects, clients
should use a different concrete factory.
AbstractFactory defers creation of
product objects to its ConcreteFactory
subclasses.
30. E.g. create objects of different types
We can order a Car and get an
Aston Martin, MG, Jaguar etc
We don’t know which factory builds the
car, just that they implement CarFactory.
Owner has created the actual factory
instance.
31. // we have a reference to owner
CarFactory aFactory = owner.makefactory();
Car myCar =aFactory.makeCar(“AstonMartin”);
class BritishFactory implements CarFactory{
public Car makeCar(String b) throws Exception {
if(b.equals(“AstonMartin”)) return new
AstonMartin();
else if (..) return ..;
else throw new Exception(b + “doesn’t
exist”);
}
}
32. Class AstonMartin extends Car {}
Class Jaguar extends Car {}
Interface CarFactory {
Public Car makeCar(String b) throws Exception;
}
34. Abstract Factory classes are often
implemented with the Factory Method
pattern.
Can also be implemented using the
Prototype pattern.
A concrete factory is often a Singleton.
Comments
35. 35
Pattern: Adapter
Suppose a client objects expect a certain interface to be
provided by called object.
However, the interface of the called object differs from
what the clients expect, and cannot be changed.
How may this situation be improved, i.e. how may the
interface satisfy the clients?
37. Transforms the interface of the target class into another
interface that the client classes expect.
Adapter lets classes work together that could not
otherwise because of incompatible interfaces.
Used to provide a new interface to existing legacy (i.e.
old) software components (aka interface engineering,
re-engineering).
Adapter also known as a wrapper
37
38. 38
Adapter Patten
Context:
1. Want to use an existing class without modifying it – call it the
“legacy” class
2. But context in which you want to use the legacy class requires
conformance to a target (i.e. new) interface that is different from
that which the legacy provides.
3. However, the target interface and legacy interface are
conceptually related.
Solution:
1. Define an adapter class that implements the target interface.
2. The adapter class holds a reference (delegates) to the legacy
class.
It translates (new) target requests (or method calls) from client
classes to (old) legacy requests (or method calls).
39. 39
Participants of the Adapter Pattern
• Target: Defines the application-specific interface that
clients use.
• Client: Collaborates with objects conforming to the
target interface.
• Legacy: Defines an existing interface that needs
adapting.
• Adapter: Adapts the interface of the legacy class to the
target interface.
40. Bind an Adapter class with the Legacy class
The Adapter class implements the ClientInterface expected by
the client. It then delegates requests from the client to the Legacy
class and performs any necessary conversion.
ClientInterface could be a Java/C# interface, or an abstract
class
40
Client
Target
ClientInterface
Request()
Legacy
ExistingRequest()
Adapter
Request()
Legacy class
delegationinheritance
41. 41
Interface inheritance is use to specify the interface of the
Adapter class – and then delegation is used to reference
the Legacy class
Legacy class
supporting old
interface
Class supporting new
interface
Inheritance
Delegation
42. 42
Example
Turkeys do not quack, they
gobble. Turkeys can fly but for
only short distances.
How can we adapt the Turkey class to behave like a
Duck class?
43. 43
duck quack becomes turkey gobble
duck fly becomes five
times turkey fly
Adapt the Turkey class to have the same interface as Duck.
i.e. have methods quack() and fly()
44. 44
Pattern: Bridge
Client objects expect a constant interface to be provided
by some called object.
However, the actual implementation of the interface may
vary – there may be lots of different implementations,
depending on the circumstances.
How may this situation be satisfied?
45. Use a Bridge pattern to decouple an
abstraction from its implementation
so that both can vary independently.
Also known as “handle/body” pattern
Allows different implementations of an interface
to be decided upon dynamically.
45
46. 46
Problem
- Want to decouple an abstraction (i.e. class interface) from its
implementation, allowing them to vary separately.
Context
- Want to change implementation details at run-time without impact to
clients classes.
Solution
- Use delegation from an interface class to an implementation class.
Consequences
- Can change (or add) interface without re-implementing.
- Can change implementation, but not impact interface for clients.
48. 48
Example
Supporting multiple Database Vendors with a Bridge
LeagueStoreImplementorLeagueStore
implements
XML Store
Implementor
SQL Server Store
Implementor
JDBC Store
Implementor
Arena
LeagueStore is the interface class to the pattern
Abstract interface
provides common
interface
49. The bridge pattern is used to provide multiple
implementations under the same interface.
Decouples an interface from the implementation so that
implementation can be substituted, possibly at runtime.
Example: Interface to a component that is incomplete,
not yet known, or unavailable during testing
49
50. 50
Consider problem of incrementally developing, testing
and integrating subsystems realized by different project
teams.
Subsystems may be completed at different times,
delaying the integration of all subsystems until the last
one has been completed.
To avoid delay, projects often use a stub
implementations in place of a specific subsystem so
that the integration tests can start even before the
subsystems are completed.
52. Similarities:
Both are used to hide the details of the underlying
implementation.
Difference:
The adapter pattern is geared towards making
unrelated components work together
Applied to systems after they are designed (reengineering,
interface engineering).
A bridge, on the other hand, is used up-front in a
design to let abstractions and implementations vary
independently.
Engineering of an “extensible system”.
New components can be added to the system, even if these
are not known at analysis or system design time.
52