Design Patterns: From Analysis To Implementation By: Et Bjectives
Design Patterns: From Analysis To Implementation By: Et Bjectives
Design Patterns: From Analysis To Implementation By: Et Bjectives
by
e
N
t
BJECTIVES
This is an excerpt from the manuals for
Design Patterns Explained: A New Perspective for Object-Oriented Design
Not all of the Gang of Four design patterns are included because not all of them are covered in
the course. Furthermore, Alan Shalloway uses a variation on the classification of the GoF
patterns. This is a work in progress. Updates will be announced through our e-zine. You can
subscribe to this by sending a message to [email protected] and putting subscribe in
the subject.
Contents:
Abstract Factory Façade Chain of Responsibility
Builder Proxy – Virtual Iterator
Factory Method Decorator Mediator
Prototype Proxy – adding function Memento
Singleton State Observer
Adapter Strategy Proxy - accessibility
Bridge Template Method Model-View-Controller
Composite Visitor
Abstract Indicators in analysis: Different cases exist that require different implementations of common rules.
factory
Indicators in design: Many polymorphic structures exist that are used in pre-defined combinations. These
combinations are defined by there being particular cases to implement or different needs of client objects.
Indication pattern is not being used when it should be: A variable is used in several places to determine which object
to instantiate.
Relationships involved: The Abstract Factory object is responsible for coordinating the family of objects that the client
object needs. The client object has the responsibility for using the objects.
Builder Indicators in analysis: Several different kinds of complex objects can be built with the same overall build process, but
where there is variation in the individual construction steps.
Indicators in design: You want to hide the implementation of instantiating complex object, or you want to bring
together all of the rules for instantiating complex objects.
Factory Indicators in analysis: There are different commonalities whose implementations are coordinated with each other.
Method
Indicators in design: A class needs to instantiate a derivation of another class, but doesn’t know which one. Factory
method allows a derived class to make this decision.
Field notes: The Factory method is often used with frameworks. It is also used when the different implementations of
one class hierarchy requires a specific implementation of another class hierarchy. Note that a factory method pattern is
not simply a method that serves as a factory. The pattern specifically involves the case where the factory is varied
polymorphically.
Singleton Indicators in analysis: There exists only one entity of something in the problem domain that is used by several
different things.
Indicators in design: Several different client objects need to refer to the same thing and we want to make sure we don’t
have more than one of them. You only want to have one of an object but there is no higher object controlling the
instantiation of the object in questions.
Field notes: You can get much the same function as Singletons with static methods. Therefore, the Singleton
should be used only when statics don’t work well. This occurs when you need to control when the class is
instantiated (that is, static members are allocated). Another case is if you want to use polymorphism on the
Singleton. Also, where an object is implementing an interface established by a framework, and an instance
is expected, the Singleton can fulfill the requirement where static methods would not.
ConcreteBuilder1 ConcreteBuilder2
+ buildStep1() + buildStep1()
+ buildStep2() + buildStep2()
+ getObject() + getObject()
ConcretePrototype1 ConcretePrototype2
+ clone() + clone()
Add a static member to the class that refers to the PSEUDO CODE Singleton
first instantiation of this object (initially it is null). (if C++, _instance should be pointer)
Then, add a static method that instantiates this
class Singleton {
class if this member is null (and sets this
public static Singleton Instance();
member’s value) and then returns the value of this protected Singleton();
member. Finally, set the constructor to protected private static _instance= null;
or private so no one can directly instantiate this
class and bypass this mechanism. Singleton Instance () {
if _instance== null)
_instance= new Singleton;
return _instance
}
}
Adapter Indicators in analysis: Normally don’t worry about interfaces here, so don’t usually think about it. However, if you
know some existing code is going to be incorporated into your system, it is likely that an adapter will be needed since
it is unlikely this pre-existing code will have the correct interface.
Indicator in design: Something has the right stuff but the wrong interface. Typically used when you have to make
something that’s a derivative of an abstract class we are defining or already have.
Field notes: The adapter pattern allows you to defer concern about what the interfaces of your pre-existing objects
look like since you can easily change them.
Bridge Indicators in analysis: There are a set of related objects using another set of objects. This second set represents an
implementation of the first set.
Indicators in design:
There is a set of derivations that use a common set of objects to get implemented.
Indication pattern is not being used when it should be: There is a class hierarchy that has redundancy in it. The
redundancy is in the way these objects use another set of object. Also, if a new case is added to this hierarchy or to the
classes being used, that will result in multiple classes being added.
Relationships involved: The using classes (the GoF’s “Abstraction”) use the used classes (the GoF’s
“Implementation”) in different ways but don’t want to know which implementor is present.
Field notes:
Although the implementer to use can vary from instance to instance, typically only one implementer is used for the life
of the using object. This means we usually select the implementer at construction time, either passing it into the
constructor or having the constructor decide which implementer should be used.
Composite Indicators in analysis: There are single things and groups of things that you want to treat the same way. The groups
of things are made up of other groups and of single things (i.e., they are hierarchically related).
Indicators in design: Some objects are comprised of collections of other objects, yet we want to handle all of these
objects in the same way.
Indication pattern is not being used when it should be: The code is distinguishing between whether a single object
is present or a collection of objects is present.
Variation encapsulated: Whether an item is a single entity or whether it is composed of several sub-components.
Field notes: Whether or not to expose an interface that would allow the client to navigate the composite is a decision
that must be considered. The ideal composite would hide its structure, and thus the navigation would not be supported,
but specifics in the problem domain often do not allow this.
Façade Indicators in analysis: A complex system will be used which will likely not be utilized to its full extent.
Indicators in design: Reference to an existing system is made in similar ways. That is, you see combinations of calls
to a system repeated over and over again.
Indication pattern is not being used when it should be: Many people on a team have to learn a new system although
each person is only using a small aspect of it.
Field notes: Not usually used for encapsulating variation, but different facades derived from the same abstract class
can encapsulate different sub-systems. This is called an encapsulating façade. The encapsulating facade can have
many positive side-effects, including support for demonstration/limited function versions of an application.
Proxy – Indicators in analysis and design: Performance issues (speed or memory) can be foreseen because of the cost of
virtual having objects around before they are actually used.
Indication pattern is not being used when it should be: Objects are being instantiated before they are actually used
and the extent of this is causing performance problems.
Variation encapsulated: Although each proxy contains only one new function or way of connecting to the proxy
object, this function can be changed (statically) in the future without affecting those objects that use the proxy.
Field notes: This pattern often comes up to solve scalability issues or performance issues that arise after a
system is working.
Adapter ExistingClass
+ operation() + itsOperation()
operation:
existingclass->itsOperation
Concrete1 Concrete2
ImpA ImpB
+ opImp1() + opImp1()
operation() { operation() { + opImp2() + opImp2()
imp.opImp1() imp.opImp2()
} }
realsubject->operation()
Decorator Indicators in analysis: There is some action that is always done, there are other actions that may need to be done.
Indicators in design: 1) There is a collection of actions; 2) These actions can be added in any combination to an
existing function; 3) You don’t want to change the code that is using the decorated function.
Indication pattern is not being used when it should be: There are switches that determine if some optional function
should be called before some existing function.
Variation Encapsulated: The functionality to be added before or after an existing function.
Field notes: This pattern is used extensively in the JDK and .NET for I/O.
Proxy – Indicators in design: We need some particular action to occur before some object we already have is called.
adding Indication pattern is not being used when it should be: We precede a function with the same code every time it is
used. Or, we add a switch to an object so it sometimes does some pre-processing and sometimes doesn’t.
function Variation encapsulated: Although each proxy contains only one new function or way of connecting to the proxy
object, this function can be changed (statically) in the future without affecting those objects that use the proxy.
Field notes: Proxies are useful to encapsulate a special function that is sometimes used prior to calling an existing
object.
State Indicators in analysis and design: We have behaviors that change, depending upon the state we are in.
Indication pattern is not being used when it should be: The code keeps track of the mode the system is in. Each
time an event is handled, a switch determines which code to execute (based on the mode the system is in). The rules
for transitioning between the patterns may also be complex.
Field notes:
We define our classes by looking at the following questions:
1. What are our states?
2. What are the events we must handle?
3. How do we handle the transitions between states?
Template Indicators in analysis: There are different procedures that are followed that are essentially the same, except that each
step does things differently.
Indicators in design: You have a consistent set of steps to follow but individual steps may have different
implementations.
Indication pattern is not being used when it should be: Different classes implement essentially the same process
flow.
Variation encapsulated: Different steps in a similar procedure.
Field notes: The template pattern is most useful when it is used to abstract out a common flow between two similar
processes.
Visitor Indicators in analysis and design: You have a reasonably stable set of classes for which you need to add new
functions. You can add tasks to be performed on this set without having to change it.
Variation encapsulated: A set of tasks to run against a set of derivations.
Field notes: This is a useful pattern for writing sets of tests that you can run when needed. The potential for change in
the class structure being visited must be considered – Visitor has maintenance issues when the visited classes change.
Adding Visitors in the future, on the other hand, tends to be quite easy.
NOTE: The Decorator and Proxy patterns are classified as Structural patterns by the GoF. Since they both add functionality, however, instead of simply
combining existing pieces, I believe they are more behavioral in nature. I have also reclassified several Behavioral patterns as Decoupling patterns (a new
classification of mine, seen later in this section). That is because those patterns moved are more about decoupling than about managing new behavior.
Set up an abstract class that represents both the original Client Component Decorator
class and the new functions to be added. Have each + operation()
1
contain a handle to an object of this type (in reality, of a
derived type). In our decorators, perform the additional
function and then call the contained object’s operation ConcreteComponent Decorator 0..1
The Client refers to the proxy object instead of an object A bstrac t Proxy –
Client
from the original class. The proxy object creates the to prox y
adding
+ op erat ion ()
RealSubject when it is created. Requests come to the
Proxy, which does its initial function (possibly), passes function
the request (possibly) to the RealSubject and then does
(possibly) some post processing. P rox y RealS ubjec t
+ operation() + operation()
Have the class that uses the algorithm contain an abstract Strategy
Client
class that has an abstract method specifying how to call
the algorithm. Each derived class implements the Context Strategy
algorithm as needed. + request(Strategy) + algorithm()
StrategyA StrategyB
+ algorithm() + algorithm()
Make an abstract class that represents the tasks to be AbstractTask Client Structure Visitor
performed. Add a method to this class for each concrete + visitElTypeA()
class you started with (your original entities). Add a + visitElTypeB()
method to the classes that you are working on to call the Element
appropriate method in this task class, giving a reference TaskA TaskB + accept(task)
to itself to this method. + visitElTypeA(typeA) + visitElTypeA(typeA)
+ visitElTypeB(typeB) + visitElTypeB(typeB)
ElementTypeA ElementTypeB
+ accept(task) + accept(task)
accept: accept:
task->visitTypeA(this) task->visitTypeB(this)
Chain of Indicators in analysis: We have the several actions that may be done by different things.
responsi- Indicators in design: We have several potential candidates to do a function. However, we don’t want the client object
to know which of these objects will actually do it.
bility Field notes: This pattern can be used to chain potential candidates to perform an action together. A variation of Chain
of Responsibility is to not stop when one object performs its function but to allow each object to do its action.
Factories are useful when chains have dependencies and business rules that specific a particular order for the objects in
the chain.
Iterator Indicators in analysis and design: We have a collection of things but aren’t clear what the right type of collection to
use is.
You want to hide the structure of a collection. Alternatively, you need to have variations in the way a collection is
traversed.
Indication pattern is not being used when it should be: Changing the underlying structure of a collection (say from
a vector to a composite) will affect the way the collection is iterated over.
Variations encapsulated: Type of collection used.
Field notes: The Iterator pattern enables us to defer a decision on which type of collection structure to use.
Mediator Indicators in analysis and design: Many objects need to communicate with many other objects yet this
communication cannot be handled with the observer pattern.
Indication pattern is not being used when it should be: The system is tightly coupled due to inter-object
communication requirements.
Field notes: When several objects are highly coupled in the way they interact, yet this set of rules can be encapsulated
in one place.
Memento Indicators in analysis and design: The state of an object needs to be remembered so we can go back to it (e.g., undo
an action).
Indication pattern is not being used when it should be: The internal state of an object is exposed to another object.
Or, copies of an object are being made to remember the object’s state, yet this object contains much information that is
not state dependent. This means the object is larger than it needs to be or contains an open connection that doesn’t
need to be remembered.
Field notes: This pattern is useful only when making copies of the object whose state is being remembered would be
inefficient.
Observer Indicators in analysis and design: Different things (objects) that need to know when an event has occurred. This list
of objects may vary from time to time or from case to case.
Indication pattern is not being used when it should be: When a new object needs to be notified of an event
occurring the programmer has to change the object that detects the event.
Variation encapsulated: The list of objects that need to know about an event occurring.
Field notes: This pattern is used extensively in the JFC for event handling and is supported with the Observable class
and Observer interface. Also note that C# multicast delegates are essentially implementations of the Observer pattern.
Essence of pattern: 1) there is a changing list of observers, 2) all observers have the same interface, 3) it is the
observers responsibility to register it the event they are ‘observing’
Proxy – Indicators in analysis and design: Are any of the things we work with remote (i.e., on other machines)? An existing
access- object needs to use an object on another machine and doesn’t want to have to worry about making the connection (or
even know about the remote connection).
ability Indication pattern is not being used when it should be: The use of an object and the set-up of the connection to the
object are found together in more than one place.
Variation encapsulated: Although each proxy contains only one new function or way of connecting to the proxy
object, this function can be changed (statically) in the future without affecting those objects that use the proxy.
Field notes: The Proxy is a useful pattern to use when it is possible a remote connection will be needed in
the future. In this case, only the Proxy object need be changed - not the object actually being used.
Define abstract classes for both collections and iterators. Have Collection Iterator Iterator
each derived collection include a method which instantiates the + createIterator() Client + first()
appropriate iterator. The iterator must be able to request the + append() + next()
+ remove() + currentItem()
required information from the collection in order to traverse it
appropriately.
Vector IteratorVector
List IteratorList
Define a central class that acts as a message routing service to aColleague Mediator
all other classes. aColleague
aMediator
aColleague aColleague
Define a new class that can remember the internal state of Caretaker Memento
another object. The Caretaker controls when to create these,
but the Originator will actually use them when it restores its Originator
The Proxy pattern has a new object (the Proxy) stand in place Proxy –
Client Abstract
of another, already existing object (the Real Subject). The to proxy
access-
+ operation()
proxy encapsulates any rules required for access to the real
subject. The proxy object and the real subject object must ability
have the same interface so that the Client does not need to
know a proxy is being used. Requests made by the Client to Proxy_Remote RealSubject
the proxy are passed through to the Real Subject with the + operation() + operation()
proxy doing any necessary processing to make the remote
connection. realsubject->operation()
Mo del
View ConcreteObservers
- CoreData
- SetOfObservers - my Model
- my Cont roller
+ attach(Observer) get
attac
data
h
+ detach(Observer) + initializ e(Model)
+ notify() + makeController()
+ getData() + ac tivate()
+ display() display Controller
+ update ()
- myModel
- myView
service
+ initialize(Model, View)
there is no concrete subject in attach + handleEvent()
this exam ple + update()
The Model-View-Controller (MVC) is primarily used when building GUIs. However, it can be used
anytime you have an interactive type system. It is used to de-couple your data, your presentation of the
data and the logic for handling the events from each other.
The Use the Analysis matrix to collect variation between the different cases you have to deal with. Do not try
Analysis to make designs from it while you are collecting it. However, the consistencies and inconsistencies
Matrix between the cases will give you clues. Remember, we will implement the rows as Strategies, Proxies,
Decorators, Bridges, etc. We will implement the columns with the Abstract Factory.
Case 1 Case 2 Case 3 Case 4
one thing that These are the concrete implementations for the ways to whatever is
is varying varying that is listed on the left.
another thing These are the concrete implementations for the ways to whatever is
that varies varying that is listed on the left.
still another These are the concrete implementations for the ways to whatever is
thing that varying that is listed on the left.
varies
… …
varies
still another thing
These imple-
These imple-
These imple-
These imple-
that varies
…
Are you concerned with interfaces, either changing, simplifying or handling disparate type objects in the same way?
Adapter – do we have the right stuff but the wrong interface? (used to fit classes into patterns as well)
Composite – do we have units and groups and want to treat them the same way
Façade – do we want to simplify our interfaces?
Proxy – do we want to incorporate a rule to access something without affecting any other class?
Remember the relationship between commonality/variability analysis, the conceptual, specification, implementation
perspectives and how these are implemented in object-oriented languages.
by looking at what
Commonality Conceptual Abstract
these objects must do
analysis perspective class
(conceptual perspective)
Operations we determine how to
call them (specification
perspective)
Specification
perspective Concrete Concrete
class class
Operations Operations
Variability Implementation
When implementing these classes, ensure that
analysis perspective
the API provides sufficient information to
enable proper implementation and decoupling
N
t
BJECTIVES
A Better Way to Do Staff Supplementation
All of our trainers are available for part-time consulting. Because they can provide mentoring to other team members as well as perform
development duties, their part-time contribution can impact a team as much as most full-time contractors. On long-term contracts, they can
also teach any of Net Objectives’ courses informally over the term of the contract at contracting rates. This both lowers your overall cost
and increases knowledge transfer.
Quality Training
Object-Oriented Analysis and Design Use Cases On-Site Courses!
Design Patterns for Beginners and Experts
C#, Java, C++ and VB.NET Object-Oriented Programming Instructor Led /
Refactoring, Unit Testing, Test-Driven Development Web-Based Training
Extreme Programming, Agile Development, RUP for Languages
_______________________________________________________________________________________________________________________________________________________________________________________________________________
"If I were tasked with bringing in an “Two things in life are certain: death and taxes” – Ben Franklin
outside design course, Net
Objectives’ would be on the top of my “In the information age, three things in life are certain – death,
list" - John Terrell, Microsoft taxes, and requirements will change” – Alan Shalloway
Writing Effective Use Cases – Instructor Certified by Alistair Cockburn
Capturing functional requirements with Use Cases is a software development best practice. This two-day course provides theory and
practice in writing use cases, an understanding of how use cases fit into software development, and a variety of optional topics. The course
is largely based on Alistair Cockburn's book "Writing Effective Use Cases" - winner of the Jolt Productivity Award for 2001. As a
certified member of Cockburn and Associates, we are one of the few companies authorized to teach it.
Agile Development Best Practices
In simple terms, an Agile Project is one that is predicated on making sure it is always doing the right thing, not merely following a plan that
has since gone out of date. The cornerstone of this approach is getting and adapting to feedback as the project progresses. Most projects
can't do this, so they fall further behind and either fail or provide inferior products. Changes are of many types, but the most common (and
important) changes are to the system's requirements. This course analyzes what it means to be an agile project, and provides a number of
best practices that provide and/or enhance agility. Different agile practices (including RUP, XP and Scrum) are discussed.
Design Patterns Explained: A New Perspective on Object-Oriented Design
This course goes beyond merely teaching several design patterns. It also teaches the principles and strategies that make design patterns
good designs. This enables students to use these advanced design techniques in their problems whether design patterns are even present.
After teaching several patterns and the principles underneath them, the course goes further by showing how patterns can work together to
create robust, flexible, maintainable designs.
Refactoring, Unit Testing and Test-Driven Development
The practice of Agile Software Development requires, among other things, a high degree of flexibility in the coding process. As we get
feedback from clients, stakeholders, and end users, we want to be able to evolve our design and functionality to meet their needs and
expectations. This implies an incremental process, with frequent (almost constant) change to the code we're working on. Refactoring, the
discipline of changing code without harming it, is an essential technique to enable this process. Unit testing, which ensures that a given
change has not caused an unforeseen ripple effect in the system, is another.