Design patterns
This presentation is the property of its rightful owner.
Sponsored Links
1 / 42

Design Patterns PowerPoint PPT Presentation


  • 75 Views
  • Uploaded on
  • Presentation posted in: General

Design Patterns. Structural Patterns. Adapter. Convert the interface of a class into another interface clients expect Adapter lets classes work together that couldn't otherwise because of incompatible interfaces Use the Adapter pattern when:

Download Presentation

Design Patterns

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


Design patterns

Design Patterns

Structural Patterns


Adapter

Adapter

  • Convert the interface of a class into another interface clients expect

  • Adapter lets classes work together that couldn't otherwise because of incompatible interfaces

  • Use the Adapter pattern when:

    • you want to use an existing class and its interface does not match the one you need

    • you need to use several existing subclasses, but it's impractical to adapt their interface by subclassing everyone. An object adapter can adapt the interface of its parent class


Adapter1

Adapter


Bridge

Bridge

  • Decouple an abstraction from its implementation so that the two can vary independently

  • Use the Bridge pattern when:

    • you want run-time binding of the implementation

    • you want to share an implementation among multiple objects


Bridge1

Bridge


Composite

Composite

  • Compose objects into tree structures to represent whole-part hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly

  • Use this pattern whenever you have "composites that contain components, each of which could be a composite".


Composite1

Composite


Decorator

Decorator

  • Attach additional responsibilities to an object dynamically

  • Decorators provide a flexible alternative to subclassing for extending functionality


Problems

Problems

  • Several classes with a similar operation (method), but different behavior.

  • We want to use many combinations of these behaviors


Example automated hospital

Example - Automated Hospital

  • People come to the reception with problems

  • They describe their problems

  • A special doctoRobot is created that is specialized to treat their special situations.


Automated hospital solution 1

Automated Hospital - Solution 1


Problems with solution 1

Problems with solution-1

  • Sometimes we don’t have multiple inheritance.

  • Even if we have, if is problematic, and bad design.

  • 2n possible classes to create before compilation.


A better idea use decorator

A Better idea: Use Decorator


Decorator in our case

Decorator in our case


Code example

Code Example

Widget* aWidget = new BorderDecorator( new HorScrollDecorator( new VerScrollDecorator( new TextWidget( 80, 24 ))));

aWidget->draw();

Stream* aStream = new CompressingStream( new ASCII7Stream( new FileStream( "fileName.dat" )));

aStream->putString( "Hello world" );


Benefits

Benefits

  • Flexible

  • Don’t have to foresee all combinations

  • Little objects

Possible problems

  • Performance

  • Decorators are not necessarily always cummutative(surgeon and Anastasiolic)


Facade

Facade

  • Provide a unified interface to a set of interfaces in a subsystem

  • Facade defines a higher-level interface that makes the subsystem easier to use

  • Create a class that is the interface to the subsystem

  • Clients interface with the Facade class to deal with the subsystem

  • It hides the implementation of the subsystem from clients

  • It promotes weak coupling between the subsystems and its clients

  • It does not prevent clients from using subsystems class, should it?


Facade1

Facade


Flyweight

Flyweight

  • Use sharing to support large numbers of fine-grained objects efficiently

  • The pattern can be used when:

    • The program uses a large number of objects and

    • Storage cost are high because of the sheer quantity of objects and

    • The program does not use object identity (==)


Flyweight1

Flyweight


Proxy

Proxy

  • Provide a surrogate or placeholder for another object to control access to it.

  • The proxy has the same interface as the original object

  • Virtual Proxy:

    • Creates/accesses expensive objects on demand

    • You may wish to delay creating an expensive object until it is really accessed

    • It may be too expensive to keep entire state of the object in memory at one time


Design patterns

  • Protection Proxy

    • Provides different objects different level of access to original object

  • Cache Proxy (Server Proxy)

    • Multiple local clients can share results from expensive operations: remote accesses or long computations

  • Firewall Proxy

    • Protect local clients from outside world


Proxy1

Proxy


Dynamics

Dynamics


Reference counting

Reference Counting

  • Don’t bother to make a copy of something until you really need one:Be Lazy ?!

  • Use someone else’s copy as long as you can get away with it.

Class String { … };

String s1 = “Hello”;

String s2=s1;

cout << s1;

cout << s1 + s2;

S2.convertToUpperCase();


Reference counting1

