Você está na página 1de 49

OO Design Patterns

CSI323 Lecture

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
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

What is a Design Pattern?


A pattern is a named problem/solution pair that can be applied in new contexts, with advice on how to apply it in novel situations. Patterns provide guidance for how responsibilities should be assigned to objects, given a specific category of problem. Patterns typically do not contain new ideas. Patterns attempts to codify existing knowledge, idioms and principles.

What is a Design Pattern? (contd)


There are four essential elements of a pattern. Pattern name Problem describes when to apply the pattern. Solution describes the elements that make up the design. Consequences are the results and trade-offs of applying the pattern.

Usually descriptions of communicating objects and classes that are customized to solve a general design problem in a particular context.

How Design Patterns Solve Design Problems


The hard part of OO design is decomposing a system into objects. Many objects in a design come from the analysis model. OO designs end-up with classes that dont have any counterparts in the real world. Design patterns help you identify less obvious abstractions.

A List of Design Patterns


Expert Creator Controller Mediator Decorator Prototype Object Pool Faade Observer Builder Adapter Command Abstract Factory Proxy Iterator

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)

1 : r := resource(callNum) : Resource :Library :Catalog

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

Closely related to/Also known as:


Put services with attributes (Coad) That which knows, does it (Sieve)

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

B is the creator of A instances.

Creator

by Creator makeBook(title)

1 : create(title) :Catalog :Book

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

Controller Facades (contd)


Other facades? a class representing the system, e.g.,
The software information system. The device that includes a computer and software (e.g., ATM) Etc.
borrowResource(callNum) :Library

borrowResource(callNum) :LibInfoSystem

Observer design patterns


Behavioral Pattern one-to-many dependency model, so that when one object changes state, all its dependents are notified and updated automatically without coupling the notifying object to the objects that are notified. Example: Button expose a clicked event that encapsulate click state, thus publish himself as an observable. Clients that are interested in this event register to it, thus becomes observers. Observer and observable are bonded in a contract and can be completely loosely coupled from one another.

Singleton design pattern


Creational pattern ensure that a class has only one instance, and to provide a global point of access to it Example: Class SomeClass { static SomeClass singleTonInstance = null; static SomeClass GetInstance() { if(singleTonInstance == null) singleTonInstance = new SomeClass() return singleTonInstance; } }

Factory design patterns (abstract\method\Lightweight)


Creational pattern Can be given to client (abstract), pass construction parameters or read creation types from configuration or system environment Can use object pool (Lightweight)

Factory design pattern - example


abstract class GUIFactory { public static GUIFactory getFactory() { int sys = readFromConfigFile("OS_TYPE"); return sys == 0 ? new WinFactory() : new OSXFactory(); } public abstract Button createButton(); } class WinFactory:GUIFactory { public override Button createButton() { return new WinButton(); } } class MacFactory:GUIFactory { public override Button createButton(){ return new MacButton(); } } abstract class Button { public string caption; public abstract void paint(); }

Factory design pattern - example


class WinButton:Button { public override void paint() { // paint a button with Win API} } class MacButton:Button { public override void paint() { // paint a button Mac style } } class Application { static void Main(string[] args) { GUIFactory aFactory = GUIFactory.getFactory(); Button aButton = aFactory.createButton(); aButton.caption = "Play"; aButton.paint(); } }

Faade design pattern


Structural Pattern Provide a unified interface to a set of interfaces in a subsystem without damaging the genric form of the sub system.

Decorator design pattern


Structural Pattern Avoid excessive sub-classing and gain run time flexibility Example: Java.IO package
BufferedReader br = new BufferedReader( new InputStreamReader( new FileInputStream(inFile)));

All derives from abstract io.Reader

Strategy design pattern


Behavioral Pattern defines a family of interchangeable encapsulated algorithms that receives the same input type and provides the same output type in different manners that can be determined in run-time. static void Main( { SortedList studentRecords = new SortedList(); studentRecords.Add("Samual"); studentRecords.Add("Jimmy"); studentRecords.Add("Sandra"); studentRecords.SetSortStrategy(new QuickSort()); studentRecords.Sort(); studentRecords.SetSortStrategy(new ShellSort()); studentRecords.Sort(); }

Strategy design pattern - example


abstract class SortStrategy { public abstract void Sort(ArrayList list) } class QuickSort : SortStrategy { public override void Sort(ArrayList list) { list.Sort(); // Default is Quicksort } } class ShellSort : SortStrategy { public override void Sort(ArrayList list) { //list.ShellSort(); not-implemented } }

Strategy design pattern - example


class SortedList { private ArrayList list = new ArrayList(); private SortStrategy sortstrategy; public void SetSortStrategy(SortStrategy sortstrategy) { this.sortstrategy = sortstrategy; } public void Add(string name) { list.Add(name); } public void Sort() { sortstrategy.Sort(list); } }

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(); } }

Model View Controller


The Model-View-Controller (MVC) pattern separates the modeling of the domain, the presentation, and the actions based on user input into three separate classes The controller changes the model The View Listens to Model Changed events and update itself Recursive MVC

Subject-observer

[from Vlissides]

Subject-observer (cont.)
1 * Observer OnUpdate()

Subject Register(Observer) Unregister(Observer) NotifyAll()

for all o in observers { o.OnUpdate() }

Subject-observer (cont.)
Subject Register(Observer) Unregister(Observer) NotifyAll() 1

Observer virtual OnUpdate()

for all o in observers { o.OnUpdate() }

ConcreteSubject

ConcreteObserver
virtual OnUpdate()

Model / view / controller (MVC)


View Controller (displays data) (mediates) (holds data)
Create()

{ Model m; Controller c(&m); View v(&c);

Model

calls Register()

Create()

Main View Create()

Controller
Model

Register()

MVC (cont.)
Subject Register(Observer) Unregister(Observer) NotifyAll() 1

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

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

Design pattern space

[from Vlissides]

END

Você também pode gostar