Top Banner
Design Patterns Design principles
61

Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

Dec 17, 2015

Download

Documents

Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

Design PatternsDesign Patterns

Design principles Design principles

Page 2: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

The Open/Closed Principle (OCP)

The Open/Closed Principle (OCP)

A module should be open for extension but closed for

modification.

A module should be open for extension but closed for

modification.

Page 3: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

The open/ closed principleThe open/ closed principle

• We should write our modules so that they can be extended, without requiring them to be modified. In other words, we want to be able to change what the modules do, without changing the source code of the modules.

• How?:

Abstraction and Polymorphism

• We should write our modules so that they can be extended, without requiring them to be modified. In other words, we want to be able to change what the modules do, without changing the source code of the modules.

• How?:

Abstraction and Polymorphism

Page 4: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

The open/ closed principle (OCP) ExampleThe open/ closed principle (OCP) Example

CircleData

radius : floatcenter : Point

SquareData

origin : Pointlength : floatwidth : float

ShapeManipulator

drawShape(shapeData : ShapeData)drawCircle(circle : CircleData)drawSquare(square : SquareData)

ShapeData

shapeType : int

public void drawShape(ShapeData shapeData) { switch (shapeData.shapeType) {

case SQUARE:drawSquare((SquareData)shapeData);break;

case CIRCLE:drawCircle((CircleData)shapeData);break;

} }

Page 5: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

The open/ closed principle (OCP) Discussion

The open/ closed principle (OCP) Discussion

• If I need to create a new shape, such as a Triangle, I must modify the ‘drawShape()' function.

• In a complex application the switch/case statement above is repeated over and over again for every kind of operation that can be performed on a shape .

• Worse, every module that contains such a switch/case statement retains a dependency upon every possible shape that can be drawn, thus, whenever one of the shapes is modified in any way, the modules all need recompilation, and possibly modification

• If I need to create a new shape, such as a Triangle, I must modify the ‘drawShape()' function.

• In a complex application the switch/case statement above is repeated over and over again for every kind of operation that can be performed on a shape .

• Worse, every module that contains such a switch/case statement retains a dependency upon every possible shape that can be drawn, thus, whenever one of the shapes is modified in any way, the modules all need recompilation, and possibly modification

Page 6: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

The open/ closed principle (OCP) ExampleThe open/ closed principle (OCP) Example

ShapeInterface

draw()move()

<<Interface>>

Circle

draw()move()

Square

draw()move()

SmartShapeManipulator

drawShape(shape : ShapeInterface)

public void drawShape(ShapeInterface shape){ shape.draw ();}

Page 7: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

SummerySummery

• When the majority of modules in an application conform to the open/closed principle, then new features can be added to the application by adding new code rather than by changing working code. Thus, the working code is not exposed to breakage.

• When the majority of modules in an application conform to the open/closed principle, then new features can be added to the application by adding new code rather than by changing working code. Thus, the working code is not exposed to breakage.

Page 8: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

The Liskov Substitution Principle (LSP)

The Liskov Substitution Principle (LSP)

Subclasses should be substitutable for their base

classes.

Subclasses should be substitutable for their base

classes.

Page 9: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

The Liskov Substitution Principle (LCP)

The Liskov Substitution Principle (LCP)

• A client of a base class should continue to function properly if a derivative of that base class is passed to it.

• In other words, if some function takes an argument ot type Policy, then it should be legal to pass in an instance of Personal Auto Policy to that provided Personal Auto Policy is directly/ indirectly derived from Policy.

• A client of a base class should continue to function properly if a derivative of that base class is passed to it.

• In other words, if some function takes an argument ot type Policy, then it should be legal to pass in an instance of Personal Auto Policy to that provided Personal Auto Policy is directly/ indirectly derived from Policy.

Page 10: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

The Liskov Substitution Principle (LCP) Example

The Liskov Substitution Principle (LCP) Example

Policy

getUnitsOfRisk()getPolicyCoverages()getRateSteps()

