37
Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk- Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

Embed Size (px)

Citation preview

Page 1: Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

Design Patterns

Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004

Copyright © INTEKS LLC, 2003-2004

Page 2: Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

Design pattern

Design pattern is a solution to a problem, which occurs over and over again.

Pattern elements:

• Name – a handle we use to describe a pattern in a word or two

• Problem – describes when to apply a pattern

• Solution – describes a set of design elements which solve a problem

• Consequences – benefits, disadvantages, constraints

Page 3: Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

Pattern types

E. Gamma classification: Creational patterns – abstract the instantiation process and make a system independent on how objects are created

Abstract Factory, Factory Method, Singleton

Structural patterns – solve objects composition problems Adapter, Bridge, Decorator, Proxy

Behavioral patterns - algorithms and the assignment of responsibilities between objects

Chain of Responsibility, Command, Iterator, Observer, State, Strategy

Page 4: Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

Abstract Server

Problem: - Button is not reusable in a context not involving a light

Button

state : bool

push()

Light

turnOn()turnOff()

1

-lamp

1

Page 5: Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

Solution

Solution: break dependency between Button and Light by inserting an interface

Light

turnOn()turnOff()

Button

state : bool

push()

Device

turnOn()turnOff()

<<Interface>>

1

-device

1

Page 6: Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

Abstract Server Pattern

Benefits:- decouples clients from their servers- servers can be changed without affecting clients- eliminates DIP violation

Server

ClientAbstractServer<<Interface>>-server

Page 7: Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

Adapter

Problem:- Light already exists and can’t inherit from Device- Device might have messages activate/deactivate

Button

state : bool

push()

Device

activate()deactivate()

Light

turnOn()turnOff()

Page 8: Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

Solution

- use an adapter to convert one interface to another

Button

state : bool

push()

Device

activate()deactivate()1

LightAdapter

activate()deactivate()

Light

turnOn()turnOff()1

-device

1

-light

1

Page 9: Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

Pattern: Adapter

Also known as: WrapperBenefits: - breaks dependency between client and server when server exists - allows different servers to be swapped in and out

ClientAbstractServer<<Interface>>-server

ServerAdapter Server-server

Page 10: Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

Pattern: Adapter

A variation, which allows server methods to be redefined

ClientAbstractServer<<Interface>>-server

ServerAdapter

Server

Page 11: Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

Abstract Client

Problem:• Server needs to send callback message to client• GUI Button is not a reusable class• Callback method makes Device unreusable

Device

start()stop()

GUIButton

isOn : bool

setState()

-device

-button

Page 12: Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

Solution

Server provides interface for client to use

Device

start()stop()

GUIButton

isOn : bool

setState()

-device

StateListener

changeState()

<<Interface>>-button

Page 13: Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

Pattern: Abstract Client

Q: What package should contain AbstractClient class ? A: Server’s package

Client Server

service()

AbstractClient

callback()

<<Interface>>

Page 14: Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

Adapted Client

Problem: GUI library components (JButton) do not implement StateListener

Solution: use Adapter pattern along with Abstract Client

GUIButton StateListener

ButtonAdapter Device

Page 15: Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

Singleton

Problem:• How many database objects do we need in a simple program?• Would it be a bad thing is someone mistakenly created more?

Solution:• prevent programmers from making objects.

• Make constructors private or protected.• make the class responsible for making the one and only object

Page 16: Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

Singleton

Use singleton when:• there must be exactly one instance of a class• it must be accessible to clients from anywhere inside the program: CompanyDb::Instance()->getEmployee(“Leha”);

CompanyDb

$ db : Database

Instance()CompanyDb()getEmployee()

class CompanyDb { private: static CompanyDb* db; CompanyDb(); ~CompanyDb(); public: static CompanyDb* Instance() { if( 0 == db ) return db = new CompanyDb(); return db; } Employee* getEmployee( const char* name );};

Page 17: Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

Monostate Solves the same problem as Singleton All members are static Constructors and destructor are private

Class CompanyDb { private: Db db; CompanyDb(); public: static Employee* get Employee( const char* name );}Db CompanyDb::db = Db( “CompanyName” );Employee* CompanyDb::getEmployee( const char* name ) { return db.find( “Employee”, name );}

Employee* emp = CompanyDb::getEmployee( “Leha” );

Page 18: Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

Singleton vs. Monostate

Construction:• Singleton has lazy construction

• Don’t pay unless you need it!• Monostates are always constructed• Singleton can have non-trivial constructors• Monostates can’t have non-trivial constructors

Destruction:• Singleton destruction is not defined• Monostate destructon is well-defined

Page 19: Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

Strategy

Problem: - different employees are paid differently - what if we need to add hourly paid manager ? - hierarchy is hard to maintain

Director

calcSalary()

Manager

calcSalary()

Employee

calcSalary()

nn

SalariedManager

calcSalary()

HourlyEmployee

calcSalary()

SalariedEmployee

calcSalary()

Page 20: Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

Solution

PaymentPolicy specifies an algorithm for payment calculation

Director

Manager

Employee

nn

PaymentPolicy

pay()

<<Interface>>

11

-payment

Hourly

pay()

