240 likes | 374 Views
Design Patterns. ECE 417/617: Elements of Software Engineering. Stan Birchfield Clemson University. What is a Design Pattern?. A design pattern abstracts a recurring design structure comprises class and/or object dependencies, structures, interactions, or conventions
E N D
Design Patterns ECE 417/617:Elements of Software Engineering Stan Birchfield Clemson University
What is a Design Pattern? • A design pattern • abstracts a recurring design structure • comprises class and/or object • dependencies, • structures, • interactions, or • conventions • distills design experience
Re-use • Code re-use • Don’t reinvent the wheel • Requires clean, elegant, understandable, general, stable code • leverage previous work • Design re-use • Don’t reinvent the wheel • Requires a precise understanding of common, recurring designs • leverage previous work
Some design patterns • Abstract factory • Adapter • Bridge • Command • Composite • Façade • Subject / Observer • Proxy • Strategy
Subject-observer [from Vlissides]
Subject-observer (cont.) 1 * Subject Register(Observer) Unregister(Observer) NotifyAll() Observer OnUpdate() for all o in observers { o.OnUpdate() }
Subject-observer (cont.) 1 * Subject Register(Observer) Unregister(Observer) NotifyAll() Observer virtual OnUpdate() for all o in observers { o.OnUpdate() } ConcreteSubject ConcreteObserver virtual OnUpdate()
Model / view / controller (MVC) (displays data) View { Model m; Controller c(&m); View v(&c); } (mediates) Controller (holds data) Model calls Register() Main Create() View Create() Register() Create() Controller Model
MVC (cont.) 1 * Subject Register(Observer) Unregister(Observer) NotifyAll() Observer virtual OnUpdate() for all o in observers { o.OnUpdate() } 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 Strategy Context 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 Implementor Abstraction Concrete ImplementorA Concrete ImplementorB Refined Abstraction
Design pattern space [from Vlissides]