AutoPolicy

PersonalAutoPolicy CommercialAutoPolicy

PolicyRateModule

This module should not break regardless of whether a Personal Auto or Commercial Auto or Home Owner Policy is passed to it

HomeOwnerPolicy

Page 11: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

The Liskov Substitution Principle (LCP) Discussion

The Liskov Substitution Principle (LCP) Discussion

• Is Square a Rectangle ? Mathematically yes, Behaviorally, a Square is not a Rectangle and it is behavior that software is really all about.

• It is only when derived types are completely substitutable for their base types that functions which use those base types canbe reused with impunity, and the derived types can be changed with impunity.

• Violations of LSP are latent violations of OCP.

• Is Square a Rectangle ? Mathematically yes, Behaviorally, a Square is not a Rectangle and it is behavior that software is really all about.

• It is only when derived types are completely substitutable for their base types that functions which use those base types canbe reused with impunity, and the derived types can be changed with impunity.

• Violations of LSP are latent violations of OCP.

Page 12: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

Structural Patterns Structural Patterns

• Structural patterns are concerned with how classes and objects are composed to form larger structures

• Structural class patterns use inheritance to compose interfaces or implementations

• Structural patterns are concerned with how classes and objects are composed to form larger structures

• Structural class patterns use inheritance to compose interfaces or implementations

Page 13: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

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

• 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

Page 14: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

Adapter Adapter

Page 15: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

Demo codeDemo code

public interface ICar{

void Drive();}

public class CToyota : ICar{

public void Drive(){

Console.WriteLine("we're off in our Toyota...");}

}

public interface ICar{

void Drive();}

public class CToyota : ICar{

public void Drive(){

Console.WriteLine("we're off in our Toyota...");}

}

Page 16: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

public class CCessna{

public void Fly(){

Console.WriteLine("we're off in our C172...");}

}

// the adapter classpublic class CDrivableCessna : CCessna, ICar{

public void Drive() { base.Fly(); }}

public class CCessna{

public void Fly(){

Console.WriteLine("we're off in our C172...");}

}

// the adapter classpublic class CDrivableCessna : CCessna, ICar{

public void Drive() { base.Fly(); }}

Page 17: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

ClientClient

ICar oCar = new CToyota();

oCar.Drive();

oCar = new CDrivableCessna();

oCar.Drive();

ICar oCar = new CToyota();

oCar.Drive();

oCar = new CDrivableCessna();

oCar.Drive();

Page 18: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

Other solutionOther solution

public class CDrivableCessna2 : ICar{

private CCessna m_oContained;

public CDrivableCessna2(){

m_oContained = new CCessna();}

public void Drive(){

m_oContained.Fly();}

}

public class CDrivableCessna2 : ICar{

private CCessna m_oContained;

public CDrivableCessna2(){

m_oContained = new CCessna();}

public void Drive(){

m_oContained.Fly();}

}

Page 19: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

BridgeBridge

• 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

• 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

Page 20: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

BridgeBridge

Page 21: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

ExampleExample

class Stack { private StackImpl impl; public Stack( String s ) { if (s.Equals("array")) impl = new StackArray(); else if (s.Equals("list")) impl = new StackList(); else Console.WriteLine( "Stack: unknown parameter" ); } public Stack() :this( "array" ) { } public virtual void push( int i ) { impl.push( i ); } public virtual int pop() { return impl.pop(); } public int top() { return impl.top(); } public bool isEmpty() { return impl.isEmpty(); } public bool isFull() { return impl.isFull(); }}

class Stack { private StackImpl impl; public Stack( String s ) { if (s.Equals("array")) impl = new StackArray(); else if (s.Equals("list")) impl = new StackList(); else Console.WriteLine( "Stack: unknown parameter" ); } public Stack() :this( "array" ) { } public virtual void push( int i ) { impl.push( i ); } public virtual int pop() { return impl.pop(); } public int top() { return impl.top(); } public bool isEmpty() { return impl.isEmpty(); } public bool isFull() { return impl.isFull(); }}

