C# Advanced L07-Design Patterns

Post on 13-Jan-2015

229 Views

Category:

Software

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

C# Advanced L07-Desgin Patterns

Transcript

Mohammad Shaker

mohammadshaker.com

@ZGTRShaker

2011, 2012, 2013, 2014

C# AdvancedL07–Design Patterns

Gang of Four (GoF) Gamma, Helm, Johnson, Vlissides

Gamma et al,

Design Patterns: Elements of Reusable Object-Oriented SoftwareAddison Wesley, 1995

Scope

• Patterns solve software structural problems like:– Abstraction,

– Encapsulation

– Information hiding

– Separation of concerns

– Coupling and cohesion

– Separation of interface and implementation

– Single point of reference

– Divide and conquer

• Patterns also solve non-functional

problems like:

– Changeability

– Interoperability

– Efficiency

– Reliability

– Testability

– Reusability

Types of Pattern

• There are 3 types of pattern:– Creational: address problems of creating an object in a flexible way. Separate creation, from

operation/use.

– Structural: address problems of using O-O constructs like inheritance to organize classes and objects

– Behavioral: address problems of assigning responsibilities to classes. Suggest both static relationships and patterns of communication

Classification of Design Patterns

Purpose

Creational Structural Behavioral

Factory Method Adapter Interpreter

Abstract Factory Bridge Template Method

Builder Composite Chain of Responsibility

Prototype Decorator Command

Singleton Façade Iterator

Flyweight Mediator

Proxy Memento

Observer

State

Strategy

Visitor

Patterns

Patterns

• Singleton

– Ensure a class only has one instance

– Provide a global point of access to it

• Abstract Factory

– Provide an interface for creating families of related or dependent objects without specifying

their concrete classes

• Factory Method

– Define an interface for creating an object but let subclasses decide which class to instantiate

– Lets a class defer instantiation to subclasses

• Prototype

– Specify the kinds of objects to create using a prototypical instance

– Create new objects by copying this prototype

Patterns

• Builder– Separate the construction of a complex object from its representation so that the same construction

process can create different representations

• Composite– Compose objects into tree structures to represent part-whole hierarchies

– Lets clients treat individual objects and compositions of objects uniformly

• Decorator– Attach additional responsibilities to an object dynamically

– Provide a flexible alternative to subclassing for extending functionality

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

– Lets classes work together that couldn’t otherwise because of incompatible interfaces

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

Patterns

• Façade– Provide a unified interface to a set of interfaces in a subsystem

– Defines an higher-level interface that makes the system easier to use

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

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

• Iterator– Provide a way to access the elements of an aggregate object without exposing its

representation

• Command– Encapsulate a request as an object, thereby letting you parameterize clients with different

requests

Patterns

• Interpreter– Given a language, define a representation for its grammar along with an interpreter that uses the

representation to interpret sentences in the language

• Mediator– Define an object that encapsulate how a set of objects interact

– Promotes loose coupling by keeping objects from referring to each other explicitly

– Lets you vary their interaction independently

• Memento– Capture and externalize an object’s internal state

• Observer– Define a one-to-many dependency between objects so when one of them change state all its

dependents are updated automatically

• State– Allow an object to alter its behavior when its internal state changes

– The object will appear to change its class

Patterns

• Visitor

– Represent an operation to be performed on the elements of an object structure

– Lets you define a new operation without changing the classes of the elements on which

operates

• Strategy

– Define a family of algorithms

– Encapsulate each one

– Make them interchangeable

– Lets the algorithms vary independently from clients that use it

• Chain of responsibilities

– Avoid coupling the sender of a request to its receiver by giving more then one object a

chance to handle the request

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

Walk Through in Some Patterns

FactoryDefine an interface for creating an object but let subclasses decide which class to

instantiate. Lets a class defer instantiation to subclasses

Factoryclass ProductClass

{

public ProductClass() { … }

public ProductClass( int aInitValue ) { … }

};

class FactoryClass

{

public ProductClass GetNewInstance()

{ return new ProductClass(); }

public ProductClass GetNewInstance( int aInitValue )

{ return new ProductClass( aInitValue ); }

};

class Client

{

public void start()

{

// create a new factory

ProductFactory lFactory = new Factory();

// create objects

ProductClass lObj1 = lFactory.GetNewInstance();

ProductClass lObj2 = lFactory.GetNewInstance(4);

}

};

