design patterns behavioral patterns. the dependency inversion principle (dip) depend upon...

105
Design Patterns Behavioral Patterns

Upload: stephen-norman

Post on 30-Dec-2015

221 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

Design PatternsDesign Patterns

Behavioral Patterns Behavioral Patterns

Page 2: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

The Dependency Inversion Principle (DIP)

The Dependency Inversion Principle (DIP)

Depend upon Abstractions. Do not depend upon concretions.

Depend upon Abstractions. Do not depend upon concretions.

Page 3: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

The Dependency Inversion Principle (DIP)The Dependency Inversion Principle (DIP)

• Dependency Inversion is the strategy of depending upon interfaces or abstract functions and classes, rather than upon concrete functions and classes.

• Every dependency in the design should target an interface, or an abstract class. No dependency should target a concrete class.

• Dependency Inversion is the strategy of depending upon interfaces or abstract functions and classes, rather than upon concrete functions and classes.

• Every dependency in the design should target an interface, or an abstract class. No dependency should target a concrete class.

Page 4: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

The Dependency Inversion Principle (DIP) ExampleDependency Structure of a Procedural Architecture

The Dependency Inversion Principle (DIP) ExampleDependency Structure of a Procedural Architecture

main

HighLevelFn1 HighLevelFn2 HighLevelFn3

LowLevelFn1 LowLevelFn2 LowLevelFn3 LowLevelFn4

Page 5: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

The Dependency Inversion Principle (DIP) ExampleDependency Structure of an Object Oriented Architecture

The Dependency Inversion Principle (DIP) ExampleDependency Structure of an Object Oriented Architecture

HighLevel

AbstractInterface1<<Interface>>

AbstractInterface2<<Interface>>

AbstractInterface3<<Interface>>

DetailImpl1 DetailImpl2 DetailImpl3

Page 6: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

The Dependency Inversion Principle (DIP) DiscussionThe Dependency Inversion Principle (DIP) Discussion

• Typically, Concrete things change a lot • abstract things change much less frequently.• One of the most common places that designs depend

upon concrete classes is when those designs create instances.

• By definition, you cannot create instances of abstract classes.

• Solution to this problem: use Abstract Factory

• Typically, Concrete things change a lot • abstract things change much less frequently.• One of the most common places that designs depend

upon concrete classes is when those designs create instances.

• By definition, you cannot create instances of abstract classes.

• Solution to this problem: use Abstract Factory

Page 7: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

The Interface Segregation Principle (ISP)

The Interface Segregation Principle (ISP)

Many client specific interfaces are better than one general purpose

interface

Many client specific interfaces are better than one general purpose

interface

Page 8: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

The Interface Segregation Principle (ISP)The Interface Segregation Principle (ISP)

• If you have a class that has several clients, rather than loading the class with all the methods that the clients need, create specific interfaces for each type of client and multiply inherit them into the class.

• If you have a class that has several clients, rather than loading the class with all the methods that the clients need, create specific interfaces for each type of client and multiply inherit them into the class.

Page 9: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

The Interface Segregation Principle (ISP) ExampleFat Service with Integrated Interfaces

The Interface Segregation Principle (ISP) ExampleFat Service with Integrated Interfaces

ClientA

ClientB

ClientC

Service

clientAMethods()clientBMethods()clientCMethods()

<<Interface>>

Page 10: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

The Interface Segregation Principle (ISP) ExampleSegregated Interfaces

The Interface Segregation Principle (ISP) ExampleSegregated Interfaces

ClientA

ClientB

ClientC

ClientAService

clientAMethods()

<<Interface>>

ClientBService

clientBMethods()

<<Interface>>

ClientCService

clientCMethods()

<<Interface>>

ServiceImpl

clientAMethods()clientBMethods()clientCMethods()

Page 11: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

The Interface Segregation Principle (ISP) DiscussionThe Interface Segregation Principle (ISP) Discussion

• Without segregation whenever a change is made to one of the methods that ClientA calls, ClientB and ClientC may be affected. It may be necessary to recompile and redeploy them. With segregation if the interface for ClientA needs to change, ClientB and ClientC will remain unaffected.

• The ISP does not recommend that every class that uses a service have its own special interface class that the service must inherit from. Rather, clients should be categorized by their type, and interfaces for each type of client should be created. If two or more different client types need the same method, the method should be added to both of their interfaces.

• Without segregation whenever a change is made to one of the methods that ClientA calls, ClientB and ClientC may be affected. It may be necessary to recompile and redeploy them. With segregation if the interface for ClientA needs to change, ClientB and ClientC will remain unaffected.

• The ISP does not recommend that every class that uses a service have its own special interface class that the service must inherit from. Rather, clients should be categorized by their type, and interfaces for each type of client should be created. If two or more different client types need the same method, the method should be added to both of their interfaces.

Page 12: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

The Acyclic Dependencies Principle (ADP)

The Acyclic Dependencies Principle (ADP)

The dependencies betwen packages must not form cycles.

The dependencies betwen packages must not form cycles.

Page 13: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

The Acyclic Dependencies Principle (ADP)

The Acyclic Dependencies Principle (ADP)

• Once changes to a package are made, developers can release the packages to the rest of the project. Before they can do this release, however, they must test that the package works. To do that, they must compile and build it with all the packages it depends upon.

• A single cyclic dependency that gets out of control can make the dependency list very long.

• Hence, someone needs to be watching the package dependency structure with regularity, and breaking cycles wherever they appear.

• Once changes to a package are made, developers can release the packages to the rest of the project. Before they can do this release, however, they must test that the package works. To do that, they must compile and build it with all the packages it depends upon.

• A single cyclic dependency that gets out of control can make the dependency list very long.

• Hence, someone needs to be watching the package dependency structure with regularity, and breaking cycles wherever they appear.

Page 14: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

The Acyclic Dependencies Principle (ADP) ExampleAcyclic Package Network

The Acyclic Dependencies Principle (ADP) ExampleAcyclic Package Network

gui

comm

modem protocol

comm_error

process

file

Page 15: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

The Acyclic Dependencies Principle (ADP) ExampleCyclic Package Network

The Acyclic Dependencies Principle (ADP) ExampleCyclic Package Network

gui

comm

modem protocol

comm_error

process

file

Page 16: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

The Acyclic Dependencies Principle (ADP) Discussion

The Acyclic Dependencies Principle (ADP) Discussion

• In the acyclic scenario to release the protocol package, the engineers would have to build it with the latest release of the comm_error package, and run their tests.

• In the cyclic scenario to release protocol, the engineers would have to build it with the latest release of the comm_error, gui, comm, process, modem, file and run their tests.

• Breaking the cycle:– Add new package in between– Add a new Interface

• In the acyclic scenario to release the protocol package, the engineers would have to build it with the latest release of the comm_error package, and run their tests.

• In the cyclic scenario to release protocol, the engineers would have to build it with the latest release of the comm_error, gui, comm, process, modem, file and run their tests.

• Breaking the cycle:– Add new package in between– Add a new Interface

Page 17: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

Behavioral patternsBehavioral patterns

• Behavioral patterns are concerned with algorithms and the assignment of responsibilities between objects