Page 22: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

class StackHanoi : Stack { private int totalRejected = 0; public StackHanoi():base( "array" ){ } public StackHanoi( String s ):base( s ){ } public int reportRejected()

{ return totalRejected; } public override void push( int i ) { if ( ! isEmpty() && i > top()) totalRejected++; else base.push( i );} }

class StackHanoi : Stack { private int totalRejected = 0; public StackHanoi():base( "array" ){ } public StackHanoi( String s ):base( s ){ } public int reportRejected()

{ return totalRejected; } public override void push( int i ) { if ( ! isEmpty() && i > top()) totalRejected++; else base.push( i );} }

Page 23: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

class StackFIFO : Stack { private StackImpl temp = new StackList(); public StackFIFO():base( "array" ){ } public StackFIFO( String s ) : base( s ){ } public override int pop() { while ( ! isEmpty()) temp.push( base.pop() ); int ret = temp.pop(); while ( ! temp.isEmpty()) push( temp.pop() ); return ret;

} }

class StackFIFO : Stack { private StackImpl temp = new StackList(); public StackFIFO():base( "array" ){ } public StackFIFO( String s ) : base( s ){ } public override int pop() { while ( ! isEmpty()) temp.push( base.pop() ); int ret = temp.pop(); while ( ! temp.isEmpty()) push( temp.pop() ); return ret;

} }

Page 24: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

interface StackImpl { void push( int i ); int pop(); int top(); bool isEmpty(); bool isFull();}

class StackArray : StackImpl { private int[] items = new int[12]; private int total = -1; public void push( int i ) { if ( ! isFull()) items[++total] = i; } public bool isEmpty() { return total == -1; } public bool isFull() { return total == 11; } public int top() { if (isEmpty()) return -1; return items[total]; } public int pop() { if (isEmpty()) return -1; return items[total--];} }

interface StackImpl { void push( int i ); int pop(); int top(); bool isEmpty(); bool isFull();}

class StackArray : StackImpl { private int[] items = new int[12]; private int total = -1; public void push( int i ) { if ( ! isFull()) items[++total] = i; } public bool isEmpty() { return total == -1; } public bool isFull() { return total == 11; } public int top() { if (isEmpty()) return -1; return items[total]; } public int pop() { if (isEmpty()) return -1; return items[total--];} }

Page 25: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

class StackList : StackImpl { private Node last; public void push( int i ) { if (last == null) last = new Node( i ); else { last.next = new Node( i ); last.next.prev = last; last = last.next; } } public bool isEmpty() { return last == null; } public bool isFull() { return false; } public int top() { if (isEmpty()) return -1; return last.value; } public int pop() { if (isEmpty()) return -1; int ret = last.value; last = last.prev; return ret;} }

class StackList : StackImpl { private Node last; public void push( int i ) { if (last == null) last = new Node( i ); else { last.next = new Node( i ); last.next.prev = last; last = last.next; } } public bool isEmpty() { return last == null; } public bool isFull() { return false; } public int top() { if (isEmpty()) return -1; return last.value; } public int pop() { if (isEmpty()) return -1; int ret = last.value; last = last.prev; return ret;} }

Page 26: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

ClientClient

Stack[] stacks = { new Stack( "array" ), new Stack( "list" ), new StackFIFO(), new StackHanoi() }; for (int i=1; i < 15; i++) for (int j=0; j < 3; j++) stacks[j].push( i ); Random rn = new Random(); for (int i=1; i < 15; i++) stacks[3].push( rn.Next(20) ); for (int i=0; i < stacks.Length; i++) { while ( ! stacks[i].isEmpty()) Console.Write( stacks[i].pop() + " " ); Console.WriteLine(); } Console.WriteLine( "total rejected is " + ((StackHanoi)stacks[3]).reportRejected() );