Factoryclass ProductClass

{

public ProductClass() { … }

public ProductClass( int aInitValue ) { … }

};

class FactoryClass

{

public ProductClass GetNewInstance()

{ return new ProductClass(); }

public ProductClass GetNewInstance( int aInitValue )

{ return new ProductClass( aInitValue ); }

};

class Client

{

public void start()

{

// create a new factory

ProductFactory lFactory = new Factory();

// create objects

ProductClass lObj1 = lFactory.GetNewInstance();

ProductClass lObj2 = lFactory.GetNewInstance(4);

}

};

StrategyDefines a family of algorithms, encapsulates each algorithm, and

makes the algorithms interchangeable within that family.

Strategypublic interface IBehaviour { public int moveCommand();}

public class AgressiveBehaviour implements IBehaviour{

public int moveCommand(){ \\AgressiveBehaviour Behaviour }

}

public class DefensiveBehaviour implements IBehaviour{

public int moveCommand(){ \\DefensiveBehaviour Behaviour }

}

public class NormalBehaviour implements IBehaviour{

public int moveCommand(){ \\NormalBehaviour Behaviour }

}

public class Robot {

IBehaviour behaviour;

String name;

public Robot(String name)

{ this.name = name; }

public void setBehaviour(IBehaviour behaviour)

{ this.behaviour = behaviour; }

public void move()

{ behaviourزmoveCommand(); }

}

Strategypublic interface IBehaviour { public int moveCommand();}

public class AgressiveBehaviour implements IBehaviour{

public int moveCommand(){ \\AgressiveBehaviour Behaviour }

}

public class DefensiveBehaviour implements IBehaviour{

public int moveCommand(){ \\DefensiveBehaviour Behaviour }

}

public class NormalBehaviour implements IBehaviour{

public int moveCommand(){ \\NormalBehaviour Behaviour }

}

public class Robot {

IBehaviour behaviour;

String name;

public Robot(String name)

{ this.name = name; }

public void setBehaviour(IBehaviour behaviour)

{ this.behaviour = behaviour; }

public void move()

{ behaviourزmoveCommand(); }

}

Three different Strategies for Robot movement

Strategypublic interface IBehaviour { public int moveCommand();}

public class AgressiveBehaviour implements IBehaviour{

public int moveCommand(){ \\AgressiveBehaviour Behaviour }

}

public class DefensiveBehaviour implements IBehaviour{

public int moveCommand(){ \\DefensiveBehaviour Behaviour }

}

public class NormalBehaviour implements IBehaviour{

public int moveCommand(){ \\NormalBehaviour Behaviour }

}

public class Robot {

IBehaviour behaviour;

String name;

public Robot(String name)

{ this.name = name; }

public void setBehaviour(IBehaviour behaviour)

{ this.behaviour = behaviour; }

public void move()

{ behaviourزmoveCommand(); }

}

Assigning a robot behaviour

Strategypublic interface IBehaviour { public int moveCommand();}

public class AgressiveBehaviour implements IBehaviour{

public int moveCommand(){ \\AgressiveBehaviour Behaviour }

}

public class DefensiveBehaviour implements IBehaviour{

public int moveCommand(){ \\DefensiveBehaviour Behaviour }

}

public class NormalBehaviour implements IBehaviour{

public int moveCommand(){ \\NormalBehaviour Behaviour }

}

public class Robot {

IBehaviour behaviour;

String name;

public Robot(String name)

{ this.name = name; }

public void setBehaviour(IBehaviour behaviour)

{ this.behaviour = behaviour; }

public void move()

{ behaviourزmoveCommand(); }

}

public static void main(String[] args) {

Robot r1 = new Robot("Big Robot");

Robot r2 = new Robot("George v.2.1");

Robot r3 = new Robot("R2");

r1.setBehaviour(new AgressiveBehaviour());

r2.setBehaviour(new DefensiveBehaviour());

r3.setBehaviour(new NormalBehaviour());

r1.move();

r2.move();

r3.move();

r1.setBehaviour(new DefensiveBehaviour());

r2.setBehaviour(new AgressiveBehaviour());

r1.move();

r2.move();

r3.move();

}

Strategypublic interface IBehaviour { public int moveCommand();}

