Escolar Documentos
Profissional Documentos
Cultura Documentos
CSI323 Lecture
Re-use
Code re-use
Dont reinvent the wheel Requires clean, elegant, understandable, general, stable code leverage previous work
Design re-use
Dont reinvent the wheel Requires a precise understanding of common, recurring designs leverage previous work
Usually descriptions of communicating objects and classes that are customized to solve a general design problem in a particular context.
Expert
Most general purpose responsibility assignment principle? Assign a responsibility to the information expert the class that has the information necessary to fulfill the responsibility.
What class should be responsible for knowing a resource, given a call number?
Catalog is an information expert on finding and returning a resource, based on a call number. It logically contains all of them.
borrowResource(callNum)
by Expert
Expert (contd)
Related to another fundamental responsibility assignment strategy which is central to object-oriented design:
Do it Myself (Coad) A Book calculated its own due date
Creator
Who should create an instance of a particular class? Consider assigning Class B the responsibility to create an instance of class A if one of the following is true:
B contains A B aggregates A B records A B closely uses A
Creator
by Creator makeBook(title)
Controller
A controller is a class that handles a system event message. What class should handle a system event message? Assign the responsibility for handling a system operation message to one of these choices:
The business or overall organization (a faade controller). The overall system (a faade controller). An animate thing in the domain that would perform the work (a role controller). An artificial class representing the use case (a use case controller).
Controller - Facades
Facades are covers. Intent a class that (in some way) represents an overall cover.
by Controller
borrowResource(callNum) :Library
borrowResource(callNum) :LibInfoSystem
Consumer/Producer
Concurrency Pattern This design pattern coordinates the concurrent production and consumption of information among producer and consumer objects that are working on different threads. This pattern is used with some type of semaphore
Consumer/Producer - example
static AutoResetEvent eventProducerDone = new AutoResetEvent(false); static AutoResetEvent eventConsumerDone = new AutoResetEvent(false); static int currentNum = 0; static void produce(object stateInfo) { eventProducerDone.Set(); while (true) { //wait for the consumer eventConsumerDone.WaitOne(); currentNum++; eventProducerDone.Set(); } }
Consumer/Producer - example
static void Main(string[] args) { ThreadPool.QueueUserWorkItem(new WaitCallback(produce)); for (int i = 0; i < 20; i++) { eventProducerDone.WaitOne(); System.Diagnostics.Debug.WriteLine(currentNum); eventConsumerDone.Set(); } }
Subject-observer
[from Vlissides]
Subject-observer (cont.)
1 * Observer OnUpdate()
Subject-observer (cont.)
Subject Register(Observer) Unregister(Observer) NotifyAll() 1
ConcreteSubject
ConcreteObserver
virtual OnUpdate()
Model
calls Register()
Create()
Controller
Model
Register()
MVC (cont.)
Subject Register(Observer) Unregister(Observer) NotifyAll() 1
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
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
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 StrategyA
Concrete 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 ImplementorA
Concrete ImplementorB
Refined Abstraction
[from Vlissides]
END