Stack[] stacks = { new Stack( "array" ), new Stack( "list" ), new StackFIFO(), new StackHanoi() }; for (int i=1; i < 15; i++) for (int j=0; j < 3; j++) stacks[j].push( i ); Random rn = new Random(); for (int i=1; i < 15; i++) stacks[3].push( rn.Next(20) ); for (int i=0; i < stacks.Length; i++) { while ( ! stacks[i].isEmpty()) Console.Write( stacks[i].pop() + " " ); Console.WriteLine(); } Console.WriteLine( "total rejected is " + ((StackHanoi)stacks[3]).reportRejected() );

Page 27: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

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

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

Page 28: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

Composite Composite

Page 29: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

ComponentComponent

abstract class DrawingElement{

protected string name;

public DrawingElement( string name ){

this.name = name;}

abstract public void Add( DrawingElement d );abstract public void Remove( DrawingElement d );abstract public void Display( int indent );

}

abstract class DrawingElement{

protected string name;

public DrawingElement( string name ){

this.name = name;}

abstract public void Add( DrawingElement d );abstract public void Remove( DrawingElement d );abstract public void Display( int indent );

}

Page 30: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

LeafLeaf

class PrimitiveElement : DrawingElement{

public PrimitiveElement( string name ) : base( name ) {}

public override void Add( DrawingElement c ){

Console.WriteLine("Cannot Add");}public override void Remove( DrawingElement c ){

Console.WriteLine("Cannot Remove");}public override void Display( int indent ){

Console.WriteLine( new String( '-', indent ) + " draw a {0}", name );}

}

class PrimitiveElement : DrawingElement{

public PrimitiveElement( string name ) : base( name ) {}

public override void Add( DrawingElement c ){

Console.WriteLine("Cannot Add");}public override void Remove( DrawingElement c ){

Console.WriteLine("Cannot Remove");}public override void Display( int indent ){

Console.WriteLine( new String( '-', indent ) + " draw a {0}", name );}

}

Page 31: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

class CompositeElement : DrawingElement{

private ArrayList elements = new ArrayList();

public CompositeElement( string name ): base( name ) {}

public override void Add( DrawingElement d ){

elements.Add( d );}public override void Remove( DrawingElement d ){

elements.Remove( d );}public override void Display( int indent ){

Console.WriteLine( new String( '-', indent ) + "+ " + name );

foreach( DrawingElement c in elements )c.Display( indent + 2 );

}}

class CompositeElement : DrawingElement{

private ArrayList elements = new ArrayList();

public CompositeElement( string name ): base( name ) {}

public override void Add( DrawingElement d ){

elements.Add( d );}public override void Remove( DrawingElement d ){

elements.Remove( d );}public override void Display( int indent ){

Console.WriteLine( new String( '-', indent ) + "+ " + name );

foreach( DrawingElement c in elements )c.Display( indent + 2 );

}}

Page 32: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

ClientClient

CompositeElement root = new CompositeElement( "Picture" );root.Add( new PrimitiveElement( "Red Line" ));root.Add( new PrimitiveElement( "Blue Circle" ));root.Add( new PrimitiveElement( "Green Box" ));

CompositeElement comp = new CompositeElement( "Two Circles" );comp.Add( new PrimitiveElement( "Black Circle" ) );comp.Add( new PrimitiveElement( "White Circle" ) );root.Add( comp );

PrimitiveElement l = new PrimitiveElement( "Yellow Line" );root.Add( l );root.Remove( l );root.Display( 1 );

CompositeElement root = new CompositeElement( "Picture" );root.Add( new PrimitiveElement( "Red Line" ));root.Add( new PrimitiveElement( "Blue Circle" ));root.Add( new PrimitiveElement( "Green Box" ));

CompositeElement comp = new CompositeElement( "Two Circles" );comp.Add( new PrimitiveElement( "Black Circle" ) );comp.Add( new PrimitiveElement( "White Circle" ) );root.Add( comp );

PrimitiveElement l = new PrimitiveElement( "Yellow Line" );root.Add( l );root.Remove( l );root.Display( 1 );

