Design Patterns: ECE 417/617: Elements of Software Engineering Stan Birchfield Clemson University
Design Patterns: ECE 417/617: Elements of Software Engineering Stan Birchfield Clemson University
[from Vlissides]
Subject-observer (cont.)
1 * Observer
Subject
Register(Observer) OnUpdate()
Unregister(Observer)
NotifyAll()
ConcreteSubject ConcreteObserver
virtual OnUpdate()
Model / view / controller (MVC)
View (displays data) {
Model m;
Controller (mediates) Controller c(&m);
View v(&c);
Model (holds data) } calls Register()
Main Create()
Create()
Register()
Create()
View
Controller
Model
MVC (cont.)
1 *
Subject Observer
Controller View
virtual OnUpdate()
MVC (cont.)
class Observer
{
protected:
virtual void OnUpdate(MsgId message_id) = 0;
};
class Subject
{
public:
enum MsgId {};
void RegisterObserver(Observer* obs);
virtual void NotifyAllObservers(MsgId message_id) {
for (int i=0 ; i<m_observers.size() ; i++) {
m_observers[i]->OnUpdate(message_id);
}
}
private:
std::vector<Observer*> m_observers;
};
MVC (cont.)
class Controller : public Subject
{
Controller(Data* d) : m_data(d) {}
const Data* GetData() const;
void AddSphere(const Sphere& s) {
m_data->AddSphere(s);
NotifyAllObservers(ADD_SPHERE);
}
private:
Data* m_data;
};
MVC (cont.)
class MainWnd : public Observer
{
public:
MainWnd(Controller* c) : m_controller(c) {
c.Register(this);
}
virtual void OnUpdate(int message_id) {
switch (message_id) {
case Subject::ADD_SPHERE:
...
}
}
private:
Controller* m_controller;
};
Adapter
• You have
– legacy code
– current client
• Adapter changes interface of legacy code so
client can use it
• Adapter fills the gap b/w two interfaces
• No changes needed for either
– legacy code, or
– client
Adapter (cont.)
class NewTime
{
public:
int GetTime() {
return m_oldtime.get_time() * 1000 + 8;
}
private:
OldTime m_oldtime;
};
Command
• You have commands that need to be
– executed,
– undone, or
– queued
• Command design pattern separates
– Receiver from Invoker from Commands
• All commands derive from Command
and implement do(), undo(), and redo()
Facade
• You
– have a set of related classes
– want to shield the rest of the system from
these details
• Facade provides a simplified interface
• Encapsulates a subsystem
Composite
• You want uniformly to treat
– items (atomic elements), and
– groups (containing items or other groups)
• Composite interface specifies operations
that are shared between items and
groups
• Examples: hierarchy of files and
directories, groups of drawable elements
Composite (cont.)
Composite
Item Group
Proxy
• You want to
– delay expensive computations,
– use memory only when needed, or
– check access before loading an object into memory
• Proxy
– has same interface as Real object
– stores subset of attributes
– does lazy evaluation
Strategy
• You want to
– use different algorithms depending upon the context
– avoid having to change the context or client
• Strategy
– decouples interface from implementation
– shields client from implementations
– Context is not aware which strategy is being used;
Client configures the Context
– strategies can be substituted at runtime
– example: interface to wired and wireless networks
Strategy (cont.)
Client Policy
Context Strategy
Concrete Concrete
StrategyA StrategyB
Bridge
• You
– have several different implementations
– need to choose one, possibly at run time
• Bridge
– decouples interface from implementation
– shields client from implementations
– Abstraction creates and initializes the
ConcreteImplementations
– Example: stub code, slow code, optimized code
Bridge (cont.)
Client
Abstraction Implementor
Concrete Concrete
ImplementorA ImplementorB
Refined
Abstraction
Design pattern space
[from Vlissides]