• Behavioral patterns describe not just patterns of objects or classes but also the patterns of communication between them.

• Behavioral patterns are concerned with algorithms and the assignment of responsibilities between objects

• Behavioral patterns describe not just patterns of objects or classes but also the patterns of communication between them.

Page 18: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

Chain of Responsibility Chain of Responsibility

• Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request.

• Chain the receiving objects and pass the request along the chain until an object handles it

• Use When:– more than on object may handle a request, and the

handler isn't known a priori– When you want to issue a request to one of several

objects without specifying the receiver explicitly – When the set of objects that can handle a request

should be specified dynamically

• Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request.

• Chain the receiving objects and pass the request along the chain until an object handles it

• Use When:– more than on object may handle a request, and the

handler isn't known a priori– When you want to issue a request to one of several

objects without specifying the receiver explicitly – When the set of objects that can handle a request

should be specified dynamically

Page 19: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

Chain of Responsibility Chain of Responsibility

Page 20: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

HandlerHandler

abstract class Approver{

protected string name;protected Approver successor;

public Approver( string name ){

this.name = name;}

public void SetSuccessor( Approver successor ){

this.successor = successor;}

abstract public void ProcessRequest(PurchaseRequest request );}

abstract class Approver{

protected string name;protected Approver successor;

public Approver( string name ){

this.name = name;}

public void SetSuccessor( Approver successor ){

this.successor = successor;}

abstract public void ProcessRequest(PurchaseRequest request );}

Page 21: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

Concrete HandlerConcrete Handler

class Director : Approver{

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

override public void ProcessRequest( PurchaseRequest request ){

if( request.Amount < 10000.0 )Console.WriteLine( "{0} {1} approved request# {2}",

this, name, request.Number);else

if( successor != null )successor.ProcessRequest( request );

}}

class Director : Approver{

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

override public void ProcessRequest( PurchaseRequest request ){

if( request.Amount < 10000.0 )Console.WriteLine( "{0} {1} approved request# {2}",

this, name, request.Number);else

if( successor != null )successor.ProcessRequest( request );

}}

Page 22: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

class VicePresident : Approver{

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

override public void ProcessRequest( PurchaseRequest request ){

if( request.Amount < 25000.0 )Console.WriteLine( "{0} {1} approved request# {2}",

this, name, request.Number);else

if( successor != null )successor.ProcessRequest( request );

}}

class VicePresident : Approver{

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

override public void ProcessRequest( PurchaseRequest request ){

if( request.Amount < 25000.0 )Console.WriteLine( "{0} {1} approved request# {2}",

this, name, request.Number);else

if( successor != null )successor.ProcessRequest( request );

}}

Page 23: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

class President : Approver{

public President ( string name ) : base( name ) {}override public void ProcessRequest( PurchaseRequest request ){

if( request.Amount < 100000.0 )Console.WriteLine( "{0} {1} approved request# {2}",

this, name, request.Number);else

Console.WriteLine( "Request# {0} requires " +"an executive meeting!", request.Number );

}}

class President : Approver{

public President ( string name ) : base( name ) {}override public void ProcessRequest( PurchaseRequest request ){

if( request.Amount < 100000.0 )Console.WriteLine( "{0} {1} approved request# {2}",

this, name, request.Number);else

Console.WriteLine( "Request# {0} requires " +"an executive meeting!", request.Number );

}}

Page 24: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

ClientClient

Director Larry = new Director( "Larry" );VicePresident Sam = new VicePresident( "Sam" );President Tammy = new President( "Tammy" );Larry.SetSuccessor( Sam );Sam.SetSuccessor( Tammy );

PurchaseRequest rs = new PurchaseRequest(2034, 350.00, "Supplies" );Larry.ProcessRequest( rs );

PurchaseRequest rx = new PurchaseRequest(2035, 32590.10, "Project X" );Larry.ProcessRequest( rx );

PurchaseRequest ry = new PurchaseRequest(2036, 122100.00, "Project Y" );Larry.ProcessRequest( ry );

Director Larry = new Director( "Larry" );VicePresident Sam = new VicePresident( "Sam" );President Tammy = new President( "Tammy" );Larry.SetSuccessor( Sam );Sam.SetSuccessor( Tammy );

PurchaseRequest rs = new PurchaseRequest(2034, 350.00, "Supplies" );Larry.ProcessRequest( rs );

PurchaseRequest rx = new PurchaseRequest(2035, 32590.10, "Project X" );Larry.ProcessRequest( rx );

PurchaseRequest ry = new PurchaseRequest(2036, 122100.00, "Project Y" );Larry.ProcessRequest( ry );

Page 25: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

Command Command

• Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations

• Use When you need an action as a parameter• Commands replace callback functions • When you need to specify, queue, and execute

requests at different times• When you need to support undo • When you need to support logging changes

• Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations

• Use When you need an action as a parameter• Commands replace callback functions • When you need to specify, queue, and execute

requests at different times• When you need to support undo • When you need to support logging changes

Page 26: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

Command Command

Page 27: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

abstract class Command

{

abstract public void Execute();

abstract public void UnExecute();

}

abstract class Command

{

abstract public void Execute();

abstract public void UnExecute();

}

Command ExampleCommand Example

Page 28: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

class CalculatorCommand : Command{ char _operator; int operand; Calculator calculator; public CalculatorCommand(Calculator calculator,char operator, int op ) { this.calculator = calculator; this._operator = _operator; this.operand = op; } public char Operator { set{ _operator = value; } } public int Operand { set{ operand = value; } }

class CalculatorCommand : Command{ char _operator; int operand; Calculator calculator; public CalculatorCommand(Calculator calculator,char operator, int op ) { this.calculator = calculator; this._operator = _operator; this.operand = op; } public char Operator { set{ _operator = value; } } public int Operand { set{ operand = value; } }

Page 29: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

override public void Execute() { calculator.Operation( _operator, operand ); } override public void UnExecute() { calculator.Operation( Undo( _operator ), operand ); } private char Undo( char _operator ) { char undo = ' '; switch( _operator ) { case '+': undo = '-'; break; case '-': undo = '+'; break; case '*': undo = '/'; break; case '/': undo = '*'; break; } return undo; }}

override public void Execute() { calculator.Operation( _operator, operand ); } override public void UnExecute() { calculator.Operation( Undo( _operator ), operand ); } private char Undo( char _operator ) { char undo = ' '; switch( _operator ) { case '+': undo = '-'; break; case '-': undo = '+'; break; case '*': undo = '/'; break; case '/': undo = '*'; break; } return undo; }}

Page 30: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

ReceiverReceiver

class Calculator{ private int total = 0; public void Operation( char _operator, int operand ) { switch( _operator ) { case '+': total += operand; break; case '-': total -= operand; break; case '*': total *= operand; break; case '/': total /= operand; break; } Console.WriteLine( "Total = {0} (following {1} {2})", total, _operator, operand ); }}

class Calculator{ private int total = 0; public void Operation( char _operator, int operand ) { switch( _operator ) { case '+': total += operand; break; case '-': total -= operand; break; case '*': total *= operand; break; case '/': total /= operand; break; } Console.WriteLine( "Total = {0} (following {1} {2})", total, _operator, operand ); }}