Page 33: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

Decorator Decorator

• Attach additional responsibilities to an object dynamically

• Decorators provide a flexible alternative to subclassing for extending functionality

• Attach additional responsibilities to an object dynamically

• Decorators provide a flexible alternative to subclassing for extending functionality

Page 34: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

ProblemsProblems

• Several classes with a similar operation

(method), but different behavior.

• We want to use many combinations of

these behaviors

• Several classes with a similar operation

(method), but different behavior.

• We want to use many combinations of

these behaviors

Page 35: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

Example - StreamsExample - Streams

• Properties:

– BufferedStream

– CryptoStream

• Objects:

– FileStream

– MemoryStream

– NetworkStream

• Properties:

– BufferedStream

– CryptoStream

• Objects:

– FileStream

– MemoryStream

– NetworkStream

Page 36: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

Solution 1Solution 1• Make all possible classes:

– FileStream

– MemoryStream

– NetworkStream

– BufferedFileStream

– CryptoFileStream

– BufferedMemoryStream

– CryptoMemoryStream

– BufferedNetworkStream

– CryptoNetworkStream

– BufferedCryptoFileStream

– BufferedCryptoNetworkStream

– …..

• Make all possible classes:

– FileStream

– MemoryStream

– NetworkStream

– BufferedFileStream

– CryptoFileStream

– BufferedMemoryStream

– CryptoMemoryStream

– BufferedNetworkStream

– CryptoNetworkStream

– BufferedCryptoFileStream

– BufferedCryptoNetworkStream

– …..

Page 37: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

Problems with solution-1Problems with solution-1

• We don’t have multiple inheritance.

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

• 2n possible classes to create before compilation.

• We don’t have multiple inheritance.

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

• 2n possible classes to create before compilation.

Page 38: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

A Better idea: Use DecoratorA Better idea: Use Decorator

Page 39: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

Code ExampleCode Example

CryptoStream cryptostreamDecr = new CryptoStream(new FileStream( "EncryptedFile.txt“ ,FileMode.Open

,FileAccess.Read), desdecrypt, CryptoStreamMode.Read);

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

aWidget.draw();

CryptoStream cryptostreamDecr = new CryptoStream(new FileStream( "EncryptedFile.txt“ ,FileMode.Open

,FileAccess.Read), desdecrypt, CryptoStreamMode.Read);

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

aWidget.draw();

Page 40: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

interface Widget {

void draw(); }

class TextField : Widget { private int width, height; public TextField( int w, int h ) { width = w; height = h; } public void draw() { Console.WriteLine("TextField: " + width + ", " + height ); } }

interface Widget {

void draw(); }

class TextField : Widget { private int width, height; public TextField( int w, int h ) { width = w; height = h; } public void draw() { Console.WriteLine("TextField: " + width + ", " + height ); } }

ExampleExample

Page 41: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

abstract class Decorator : Widget { private Widget wid; public Decorator( Widget w ) { wid = w; } public virtual void draw() { wid.draw(); } }