Reference Counting

  • Copying the string contents in every

    • Assignment,

    • Argument passing, and

    • Function returning value

  • Can be both

    • Expensive, and

    • Unnecessary!


The basic string class

The basic String class

class String {

public:

String(const char* value= “”);

String(const String& rhs);

String& operator=(const String& rhs);

private:

char *date;

};


The common implementation

The common implementation

String& String::operator=(const String& rhs)

{

if(this == &rhs) return * this;

delete [] data;

data = new char[strlen(rhs.data) + 1];

strcpy(data,rhs.data);

return *this;

}


Using the string class

Using the String class

String a,b,c,d,e;

a=b=c=d=e=“Hello”

String A

Hello\0

String B

Hello\0

String C

Hello\0

String D

Hello\0

String E

Hello\0


The idea behind reference counting

The Idea Behind Reference Counting

String A

Reference

String B

String C

5

Hello\0

String D

String E


Implement the reference counting

Implement The Reference Counting

class String{

private:

struct StringRef{

int refCount;

char *data;

StringRef(const char *initValue);

~StringRef();

};

StringRef *value;

public:

String(const char* value= “”);

String(const String& rhs);

String& operator=(const String& rhs);

};


Stringref class implementation

StringRef class implementation

String::StringRef::StringRef(const char* initVal)

: refCount(1)

{

data = new char[strlen(initVal) + 1];

strcpy(data,initVal);

}

String::StringRef::~StringRef()

{

delete []data;

}


String class implementation

String class implementation

String::String(const char *initVal)

: value(new StringRef(initVal))

{}

String::String(const String& rhs) : value(rhs.value)

{

++value->refCount;

}

String::~String()

{

if(--value->refCount == 0) delete value;

}


String class implementation1

String class implementation

String& String::operator=(const String& rhs)

{

if (value == rhs.value) return *this;

if (--vaule->refCount == 0) delete value;

value = rhs.value;

++value->refCount;

return *this;

}


Using the string class1

Using the String class

String s1(“More Effective c++”);

String s2(“More Effective c++”);

String s3=s2;

String s4;

S4=s3;

StringRef

s1

More Effective c++\0

1

s2

s3

More Effective c++\0

3

s4


Copy on write

Copy on Write

Class String {

public:

char operator[](int index) const;

char& operator[](int index);

};

char String::operator[](int index) const

{

return value->data[index];

}


Copy on write1

Copy on Write

char& String::operator[](int index)

{

if(value->refCount > 1){

--value->refCount;

value = new StringRef(value->data);

}

return value->data[index];

}

String s1;

const String s2;

cout << s1 << s2;

s1[5] = ‘x’;


Distinguishing reads from writes

Distinguishing Reads from Writes

  • Reading a reference counting is cheap

  • Writing require splitting off a new copy

String s = “H. Simpson”;

cout << s[5];

S[5] = ‘I’;


Distinguishing reads from writes via operator

Distinguishing Reads from Writes via operator[]

class String{

public:

class CharProxy{

public:

CharProxy(String& str,int index);

CharProxy& operator=(const CharProxy& rhs);

CharProxy& opeartor=(char c);

operator char() const;

private:

String& theString;

int charIndex;

};

const CharProxy operator[](int index) const;

CharProxy operator[](int index);

friend class CharProxy;

private:

struct StringRef{…};

StringRef *value;

};


Distinguishing reads from writes via operator1

Distinguishing Reads from Writes via operator[]

const String::CharProxy String::operator[](int index) const

{

return CharProxy(const_cast<String&>(*this),index);

}

String::CharProxy String::operator[](int index)

{

return CharProxy(*this,index);

}

String::CharProxy::CharProxy(String& str,int index)

: theString(str),charIndex(index){}

String::CharProxy::operator char() const

{

return theString.value->data[charIndex];

}


Distinguishing reads from writes via operator2

Distinguishing Reads from Writes via operator[]

String::CharProxy&

String::CharProxy::operator=(const CharProxy& rhs)

{

if(theString.value->reCount > 1)

theString.value = new StringRef(theString.value->data);

theString.value->data[charIndex] =

rhs.theString.value->data[charIndex];

return *this;

}

String::CharProxy& String::CharProxy::operator=(char c)

{

if(theString.value->reCount > 1)

theString.value = new StringRef(theString.value->data);

theString.value->data[charIndex] = c;

return *this;

}


Using the proxy class

Using the proxy class

String s1,s2;

cout << s1[5];

s1[5] = ‘x’;

s1[3] = s2[8];


  • Login