Design patterns
Download
1 / 42

Design Patterns - PowerPoint PPT Presentation


  • 101 Views
  • Uploaded on

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:

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about ' Design Patterns' - clemance-legend


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



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



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



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.



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.




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?



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 (==)



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


  • 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




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


ad