Weekly

pay()

Revenue

pay()

Page 21: Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

Strategy Pattern

Also known as: PolicyBenefits:- different strategies can be swapped in and out- context is closed to changes or additions of strategies

Context Strategy

algorithm()

<<Interface>>1

Strategy1

algorithm()

Strategy2

algorithm()

Strategy3

algorithm()

1

Page 22: Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

Bridge

Problem:- Client code depends on platform- To support a new platform, we need to reproduce all Window’s derivatives

Window

XWindow PMWindow

DialogWindowXDialogWindow

Page 23: Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

Solution

All operations on Window subclasses are implemented in terms of abstract operations from the WindowImp interface Makes Window and its subclasses platform-independent Q: How to make clients independent on WindowImp subclasses?

Window

drawText()

WindowImp

drawText()

11

XWindowImp

drawText()

PMWindowImp

drawText()

DialogWindowIconWindow

Bridge

Page 24: Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

Bridge Pattern

Also known as: Handle/BodyBenefits: - Eliminates DIP & OCP violation - Increases maintainability

Implementor

operation()

Implementor1

operation()

Implementor2

operation()

Client

Abstraction

operation()11

RefinedAbstration

Page 25: Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

Proxy

Problem:We need to optimize object access in order to make resource allocation operations on demand

ClientImage

Draw()GetSize()GetPosition()

Page 26: Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

Solution

Solution: - use a surrogate that will initiate create operation on demand - clients can treat RealImage and ImageProxy as similar objects.

ClientImage

Draw()GetSize()GetPosition()

<<Interface>>

ImageProxyRealImage0..1 0..*0..*0..1

Page 27: Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

Proxy Pattern

Also known as: SurrogateApplicability: - remote proxy - virtual proxy (creation of real object on demand) - protection proxy (for example: ACL support)

Client Subject

request()

Proxy

request()

RealSubject

request()

Page 28: Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

Abstract Factory

Problem: - creating objects creates a dependency on a concrete type - all other manipulations are done through interface !

Circle Square

ClientShape

<<Interface>>

<<creates>>

<<creates>>

Page 29: Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

Solution

Make a class whose responsibility is to make objectsMaking objects can’t be avoided, but can be contained

Circle Square

Shape<<Interface>>

FactoryImp

makeCircle()makeSquare()

Client

ShapeFactory

makeCircle()makeSquare()

<<Interface>>

<<creates>> <<creates>>

Page 30: Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

Factory Pattern

Isolates concrete classes, makes Types family changes easier

ConcreteFactoryA

createType1()createType2()

ConcreteFactoryB

createType1()createType2()

Type

Type1A Type2A

ClientAbstractFactory

createType1() : TypecreateType2() : Type

Type2A Type2B

Page 31: Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

Stairway to Heaven

Problem: - We wish to make an hierarchy of classes persistent, but we don’t want to depend upon the vendor of our database

Type1

Type2

Type3

PersistentObject

load()save()

Page 32: Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

Solution

Use Adaptor pattern at each level in the hierarchy Requires virtual multiple inheritance

Type1

Type2

Type3

PersistentObject

load()save()

PersistentType1

PersistentType2

PersistentType3

Knowledge of persistence

Knowledgeof business

Page 33: Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

Visitor

• What if we need to configure modems differently for different operating systems?

ModemDial()Send()Hangup()Recv()

<<Interface>>

SiemensGSMModem ZyxelHwModem WinModem

Page 34: Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

Visitor

• Problem?• ISP violation. Hard to support new OSes.

ModemDial()Send()Hangup()Recv()ConfigureForWin()ConfigureForLinux()

<<Interface>>

Page 35: Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

SolutionModem

Dial()Send()Hangup()Recv()accept(ModemVisitor)

<<Interface>>

SiemensGSMModem

ZyxelHwModem WinModem

ModemVisitorvisit(SiemensGSMModem)visit(ZyxelHwModem)visit(WinModem)

WindowsModemConfigurator

public void accept(ModemVisitor v){ v.visit(this)}

Page 36: Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

Issues

• Problem?• A cycle involving modem implementations. Hard

to support new modem types.

ModemDial()Send()Hangup()Recv()accept(ModemVisitor)

<<Interface>>

ModemVisitorvisit(SiemensGSMModem)visit(ZyxelHwModem)visit(WinModem)

WinModem

Page 37: Design Patterns Copyright © Vyacheslav Mukhortov, Nikita Nyanchuk-Tatarskiy, 2001-2004 Copyright © INTEKS LLC, 2003-2004

New Solution: Acyclic Visitor

Zyxel WinModem

ModemDial()Send()Recv()Hangup()accept(ModemVIsitor)

<<Interface>>

ModemVisitor<<Interface>>

SiemensVisitorvisit(mdm : Siemens)

<<Interface>>

Siemens

ZyxelVisitorvisit(mdm : Zyxel)

<<Interface>>

public void accept( ModemVisitor v) { try { SiemensVisitor sv = (SiemensVisitor) v; sv.visit(this); } catch (ClassCastException e){}}

WinModemVisitorvisit(mdm : WinModem)

<<Interface>>

WindowsModemConfigurator