class BorderDecorator : Decorator { public BorderDecorator( Widget w ):base(w) { } public override void draw() { base.draw(); Console.WriteLine( “ BorderDecorator" );

} }

class ScrollDecorator : Decorator { public ScrollDecorator( Widget w ) :base(w){ } public override void draw() { base.draw(); Console.WriteLine( " ScrollDecorator" );

} }

abstract class Decorator : Widget { private Widget wid; public Decorator( Widget w ) { wid = w; } public virtual void draw() { wid.draw(); } }

class BorderDecorator : Decorator { public BorderDecorator( Widget w ):base(w) { } public override void draw() { base.draw(); Console.WriteLine( “ BorderDecorator" );

} }

class ScrollDecorator : Decorator { public ScrollDecorator( Widget w ) :base(w){ } public override void draw() { base.draw(); Console.WriteLine( " ScrollDecorator" );

} }

Page 42: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

ClientClient

public static void Main( String[] args ) { Widget aWidget =

new BorderDecorator( new BorderDecorator( new ScrollDecorator(

new TextField( 80, 24 ))));

aWidget.draw();}

public static void Main( String[] args ) { Widget aWidget =

new BorderDecorator( new BorderDecorator( new ScrollDecorator(

new TextField( 80, 24 ))));

aWidget.draw();}

Page 43: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

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?

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

Page 44: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

Facade Facade

Page 45: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

class Bank{public bool SufficientSavings( Customer c ){

Console.WriteLine("Check bank for {0}", c.Name );return true;

}}

class Credit{public bool GoodCredit( int amount, Customer c ){

Console.WriteLine( "Check credit for {0}", c.Name );return true;

}}

class Loan{public bool GoodLoan( Customer c ){

Console.WriteLine( "Check loan for {0}", c.Name );return true;

}}

class Bank{public bool SufficientSavings( Customer c ){

Console.WriteLine("Check bank for {0}", c.Name );return true;

}}

class Credit{public bool GoodCredit( int amount, Customer c ){

Console.WriteLine( "Check credit for {0}", c.Name );return true;

}}

class Loan{public bool GoodLoan( Customer c ){

Console.WriteLine( "Check loan for {0}", c.Name );return true;

}}

Page 46: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

class MortgageApplication{

int amount;private Bank bank = new Bank();private Loan loan = new Loan();private Credit credit = new Credit();public MortgageApplication( int amount ){

this.amount = amount;}

public bool IsEligible( Customer c ){

if( !bank.SufficientSavings( c ) ) return false;

if( !loan.GoodLoan( c ) ) return false;

if( !credit.GoodCredit( amount, c )) return false;

return true;}

}

class MortgageApplication{

int amount;private Bank bank = new Bank();private Loan loan = new Loan();private Credit credit = new Credit();public MortgageApplication( int amount ){

this.amount = amount;}

public bool IsEligible( Customer c ){

if( !bank.SufficientSavings( c ) ) return false;

if( !loan.GoodLoan( c ) ) return false;

if( !credit.GoodCredit( amount, c )) return false;

return true;}

}

Page 47: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

ClientClient

MortgageApplication mortgage =

new MortgageApplication( 125000 );

// Call subsystem through Facade

mortgage.IsEligible(

new Customer( “Bill Gates" ) );

MortgageApplication mortgage =

new MortgageApplication( 125000 );

// Call subsystem through Facade

mortgage.IsEligible(

new Customer( “Bill Gates" ) );

Page 48: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

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

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

Page 49: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

Flyweight Flyweight

Page 50: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

ExampleExample

abstract class Character{

protected char symbol;protected int width;protected int height;protected int ascent;protected int descent;protected int pointSize;

public abstract void Draw( int pointSize );}

abstract class Character{

protected char symbol;protected int width;protected int height;protected int ascent;protected int descent;protected int pointSize;

public abstract void Draw( int pointSize );}

Page 51: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

class CharacterA : Character{

public CharacterA( ){

this.symbol = 'A';this.height = 100;this.width = 120;this.ascent = 70;this.descent = 0;

}

public override void Draw( int pointSize ){

this.pointSize = pointSize;Console.Write( this.symbol );

}}

// repeat for all characters

class CharacterA : Character{

public CharacterA( ){

this.symbol = 'A';this.height = 100;this.width = 120;this.ascent = 70;this.descent = 0;

}

public override void Draw( int pointSize ){

this.pointSize = pointSize;Console.Write( this.symbol );

}}

// repeat for all characters

Page 52: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

class CharacterFactory{

private Hashtable characters = new Hashtable();

public Character GetCharacter( char key ){

Character character = (Character)characters[ key ];if( character == null ){

switch( key ){

case 'A': character = new CharacterA(); break;case 'B': character = new CharacterB(); break;

//...case 'Z': character = new CharacterZ(); break;

}characters.Add( key, character );

}return character;

}}

class CharacterFactory{

private Hashtable characters = new Hashtable();

public Character GetCharacter( char key ){

Character character = (Character)characters[ key ];if( character == null ){

switch( key ){

case 'A': character = new CharacterA(); break;case 'B': character = new CharacterB(); break;

//...case 'Z': character = new CharacterZ(); break;

}characters.Add( key, character );

}return character;

}}

Page 53: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

ClientClient

char[] document = {'A','B','Z','Z','A','A'};

CharacterFactory f = new CharacterFactory();

int pointSize = 12;

foreach( char c in document ){

Character character = f.GetCharacter( c );character.Draw( pointSize );

}

char[] document = {'A','B','Z','Z','A','A'};

CharacterFactory f = new CharacterFactory();

int pointSize = 12;

foreach( char c in document ){

Character character = f.GetCharacter( c );character.Draw( pointSize );

}

Page 54: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

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

• 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

Page 55: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

• 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

• 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

Page 56: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

Proxy Proxy

Page 57: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

Dynamics Dynamics

Page 58: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

ExampleExample

public interface IMath{

double Add( double x, double y );double Sub( double x, double y );double Mul( double x, double y );double Div( double x, double y );

}class Math : MarshalByRefObject, IMath{

public double Add( double x, double y ) { return x + y; }public double Sub( double x, double y ) { return x - y; }public double Mul( double x, double y ){ return x * y; }public double Div( double x, double y ){ return x / y; }

}

public interface IMath{

double Add( double x, double y );double Sub( double x, double y );double Mul( double x, double y );double Div( double x, double y );

}class Math : MarshalByRefObject, IMath{

public double Add( double x, double y ) { return x + y; }public double Sub( double x, double y ) { return x - y; }public double Mul( double x, double y ){ return x * y; }public double Div( double x, double y ){ return x / y; }

}

Page 59: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

class MathProxy : IMath{

Math math;

public MathProxy(){

AppDomain ad = System.AppDomain.CreateDomain( "MathDomain",null, null );

ObjectHandle o = ad.CreateInstance("Proxy","Math",false, System.Reflection.BindingFlags.CreateInstance,

null, null, null,null,null );math = (Math) o.Unwrap();

}

class MathProxy : IMath{

Math math;

public MathProxy(){

AppDomain ad = System.AppDomain.CreateDomain( "MathDomain",null, null );

ObjectHandle o = ad.CreateInstance("Proxy","Math",false, System.Reflection.BindingFlags.CreateInstance,

null, null, null,null,null );math = (Math) o.Unwrap();

}

Page 60: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

public double Add( double x, double y ){

return math.Add(x,y); }public double Sub( double x, double y ){

return math.Sub(x,y); }public double Mul( double x, double y ){

return math.Mul(x,y); }public double Div( double x, double y ){

return math.Div(x,y); }

}

public double Add( double x, double y ){

return math.Add(x,y); }public double Sub( double x, double y ){

return math.Sub(x,y); }public double Mul( double x, double y ){

return math.Mul(x,y); }public double Div( double x, double y ){

return math.Div(x,y); }

}

Page 61: Design Patterns Design principles. The Open/Closed Principle (OCP) A module should be open for extension but closed for modification.

ClientClient

MathProxy p = new MathProxy();

Console.WriteLine( "4 + 2 = {0}", p.Add( 4, 2 ) );

Console.WriteLine( "4 - 2 = {0}", p.Sub( 4, 2 ) );

Console.WriteLine( "4 * 2 = {0}", p.Mul( 4, 2 ) );

Console.WriteLine( "4 / 2 = {0}", p.Div( 4, 2 ) );

MathProxy p = new MathProxy();

Console.WriteLine( "4 + 2 = {0}", p.Add( 4, 2 ) );

Console.WriteLine( "4 - 2 = {0}", p.Sub( 4, 2 ) );

Console.WriteLine( "4 * 2 = {0}", p.Mul( 4, 2 ) );

Console.WriteLine( "4 / 2 = {0}", p.Div( 4, 2 ) );