design patterns
Download
Skip this Video
Download Presentation
Design Patterns

Loading in 2 Seconds...

play fullscreen
1 / 61

Design Patterns - PowerPoint PPT Presentation


  • 63 Views
  • Uploaded on

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

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


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

Design principles

the open closed principle ocp

The Open/Closed Principle (OCP)

A module should be open for extension but closed for modification.

the open closed principle
The 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

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
summery
Summery
  • 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.
the liskov substitution principle lsp

The Liskov Substitution Principle (LSP)

Subclasses should be substitutable for their base classes.

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 functiontakes 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.
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.
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
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
demo code
Demo code

public interface ICar

{

void Drive();

}

public class CToyota : ICar

{

public void Drive()

{

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

}

}

slide16
public class CCessna

{

public void Fly()

{

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

}

}

// the adapter class

public class CDrivableCessna : CCessna, ICar

{

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

}

client
Client

ICar oCar = new CToyota();

oCar.Drive();

oCar = new CDrivableCessna();

oCar.Drive();

other solution
Other solution

public class CDrivableCessna2 : ICar

{

private CCessna m_oContained;

public CDrivableCessna2()

{

m_oContained = new CCessna();

}

public void Drive()

{

m_oContained.Fly();

}

}

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

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

}

slide22
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 );

}

}

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

}

}

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

} }

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

} }

client1
Client

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

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

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

}

slide30
Leaf

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

}

}

slide31
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 );

}

}

client2
Client

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

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 streams
Example - Streams
  • Properties:
    • BufferedStream
    • CryptoStream
  • Objects:
    • FileStream
    • MemoryStream
    • NetworkStream
solution 1
Solution 1
  • Make all possible classes:
    • FileStream
    • MemoryStream
    • NetworkStream
    • BufferedFileStream
    • CryptoFileStream
    • BufferedMemoryStream
    • CryptoMemoryStream
    • BufferedNetworkStream
    • CryptoNetworkStream
    • BufferedCryptoFileStream
    • BufferedCryptoNetworkStream
    • …..
problems with solution 1
Problems 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.
code example
Code 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();

example1
Example

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

}

}

slide41
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" );

}

}

client3
Client

public static void Main( String[] args )

{

Widget aWidget =

new BorderDecorator(

new BorderDecorator(

new ScrollDecorator(

new TextField( 80, 24 ))));

aWidget.draw();

}

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?
slide45
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;

}

}

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

}

}

client4
Client

MortgageApplication mortgage =

new MortgageApplication( 125000 );

// Call subsystem through Facade

mortgage.IsEligible(

new Customer( “Bill Gates" ) );

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

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

}

slide51
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

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

}

}

client5
Client

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

}

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
slide55
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
example3
Example

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

}

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

}

slide60
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);

}

}

client6
Client

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

ad