public class AgressiveBehaviour implements IBehaviour{

public int moveCommand(){ \\AgressiveBehaviour Behaviour }

}

public class DefensiveBehaviour implements IBehaviour{

public int moveCommand(){ \\DefensiveBehaviour Behaviour }

}

public class NormalBehaviour implements IBehaviour{

public int moveCommand(){ \\NormalBehaviour Behaviour }

}

public class Robot {

IBehaviour behaviour;

String name;

public Robot(String name)

{ this.name = name; }

public void setBehaviour(IBehaviour behaviour)

{ this.behaviour = behaviour; }

public void move()

{ behaviourزmoveCommand(); }

}

public static void main(String[] args) {

Robot r1 = new Robot("Big Robot");

Robot r2 = new Robot("George v.2.1");

Robot r3 = new Robot("R2");

r1.setBehaviour(new AgressiveBehaviour());

r2.setBehaviour(new DefensiveBehaviour());

r3.setBehaviour(new NormalBehaviour());

r1.move();

r2.move();

r3.move();

r1.setBehaviour(new DefensiveBehaviour());

r2.setBehaviour(new AgressiveBehaviour());

r1.move();

r2.move();

r3.move();

}

Simply change the Strategy and the

behavior will change

SingletonWhen one, and only one, instance of class is needed. Providing

a global point of access to it.

Singletonprivate readonly SqlConnection _sqlConnection;

const CONNECTION_STRING = (@"Data Source=127.0.0.1;database=soa;User id=sa1;Password=sa1;“;

public static SqlConnection GetSqlConnectionSingleton()

{

if (_sqlConnection == null)

{

_sqlConnection = new SqlConnection(CONNECTION_STRING );

}

return _sqlConnection;

}

Any client will call GetSqlConnectionSingleton (public) and has no direct access to _sqlConnection (private)

Singleton for an Object

public sealed class Singleton

{

private static Singleton _instance;

private Singleton() { }

public static Singleton GetSingleton()

{

if (_instance == null) _instance = new Singleton();

return _instance;

}

}

No one can instantiate this (since the constructor is private), like this:Singleton s = new Singleton();

Singleton for an Object

public sealed class Singleton

{

private static Singleton _instance;

private Singleton() { }

public static Singleton GetSingleton()

{

if (_instance == null) _instance = new Singleton();

return _instance;

}

}

One Instance and One Instance Only will be Created for this Class Object

Database Connection Singleton private readonly SqlConnection _sqlConnection;

const CONNECTION_STRING = (@"Data Source=127.0.0.1;database=soa;User id=sa1;Password=sa1;“;

public static SqlConnection GetSqlConnectionSingleton()

{

if (_sqlConnection == null)

{

_sqlConnection = new SqlConnection(CONNECTION_STRING );

}

return _sqlConnection;

}

Database Connection Singleton private readonly SqlConnection _sqlConnection;

const CONNECTION_STRING = (@"Data Source=127.0.0.1;database=soa;User id=sa1;Password=sa1;“;

public static SqlConnection GetSqlConnectionSingleton()

{

if (_sqlConnection == null)

{

_sqlConnection = new SqlConnection(CONNECTION_STRING );

}

return _sqlConnection;

}

Singleton for an Object in Multi-threaded Application?

Any Need to Adjust?

Singleton for an Object in Multi-threaded Applicationpublic sealed class Singleton

{

private static Singleton _instance;

private static object _lockThis = new object();

private Singleton() { }

public static Singleton GetSingleton()

{

lock (_lockThis)

{

if (_instance == null) _instance = new Singleton();

}

return _instance;

}

}

MultitonIs an extension of the singleton pattern. When one, and only one, instance of

class is needed that corresponds to a key. Providing a global point of access to it.

MultitonDictionary <Key, SingletonObject> _singletonInstances;public static SingletonInstances GetMultiton(string key){

lock (_lock){

if (!_singletonInstances.ContainsKey(key)) _singletonInstances.Add(key, new Multiton());}return _instances[key];

}

MultitonDictionary <Key, SingletonObject> _singletonInstances;public static SingletonInstances GetMultiton(string key){

lock (_lock){

if (!_singletonInstances.ContainsKey(key)) _singletonInstances.Add(key, new Multiton());}return _instances[key];

}

Software Architectural Patterns

MVCModel View Controller

MVVMModel View View Model

top related