Page 31: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

InvokerInvoker

class User

{

private Calculator calculator = new Calculator();

private ArrayList commands = new ArrayList();

private int current = 0;

public void Redo( int levels )

{

Console.WriteLine( "---- Redo {0} levels ", levels );

for( int i = 0; i < levels; i++ )

if( current < commands.Count - 1 )

((Command)commands[ current++ ]).Execute();

}

class User

{

private Calculator calculator = new Calculator();

private ArrayList commands = new ArrayList();

private int current = 0;

public void Redo( int levels )

{

Console.WriteLine( "---- Redo {0} levels ", levels );

for( int i = 0; i < levels; i++ )

if( current < commands.Count - 1 )

((Command)commands[ current++ ]).Execute();

}

Page 32: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

public void Undo( int levels )

{

Console.WriteLine( "---- Undo {0} levels ", levels );

for( int i = 0; i < levels; i++ )

if( current > 0 )

((Command)commands[ --current ]).UnExecute();

}

public void Compute( char _operator, int operand )

{

Command command = new CalculatorCommand(

calculator, _operator, operand );

command.Execute();

commands.Add( command );

current++;

}

public void Undo( int levels )

{

Console.WriteLine( "---- Undo {0} levels ", levels );

for( int i = 0; i < levels; i++ )

if( current > 0 )

((Command)commands[ --current ]).UnExecute();

}

public void Compute( char _operator, int operand )

{

Command command = new CalculatorCommand(

calculator, _operator, operand );

command.Execute();

commands.Add( command );

current++;

}

Page 33: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

ClientClient

User user = new User();

user.Compute( '+', 100 );user.Compute( '-', 50 );user.Compute( '*', 10 );user.Compute( '/', 2 );

user.Undo( 4 );user.Redo( 3 );

User user = new User();

user.Compute( '+', 100 );user.Compute( '-', 50 );user.Compute( '*', 10 );user.Compute( '/', 2 );

user.Undo( 4 );user.Redo( 3 );

Page 34: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

Interpreter Interpreter

• Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language

• you create a class for each rule

• The classes can be used to construct a tree that represents elements of the language

• Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language

• you create a class for each rule

• The classes can be used to construct a tree that represents elements of the language

Page 35: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

Interpreter Interpreter

Page 36: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

class Context{ private string input; private int output; public Context( string input ) { this.input = input; } public string Input { get{ return input; } set{ input = value; } } public int Output { get{ return output; } set{ output = value; } }}

class Context{ private string input; private int output; public Context( string input ) { this.input = input; } public string Input { get{ return input; } set{ input = value; } } public int Output { get{ return output; } set{ output = value; } }}

Page 37: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

Abstract ExpressionAbstract Expression

abstract class Expression

{

public abstract string One();

public abstract string Four();

public abstract string Five();

public abstract string Nine();

public abstract int Multiplier();

abstract class Expression

{

public abstract string One();

public abstract string Four();

public abstract string Five();

public abstract string Nine();

public abstract int Multiplier();

Page 38: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

public void Interpret( Context context ) { if( context.Input.Length == 0 ) return; if( context.Input.StartsWith( Nine() ) ) { context.Output += 9 * Multiplier(); context.Input = context.Input.Substring(2);

} else if( context.Input.StartsWith( Four() ) ) { context.Output += 4 * Multiplier(); context.Input = context.Input.Substring( 2); } else if( context.Input.StartsWith( Five() ) ) { context.Output += 5 * Multiplier(); context.Input = context.Input.Substring( 1); } while( context.Input.StartsWith( One() ) ) { context.Output += 1 * Multiplier(); context.Input = context.Input.Substring( 1 ); } }

public void Interpret( Context context ) { if( context.Input.Length == 0 ) return; if( context.Input.StartsWith( Nine() ) ) { context.Output += 9 * Multiplier(); context.Input = context.Input.Substring(2);

} else if( context.Input.StartsWith( Four() ) ) { context.Output += 4 * Multiplier(); context.Input = context.Input.Substring( 2); } else if( context.Input.StartsWith( Five() ) ) { context.Output += 5 * Multiplier(); context.Input = context.Input.Substring( 1); } while( context.Input.StartsWith( One() ) ) { context.Output += 1 * Multiplier(); context.Input = context.Input.Substring( 1 ); } }

Page 39: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

class ThousandExpression : Expression

{

public override string One() { return "M"; }

public override string Four(){ return " "; }

public override string Five(){ return " "; }

public override string Nine(){ return " "; }

public override int Multiplier() { return 1000; }

}

class HundredExpression : Expression

{

public override string One() { return "C"; }

public override string Four(){ return "CD"; }

public override string Five(){ return "D"; }

public override string Nine(){ return "CM"; }

public override int Multiplier() { return 100; }

}

class ThousandExpression : Expression

{

public override string One() { return "M"; }

public override string Four(){ return " "; }

public override string Five(){ return " "; }

public override string Nine(){ return " "; }

public override int Multiplier() { return 1000; }

}

class HundredExpression : Expression

{

public override string One() { return "C"; }

public override string Four(){ return "CD"; }

public override string Five(){ return "D"; }

public override string Nine(){ return "CM"; }

public override int Multiplier() { return 100; }

}

Page 40: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

class TenExpression : Expression

{

public override string One() { return "X"; }

public override string Four(){ return "XL"; }

public override string Five(){ return "L"; }

public override string Nine(){ return "XC"; }

public override int Multiplier() { return 10; }

}

class OneExpression : Expression

{

public override string One() { return "I"; }

public override string Four(){ return "IV"; }

public override string Five(){ return "V"; }

public override string Nine(){ return "IX"; }

public override int Multiplier() { return 1; }

}

class TenExpression : Expression

{

public override string One() { return "X"; }

public override string Four(){ return "XL"; }

public override string Five(){ return "L"; }

public override string Nine(){ return "XC"; }

public override int Multiplier() { return 10; }

}

class OneExpression : Expression

{

public override string One() { return "I"; }

public override string Four(){ return "IV"; }

public override string Five(){ return "V"; }

public override string Nine(){ return "IX"; }

public override int Multiplier() { return 1; }

}

Page 41: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

ClientClient

string roman = "MCMXXVIII";

Context context = new Context( roman );

ArrayList parse = new ArrayList();

parse.Add(new ThousandExpression());

parse.Add(new HundredExpression());

parse.Add(new TenExpression());

parse.Add(new OneExpression());

foreach( Expression exp in parse )

exp.Interpret( context );

Console.WriteLine( "{0} = {1}",roman, context.Output );

string roman = "MCMXXVIII";

Context context = new Context( roman );

ArrayList parse = new ArrayList();

parse.Add(new ThousandExpression());

parse.Add(new HundredExpression());

parse.Add(new TenExpression());

parse.Add(new OneExpression());

foreach( Expression exp in parse )

exp.Interpret( context );

Console.WriteLine( "{0} = {1}",roman, context.Output );

Page 42: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

Iterator Iterator

• Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation

• methods:– movenext()– getcur()– eof()

• Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation

• methods:– movenext()– getcur()– eof()

Page 43: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

Iterator Iterator

Page 44: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

class Item

{

string name;

public Item( string name )

{

this.name = name;

}

public string Name

{

get{ return name; }

}

}

class Item

{

string name;

public Item( string name )

{

this.name = name;

}

public string Name

{

get{ return name; }

}

}

Page 45: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

abstract class AbstractCollection{ abstract public Iterator CreateIterator();}class Collection : AbstractCollection{ private ArrayList items = new ArrayList(); public override Iterator CreateIterator() { return new Iterator( this ); } public int Count { get{ return items.Count; } } public object this[ int index ] { get{ return items[ index ]; } set{ items.Add( value ); } }}

abstract class AbstractCollection{ abstract public Iterator CreateIterator();}class Collection : AbstractCollection{ private ArrayList items = new ArrayList(); public override Iterator CreateIterator() { return new Iterator( this ); } public int Count { get{ return items.Count; } } public object this[ int index ] { get{ return items[ index ]; } set{ items.Add( value ); } }}

Page 46: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

abstract class AbstractIterator{ abstract public Item First(); abstract public Item Next(); abstract public bool IsDone(); abstract public Item CurrentItem();}class Iterator : AbstractIterator{ private Collection collection; private int current = 0; private int step = 1; public Iterator( Collection collection ) { this.collection = collection; } public int Step { get{ return step; } set{ step = value; } }

abstract class AbstractIterator{ abstract public Item First(); abstract public Item Next(); abstract public bool IsDone(); abstract public Item CurrentItem();}class Iterator : AbstractIterator{ private Collection collection; private int current = 0; private int step = 1; public Iterator( Collection collection ) { this.collection = collection; } public int Step { get{ return step; } set{ step = value; } }

Page 47: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

override public Item First() { current = 0; return (Item)collection[ current ]; } override public Item Next() { current += step; if( !IsDone() ) return (Item)collection[ current ]; else return null; } override public Item CurrentItem() { return (Item)collection[ current ]; } override public bool IsDone() { return current >= collection.Count ? true : false ; }

override public Item First() { current = 0; return (Item)collection[ current ]; } override public Item Next() { current += step; if( !IsDone() ) return (Item)collection[ current ]; else return null; } override public Item CurrentItem() { return (Item)collection[ current ]; } override public bool IsDone() { return current >= collection.Count ? true : false ; }

Page 48: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

ClientClient

Collection collection = new Collection();

collection[0] = new Item( "Item 0" );

collection[1] = new Item( "Item 1" );

:

collection[8] = new Item( "Item 8" );

Iterator iterator = new Iterator( collection );

iterator.Step = 2;

for( Item item = iterator.First(); !iterator.IsDone(); item = iterator.Next() )

{

Console.WriteLine( item.Name );

}

Collection collection = new Collection();

collection[0] = new Item( "Item 0" );

collection[1] = new Item( "Item 1" );

:

collection[8] = new Item( "Item 8" );

Iterator iterator = new Iterator( collection );

iterator.Step = 2;

for( Item item = iterator.First(); !iterator.IsDone(); item = iterator.Next() )

{

Console.WriteLine( item.Name );

}

Page 49: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

Mediator Mediator

• Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently

• Defines an interface for communicating with Colleague objects

• Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently

• Defines an interface for communicating with Colleague objects

Page 50: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

Mediator Mediator

Page 51: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

ExampleExample

interface IChatroom

{

void Register( Participant participant );

void Send( string from, string to, string message );

}

interface IChatroom

{

void Register( Participant participant );

void Send( string from, string to, string message );

}

Page 52: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

class Chatroom : IChatroom{ private Hashtable participants = new Hashtable();

public void Register( Participant participant ) { if( participants[ participant.Name ] == null ) participants[ participant.Name ] = participant;

participant.Chatroom = this; }

public void Send( string from, string to, string message ) { Participant pto = (Participant)participants[ to ]; if( pto != null ) pto.Receive( from, message ); }}

class Chatroom : IChatroom{ private Hashtable participants = new Hashtable();

public void Register( Participant participant ) { if( participants[ participant.Name ] == null ) participants[ participant.Name ] = participant;

participant.Chatroom = this; }

public void Send( string from, string to, string message ) { Participant pto = (Participant)participants[ to ]; if( pto != null ) pto.Receive( from, message ); }}

Page 53: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

class Participant{ private Chatroom chatroom; private string name; public Participant( string name ) { this.name = name; } public string Name { get{ return name; } } public Chatroom Chatroom { set{ chatroom = value; } get{ return chatroom; } } public void Send( string to, string message ) { chatroom.Send( name, to, message ); } virtual public void Receive(string from, string message ) { Console.WriteLine( "{0} to {1}: '{2}'",from, this.name, message ); }}

class Participant{ private Chatroom chatroom; private string name; public Participant( string name ) { this.name = name; } public string Name { get{ return name; } } public Chatroom Chatroom { set{ chatroom = value; } get{ return chatroom; } } public void Send( string to, string message ) { chatroom.Send( name, to, message ); } virtual public void Receive(string from, string message ) { Console.WriteLine( "{0} to {1}: '{2}'",from, this.name, message ); }}

Page 54: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

class BeatleParticipant : Participant{public BeatleParticipant( string name ) : base ( name ) { }override public void Receive( string from, string message ) { Console.Write( "To a Beatle: " ); base.Receive( from, message ); }}class NonBeatleParticipant : Participant{public NonBeatleParticipant( string name ) : base ( name ) { } override public void Receive(string from, string message ) { Console.Write( "To a non-Beatle: " ); base.Receive( from, message ); }}

class BeatleParticipant : Participant{public BeatleParticipant( string name ) : base ( name ) { }override public void Receive( string from, string message ) { Console.Write( "To a Beatle: " ); base.Receive( from, message ); }}class NonBeatleParticipant : Participant{public NonBeatleParticipant( string name ) : base ( name ) { } override public void Receive(string from, string message ) { Console.Write( "To a non-Beatle: " ); base.Receive( from, message ); }}

Page 55: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

ClientClient

Chatroom c = new Chatroom();Participant George = new BeatleParticipant("George");Participant Paul = new BeatleParticipant("Paul");Participant Ringo = new BeatleParticipant("Ringo");Participant John = new BeatleParticipant("John") ;Participant Yoko = new NonBeatleParticipant("Yoko");c.Register( George );c.Register( Paul );c.Register( Ringo );c.Register( John );c.Register( Yoko );Yoko.Send( "John", "Hi John!" );Paul.Send( "Ringo", "All you need is love" );Ringo.Send( "George", "My sweet Lord" );Paul.Send( "John", "Can't buy me love" );John.Send( "Yoko", "My sweet love" ) ;

Chatroom c = new Chatroom();Participant George = new BeatleParticipant("George");Participant Paul = new BeatleParticipant("Paul");Participant Ringo = new BeatleParticipant("Ringo");Participant John = new BeatleParticipant("John") ;Participant Yoko = new NonBeatleParticipant("Yoko");c.Register( George );c.Register( Paul );c.Register( Ringo );c.Register( John );c.Register( Yoko );Yoko.Send( "John", "Hi John!" );Paul.Send( "Ringo", "All you need is love" );Ringo.Send( "George", "My sweet Lord" );Paul.Send( "John", "Can't buy me love" );John.Send( "Yoko", "My sweet love" ) ;

Page 56: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

Memento Memento

• Without violating encapsulation, capture and externalize an object's internal state so that the object can be returned to this state later

• Allow undos, rollbacks, etc.• But we have Command and Clone, why do we

need another pattern for undo?– Clone can be more expensive than we need

• Only part of the state of an object may change, cloning will copy all the state

• Cloning can be hard to implement • Replacing an object with a clone does not work when other

objects have references to the object to rollback

• Without violating encapsulation, capture and externalize an object's internal state so that the object can be returned to this state later

• Allow undos, rollbacks, etc.• But we have Command and Clone, why do we

need another pattern for undo?– Clone can be more expensive than we need

• Only part of the state of an object may change, cloning will copy all the state

• Cloning can be hard to implement • Replacing an object with a clone does not work when other

objects have references to the object to rollback

Page 57: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

Memento Memento

Page 58: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

class SalesProspect{ private string name; private string phone; private double budget; public string Name { get{ return name; } set{ name = value; } } public string Phone { get{ return phone; } set{ phone = value; } } public double Budget { get{ return budget; } set{ budget = value; } }

class SalesProspect{ private string name; private string phone; private double budget; public string Name { get{ return name; } set{ name = value; } } public string Phone { get{ return phone; } set{ phone = value; } } public double Budget { get{ return budget; } set{ budget = value; } }

Page 59: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

• public Memento SaveMemento()• {• return (new Memento( name, phone, budget ));• }• public void RestoreMemento( Memento memento )• {• this.name = memento.Name;• this.phone = memento.Phone;• this.budget = memento.Budget;• }• public void Show()• {• Console.WriteLine( "\nSales prospect ---- " );• Console.WriteLine( "Name: {0}", this.name );• Console.WriteLine( "Phone: {0}", this.phone );• Console.WriteLine( "Budget: {0:C}", this.budget );• }

• public Memento SaveMemento()• {• return (new Memento( name, phone, budget ));• }• public void RestoreMemento( Memento memento )• {• this.name = memento.Name;• this.phone = memento.Phone;• this.budget = memento.Budget;• }• public void Show()• {• Console.WriteLine( "\nSales prospect ---- " );• Console.WriteLine( "Name: {0}", this.name );• Console.WriteLine( "Phone: {0}", this.phone );• Console.WriteLine( "Budget: {0:C}", this.budget );• }

Page 60: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

class Memento

{

private string name;

private string phone;

private double budget;

public Memento(string name,string phone,double budget)

{ this.name = name;

this.phone = phone;

this.budget = budget;

}

public string Name

{

get{ return name; }

set{ name = value; }

}

// also for phone and budget

}

class Memento

{

private string name;

private string phone;

private double budget;

public Memento(string name,string phone,double budget)

{ this.name = name;

this.phone = phone;

this.budget = budget;

}

public string Name

{

get{ return name; }

set{ name = value; }

}

// also for phone and budget

}

Page 61: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

class ProspectMemory{ private Memento memento;

public Memento Memento { set{ memento = value; } get{ return memento; } }}

class ProspectMemory{ private Memento memento;

public Memento Memento { set{ memento = value; } get{ return memento; } }}

Page 62: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

ClientClientSalesProspect s = new SalesProspect();s.Name = "Noel van Halen";s.Phone = "(412) 256-0990";s.Budget = 25000.0;s.Show();

ProspectMemory m = new ProspectMemory();m.Memento = s.SaveMemento();

s.Name = "Leo Welch";s.Phone = "(310) 209-7111";s.Budget = 1000000.0;s.Show();

s.RestoreMemento( m.Memento );s.Show();

SalesProspect s = new SalesProspect();s.Name = "Noel van Halen";s.Phone = "(412) 256-0990";s.Budget = 25000.0;s.Show();

ProspectMemory m = new ProspectMemory();m.Memento = s.SaveMemento();

s.Name = "Leo Welch";s.Phone = "(310) 209-7111";s.Budget = 1000000.0;s.Show();

s.RestoreMemento( m.Memento );s.Show();

Page 63: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

Observer Observer

• Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

• Use the Observer pattern: – When an abstraction has two aspects, one dependent

on the other. – When a change to one object requires changing

others, and you don't how many objects need to be changed

– When an object should be able to notify other objects without making assumptions about who these objects are.

• Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

• Use the Observer pattern: – When an abstraction has two aspects, one dependent

on the other. – When a change to one object requires changing

others, and you don't how many objects need to be changed

– When an object should be able to notify other objects without making assumptions about who these objects are.

Page 64: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

Observer Observer

Page 65: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

abstract class Stock{ protected string symbol; protected double price; private ArrayList investors = new ArrayList(); public Stock( string symbol, double price ) {

this.symbol = symbol; this.price = price;

} public void Attach( Investor investor ) { investors.Add( investor ); } public void Detach( Investor investor ) { investors.Remove( investor ); }

abstract class Stock{ protected string symbol; protected double price; private ArrayList investors = new ArrayList(); public Stock( string symbol, double price ) {

this.symbol = symbol; this.price = price;

} public void Attach( Investor investor ) { investors.Add( investor ); } public void Detach( Investor investor ) { investors.Remove( investor ); }

Page 66: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

public void Notify() { foreach( Investor i in investors ) i.Update( this ); } public double Price { get{ return price; } set{ price = value; Notify(); } } public string Symbol { get{ return symbol; } set{ symbol = value; } }}class IBM : Stock{ public IBM( string symbol, double price ) : base( symbol, price ) {}}

public void Notify() { foreach( Investor i in investors ) i.Update( this ); } public double Price { get{ return price; } set{ price = value; Notify(); } } public string Symbol { get{ return symbol; } set{ symbol = value; } }}class IBM : Stock{ public IBM( string symbol, double price ) : base( symbol, price ) {}}

Page 67: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

interface IInvestor{

void Update( Stock stock ); }class Investor : IInvestor{ private string name; private string observerState; private Stock stock; public Investor( string name ) { this.name = name; } public void Update( Stock stock ) { Console.WriteLine( "Notified investor {0} of {1}'s " + change to {2:C}", name, stock.Symbol, stock.Price ); } public Stock Stock { get{ return stock; } set{ stock = value; } }}

interface IInvestor{

void Update( Stock stock ); }class Investor : IInvestor{ private string name; private string observerState; private Stock stock; public Investor( string name ) { this.name = name; } public void Update( Stock stock ) { Console.WriteLine( "Notified investor {0} of {1}'s " + change to {2:C}", name, stock.Symbol, stock.Price ); } public Stock Stock { get{ return stock; } set{ stock = value; } }}

Page 68: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

ClientClient

Investor s = new Investor( "Sorros" );Investor b = new Investor( "Berkshire" );IBM ibm = new IBM( "IBM", 120.00 );ibm.Attach( s );ibm.Attach( b );ibm.Price = 120.10;ibm.Price = 121.00;ibm.Price = 120.50;ibm.Price = 120.75;

Investor s = new Investor( "Sorros" );Investor b = new Investor( "Berkshire" );IBM ibm = new IBM( "IBM", 120.00 );ibm.Attach( s );ibm.Attach( b );ibm.Price = 120.10;ibm.Price = 121.00;ibm.Price = 120.50;ibm.Price = 120.75;

Page 69: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

State State

• Allow an object to alter its behavior when its internal state changes. The object will appear to change its class

• Use the State pattern in either of the following cases: – An object's behavior depends on its state, and it must

change its behavior at run-time depending on that state.

– Operations have large, multipart conditional statements that depend on the object's state. Often, several operations will contain this same conditional structure

• Allow an object to alter its behavior when its internal state changes. The object will appear to change its class

• Use the State pattern in either of the following cases: – An object's behavior depends on its state, and it must

change its behavior at run-time depending on that state.

– Operations have large, multipart conditional statements that depend on the object's state. Often, several operations will contain this same conditional structure

Page 70: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

State State

Page 71: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

abstract class State{

protected Account account;protected double balance;protected double interest;protected double lowerLimit;protected double upperLimit;public Account Account{

get{ return account; }set{ account = value; }

}public double Balance{

get{ return balance; }set{ balance = value; }

}abstract public void Initialize();abstract public void Deposit( double amount );abstract public void Withdraw( double amount );abstract public void PayInterest();abstract public void StateChangeCheck();

}

abstract class State{

protected Account account;protected double balance;protected double interest;protected double lowerLimit;protected double upperLimit;public Account Account{

get{ return account; }set{ account = value; }

}public double Balance{

get{ return balance; }set{ balance = value; }

}abstract public void Initialize();abstract public void Deposit( double amount );abstract public void Withdraw( double amount );abstract public void PayInterest();abstract public void StateChangeCheck();

}

Page 72: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

class RedState : State{

double serviceFee;public RedState( State state ){

this.balance = state.Balance;this.account = state.Account;Initialize();

}override public void Initialize(){

interest = 0.0;lowerLimit = -100.0;upperLimit = 0.0;serviceFee = 15.00;

}override public void Deposit( double amount ){

balance += amount;StateChangeCheck();

}

class RedState : State{

double serviceFee;public RedState( State state ){

this.balance = state.Balance;this.account = state.Account;Initialize();

}override public void Initialize(){

interest = 0.0;lowerLimit = -100.0;upperLimit = 0.0;serviceFee = 15.00;

}override public void Deposit( double amount ){

balance += amount;StateChangeCheck();

}

Page 73: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

override public void Withdraw( double amount ){

amount = amount - serviceFee;Console.WriteLine("No funds available to

withdraw!" );}

override public void PayInterest(){

// No interest is paid}

override public void StateChangeCheck(){

if( balance > upperLimit )account.State = new SilverState( this );

}

override public void Withdraw( double amount ){

amount = amount - serviceFee;Console.WriteLine("No funds available to

withdraw!" );}

override public void PayInterest(){

// No interest is paid}

override public void StateChangeCheck(){

if( balance > upperLimit )account.State = new SilverState( this );

}

Page 74: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

class SilverState : State{

public SilverState(double balance, Account account ){

this.balance = balance;this.account = account;Initialize();

}public SilverState( State state ){

this.balance = state.Balance;this.account = state.Account;Initialize();

}override public void Initialize(){

interest = 0.0;lowerLimit = 0.0;upperLimit = 1000.0;

}

class SilverState : State{

public SilverState(double balance, Account account ){

this.balance = balance;this.account = account;Initialize();

}public SilverState( State state ){

this.balance = state.Balance;this.account = state.Account;Initialize();

}override public void Initialize(){

interest = 0.0;lowerLimit = 0.0;upperLimit = 1000.0;

}

Page 75: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

override public void Deposit( double amount ){

balance += amount;StateChangeCheck();

}override public void Withdraw( double amount ){

balance -= amount;StateChangeCheck();

}override public void PayInterest(){

balance += interest * balance;StateChangeCheck();

}override public void StateChangeCheck(){

if( balance < lowerLimit )account.State = new RedState( this );

else if( balance > upperLimit )account.State = new GoldState( this );

}

override public void Deposit( double amount ){

balance += amount;StateChangeCheck();

}override public void Withdraw( double amount ){

balance -= amount;StateChangeCheck();

}override public void PayInterest(){

balance += interest * balance;StateChangeCheck();

}override public void StateChangeCheck(){

if( balance < lowerLimit )account.State = new RedState( this );

else if( balance > upperLimit )account.State = new GoldState( this );

}

Page 76: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

class GoldState : State{

public GoldState(double balance, Account account ){

this.balance = balance;this.account = account;Initialize();

}public GoldState( State state ){

this.balance = state.Balance;this.account = state.Account;Initialize();

}override public void Initialize(){

// Should come from a databaseinterest = 0.05;lowerLimit = 1000.0;upperLimit = 10000000.0;

}

class GoldState : State{

public GoldState(double balance, Account account ){

this.balance = balance;this.account = account;Initialize();

}public GoldState( State state ){

this.balance = state.Balance;this.account = state.Account;Initialize();

}override public void Initialize(){

// Should come from a databaseinterest = 0.05;lowerLimit = 1000.0;upperLimit = 10000000.0;

}

Page 77: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

override public void Deposit( double amount ){

balance += amount;StateChangeCheck();

}override public void Withdraw( double amount ){

balance -= amount;StateChangeCheck();

}override public void PayInterest(){

balance += interest * balance;StateChangeCheck();

}override public void StateChangeCheck(){

if( balance < 0.0 )account.State = new RedState( this );

else if( balance < lowerLimit )account.State = new SilverState( this );

}

override public void Deposit( double amount ){

balance += amount;StateChangeCheck();

}override public void Withdraw( double amount ){

balance -= amount;StateChangeCheck();

}override public void PayInterest(){

balance += interest * balance;StateChangeCheck();

}override public void StateChangeCheck(){

if( balance < 0.0 )account.State = new RedState( this );

else if( balance < lowerLimit )account.State = new SilverState( this );

}

Page 78: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

class Account{

private State state;private string owner;public Account( string owner ){ // New accounts are 'Silver' by default

this.owner = owner;state = new SilverState( 0.0, this );

}public double Balance { get{ return state.Balance; }}public State State{

get{ return state; }set{ state = value; }

}public void Deposit( double amount ){

state.Deposit( amount );Console.WriteLine( "Deposited {0:C} --- ", amount);Console.WriteLine( " Balance = {0:C}", this.Balance );Console.WriteLine( " Status = {0}" , this.State );Console.WriteLine( "" );

}

class Account{

private State state;private string owner;public Account( string owner ){ // New accounts are 'Silver' by default

this.owner = owner;state = new SilverState( 0.0, this );

}public double Balance { get{ return state.Balance; }}public State State{

get{ return state; }set{ state = value; }

}public void Deposit( double amount ){

state.Deposit( amount );Console.WriteLine( "Deposited {0:C} --- ", amount);Console.WriteLine( " Balance = {0:C}", this.Balance );Console.WriteLine( " Status = {0}" , this.State );Console.WriteLine( "" );

}

Page 79: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

public void Withdraw( double amount ){

state.Withdraw( amount );Console.WriteLine( "Withdrew {0:C} --- ", amount);Console.WriteLine( " Balance = {0:C}", this.Balance );Console.WriteLine( " Status = {0}" , this.State );Console.WriteLine( "" );

}

public void PayInterest(){

state.PayInterest();Console.WriteLine( "Interest Paid --- ");Console.WriteLine( " Balance = {0:C}",this.Balance );Console.WriteLine( " Status = {0}" , this.State );Console.WriteLine( "" );

}

public void Withdraw( double amount ){

state.Withdraw( amount );Console.WriteLine( "Withdrew {0:C} --- ", amount);Console.WriteLine( " Balance = {0:C}", this.Balance );Console.WriteLine( " Status = {0}" , this.State );Console.WriteLine( "" );

}

public void PayInterest(){

state.PayInterest();Console.WriteLine( "Interest Paid --- ");Console.WriteLine( " Balance = {0:C}",this.Balance );Console.WriteLine( " Status = {0}" , this.State );Console.WriteLine( "" );

}

Page 80: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

ClientClient

Account account = new Account( "Ana Micola" );

account.Deposit( 500.0 );

account.Deposit( 300.0 );

account.Deposit( 550.0 );

account.PayInterest();

account.Withdraw( 2000.00 );

account.Withdraw( 1100.00 );

Account account = new Account( "Ana Micola" );

account.Deposit( 500.0 );

account.Deposit( 300.0 );

account.Deposit( 550.0 );

account.PayInterest();

account.Withdraw( 2000.00 );

account.Withdraw( 1100.00 );

Page 81: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

Strategy Strategy

• Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from the clients that use it

• The Strategy pattern should only be used when the variation in behavior is relevant to clients. If this criteria is not satisfied, the additional abstraction and effort necessary to implement the Strategy pattern is not justified

• Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from the clients that use it

• The Strategy pattern should only be used when the variation in behavior is relevant to clients. If this criteria is not satisfied, the additional abstraction and effort necessary to implement the Strategy pattern is not justified

Page 82: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

Strategy Strategy

Page 83: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

abstract class SortStrategy{

abstract public void Sort( ArrayList list );}

// "ConcreteStrategy"

class QuickSort : SortStrategy{

public override void Sort(ArrayList list ){

list.Sort(); // Default is QuicksortConsole.WriteLine("QuickSorted list ");

}}

abstract class SortStrategy{

abstract public void Sort( ArrayList list );}

// "ConcreteStrategy"

class QuickSort : SortStrategy{

public override void Sort(ArrayList list ){

list.Sort(); // Default is QuicksortConsole.WriteLine("QuickSorted list ");

}}

Page 84: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

class ShellSort : SortStrategy{

public override void Sort(ArrayList list ){

//list.ShellSort();Console.WriteLine("ShellSorted list ");

}}

class MergeSort : SortStrategy{

public override void Sort( ArrayList list ){

//list.MergeSort();Console.WriteLine("MergeSorted list ");

}}

class ShellSort : SortStrategy{

public override void Sort(ArrayList list ){

//list.ShellSort();Console.WriteLine("ShellSorted list ");

}}

class MergeSort : SortStrategy{

public override void Sort( ArrayList list ){

//list.MergeSort();Console.WriteLine("MergeSorted list ");

}}

Page 85: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

class SortedList{

private ArrayList list = new ArrayList();private SortStrategy sortstrategy;public void SetSortStrategy( SortStrategy sortstrategy ){

this.sortstrategy = sortstrategy;}public void Sort(){

sortstrategy.Sort( list );}public void Add( string name ){

list.Add( name );}public void Display(){

foreach( string name in list )Console.WriteLine( " " + name );

}}

class SortedList{

private ArrayList list = new ArrayList();private SortStrategy sortstrategy;public void SetSortStrategy( SortStrategy sortstrategy ){

this.sortstrategy = sortstrategy;}public void Sort(){

sortstrategy.Sort( list );}public void Add( string name ){

list.Add( name );}public void Display(){

foreach( string name in list )Console.WriteLine( " " + name );

}}

Page 86: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

ClientClient

SortedList studentRecords = new SortedList( );studentRecords.Add( "Samual" );studentRecords.Add( "Jimmy" );studentRecords.Add( "Sandra" );studentRecords.Add( "Anna" );studentRecords.Add( "Vivek" );

studentRecords.SetSortStrategy( new QuickSort() );studentRecords.Sort();studentRecords.Display();

SortedList studentRecords = new SortedList( );studentRecords.Add( "Samual" );studentRecords.Add( "Jimmy" );studentRecords.Add( "Sandra" );studentRecords.Add( "Anna" );studentRecords.Add( "Vivek" );

studentRecords.SetSortStrategy( new QuickSort() );studentRecords.Sort();studentRecords.Display();

Page 87: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

Template Method Template Method

• Define the skeleton of an algorithm in an operation, deferring some steps to client subclasses.

• Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.

• Define the skeleton of an algorithm in an operation, deferring some steps to client subclasses.

• Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.

Page 88: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

Template Method Template Method

Page 89: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

abstract class DataObject{ 

  abstract public void Connect();  abstract public void Select();  abstract public void Process();  abstract public void Disconnect();

  // The "Template Method"  public void Run()  {    Connect();    Select();    Process();    Disconnect();  }}

abstract class DataObject{ 

  abstract public void Connect();  abstract public void Select();  abstract public void Process();  abstract public void Disconnect();

  // The "Template Method"  public void Run()  {    Connect();    Select();    Process();    Disconnect();  }}

Page 90: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

class CustomerDataObject : DataObject{

private string connectionString ="provider=Microsoft.JET.OLEDB.4.0; "+ "data source=c:\\nwind.mdb";

private string commandString;private DataSet dataSet;public override void Connect( ){ // Nothing to do }public override void Select( ){

commandString = "select CompanyName from Customers";OleDbDataAdapter dataAdapter = new OleDbDataAdapter(

commandString, connectionString );dataSet = new DataSet();dataAdapter.Fill( dataSet, "Customers" );

}public override void Process(){

DataTable dataTable = dataSet.Tables["Customers"];foreach( DataRow dataRow in dataTable.Rows )

Console.WriteLine( dataRow[ "CompanyName" ] );}public override void Disconnect(){ // Nothing to do }

}

class CustomerDataObject : DataObject{

private string connectionString ="provider=Microsoft.JET.OLEDB.4.0; "+ "data source=c:\\nwind.mdb";

private string commandString;private DataSet dataSet;public override void Connect( ){ // Nothing to do }public override void Select( ){

commandString = "select CompanyName from Customers";OleDbDataAdapter dataAdapter = new OleDbDataAdapter(

commandString, connectionString );dataSet = new DataSet();dataAdapter.Fill( dataSet, "Customers" );

}public override void Process(){

DataTable dataTable = dataSet.Tables["Customers"];foreach( DataRow dataRow in dataTable.Rows )

Console.WriteLine( dataRow[ "CompanyName" ] );}public override void Disconnect(){ // Nothing to do }

}

Page 91: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

ClientClient

public static void Main( string[] args )

{

CustomerDataObject c = new

CustomerDataObject( );

c.Run();

}

public static void Main( string[] args )

{

CustomerDataObject c = new

CustomerDataObject( );

c.Run();

}

Page 92: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

Visitor Visitor

• Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates

• Use When an object structure contains many classes of objects with differing interfaces, and you want to perform operations on these objects that depend on their concrete classes

• Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates

• Use When an object structure contains many classes of objects with differing interfaces, and you want to perform operations on these objects that depend on their concrete classes

Page 93: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

The ProblemThe Problem

• We have a set of Objects.

• We are writing several algorithms working with these objects.

• We don’t want the objects to be responsible for their part in the algorithm– It does not look good– Several teams are developing with these

classes and we can’t change them easily.

• We have a set of Objects.

• We are writing several algorithms working with these objects.

• We don’t want the objects to be responsible for their part in the algorithm– It does not look good– Several teams are developing with these

classes and we can’t change them easily.

Page 94: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

Example - Animal hospitalExample - Animal hospital

• We have many animals

• We want to create a dentist class that can treat any animal’s tooth ache

• Addition of new animals is not so probable

• Addition of new types of doctors is probable.

• We have many animals

• We want to create a dentist class that can treat any animal’s tooth ache

• Addition of new animals is not so probable

• Addition of new types of doctors is probable.

Page 95: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

Solution - 1Solution - 1

Let the damn horse treat itself ….

class Horse : public Animal {public:

void CureTeeth() { }}

class Animal {public: void CureTeeth()=0;}

Looks ugly !

Page 96: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

ProblemsProblems

• It does not make any sense. – Heeling teeth is not one of the things horses

(or any animals) do to themselves.

• Maybe we can’t change the animal classes– Other groups might be working on it

simultaneously.

• It does not make any sense. – Heeling teeth is not one of the things horses

(or any animals) do to themselves.

• Maybe we can’t change the animal classes– Other groups might be working on it

simultaneously.

Page 97: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

Solution - 2Solution - 2

Void foo(Animal x) {if (x instanceof Horse) {

//give a horse teeth treatment} else if (x instanceof Mouse) {

//give a mouse teeth treatment} …

}

Page 98: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

ProblemsProblems

• Looks bad!

• Slow

• RTTI usage is not recommended in good design.

• Looks bad!

• Slow

• RTTI usage is not recommended in good design.

Page 99: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

A Better Idea - Use VisitorA Better Idea - Use VisitorVisitor

VisitConcreteElementA ( : ConcreteElementA)VisitConcreteElementB ( : ConcreteElementB)

ConcreteVisitor1

VisitConcreteElementA ( : ConcreteElementA)VisitConcreteElementB ( : ConcreteElementB)

ConcreteVisitor2

VisitConcreteElementA ( : ConcreteElementA)VisitConcreteElementB ( : ConcreteElementB)

Element

Accept ( : Visitor)

ConcreteElementB

Accept ( : Visitor)OperationB ()

ConcreteElementA

Accept ( : Visitor)OperationA ()

Page 100: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

How does it work ?How does it work ? : SomeObject a : ConcreteElementA v : ConcreteVisitor1b : ConcreteElementB

Accept (v)VisitConcreteElementA (a)

OperationA ( )

Accept (v)VisitConcreteElementB (b)

OperationB ( )

Page 101: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

abstract class Visitor{

abstract public void Visit( Element element );}

// "ConcreteVisitor1"

class IncomeVisitor : Visitor{

public override void Visit( Element element ){

Employee employee = ((Employee)element);

// Provide 10% pay raiseemployee.Income *= 1.10;Console.WriteLine( "{0}'s new income: {1:C}",

employee.Name, employee.Income );}

}

abstract class Visitor{

abstract public void Visit( Element element );}

// "ConcreteVisitor1"

class IncomeVisitor : Visitor{

public override void Visit( Element element ){

Employee employee = ((Employee)element);

// Provide 10% pay raiseemployee.Income *= 1.10;Console.WriteLine( "{0}'s new income: {1:C}",

employee.Name, employee.Income );}

}

Page 102: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

class VacationVisitor : Visitor{

public override void Visit( Element element ){

Employee employee = ((Employee)element);

// Provide 3 extra vacation daysemployee.VacationDays += 3;Console.WriteLine( "{0}'s new vacation days: {1}",

employee.Name, employee.VacationDays );}

}

class VacationVisitor : Visitor{

public override void Visit( Element element ){

Employee employee = ((Employee)element);

// Provide 3 extra vacation daysemployee.VacationDays += 3;Console.WriteLine( "{0}'s new vacation days: {1}",

employee.Name, employee.VacationDays );}

}

Page 103: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

abstract class Element{

abstract public void Accept( Visitor visitor );}class Employee : Element{

string name;double income;int vacationDays;public Employee( string name, double income,int vacationDays ){

this.name = name;this.income = income;this.vacationDays = vacationDays;

}//properties for all fieldspublic override void Accept( Visitor visitor ){

visitor.Visit( this );}

}

abstract class Element{

abstract public void Accept( Visitor visitor );}class Employee : Element{

string name;double income;int vacationDays;public Employee( string name, double income,int vacationDays ){

this.name = name;this.income = income;this.vacationDays = vacationDays;

}//properties for all fieldspublic override void Accept( Visitor visitor ){

visitor.Visit( this );}

}

Page 104: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

class Employees{

private ArrayList employees = new ArrayList();

public void Attach( Employee employee ){

employees.Add( employee );}

public void Detach( Employee employee ){

employees.Remove( employee );}

public void Accept( Visitor visitor ){

foreach( Employee e in employees )e.Accept( visitor );

}}

class Employees{

private ArrayList employees = new ArrayList();

public void Attach( Employee employee ){

employees.Add( employee );}

public void Detach( Employee employee ){

employees.Remove( employee );}

public void Accept( Visitor visitor ){

foreach( Employee e in employees )e.Accept( visitor );

}}

Page 105: Design Patterns Behavioral Patterns. The Dependency Inversion Principle (DIP) Depend upon Abstractions. Do not depend upon concretions

ClientClient

Employees e = new Employees();e.Attach( new Employee( "Hank", 25000.0, 14 ) );e.Attach( new Employee( "Elly", 35000.0, 16 ) );e.Attach( new Employee( "Dick", 45000.0, 21 ) );

// Create two visitorsIncomeVisitor v1 = new IncomeVisitor();VacationVisitor v2 = new VacationVisitor();

// Employees are visitede.Accept( v1 );e.Accept( v2 );

Employees e = new Employees();e.Attach( new Employee( "Hank", 25000.0, 14 ) );e.Attach( new Employee( "Elly", 35000.0, 16 ) );e.Attach( new Employee( "Dick", 45000.0, 21 ) );

// Create two visitorsIncomeVisitor v1 = new IncomeVisitor();VacationVisitor v2 = new VacationVisitor();

// Employees are visitede.Accept( v1 );e.Accept( v2 );