Top Banner
Design Patterns Training 02/2014
61

Design Patterns

May 10, 2015

Download

Technology

In software engineering, a design pattern is a general reusable solution to a commonly occurring problem within a given context in software design
Patterns are formalized best practices that the programmer must implement in the application.
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Design Patterns

Design Patterns Training

02/2014

Page 2: Design Patterns

Agenda

What’s a design pattern…

Pros / Cons

Families

Patterns x10

2All photos and pictures included in those slides are courtesy and copyright of their respective owners.

Page 3: Design Patterns

Homework

Object-Oriented Design : Coupling

Cohesion

Inheritance

Interface

Polymorphism

S.O.L.I.D. principles Refer A. Sauvinet mini-training

3

Page 4: Design Patterns

Definition

In software engineering, a design pattern is a general reusable solution to a commonly occurring problem within a given context in software design

Patterns are formalized best practices that the programmer must implement in the application

4

Page 5: Design Patterns

Pros / Cons

Pros : speed up development by providing tested, proven paradigms

Robust solution

Smart design

Flexibility

Re-usable

Cons : Usage reveals missing feature in programming language

Inappropriate use of patterns may unnecessarily increase complexity

Some patterns have impacts on performance

5

Page 6: Design Patterns

Families

3 main families : Creational patterns : control object creation mechanisms

Structural patterns : ease relationships between entities

Behavioral pattern : increase flexibility and communication between objects

2 extra families : Concurrency patterns

Lock

MDP : Messaging Design Pattern

Architectural patterns MVC : Model-View-Controller

MVVM : Model-View-ViewModel

MVP : Model-View-Presenter

Event-driven architecture

6

Page 7: Design Patterns

Families : Creational Patterns

Control object creation mechanisms Singleton*

Builder*

Abstract Factory

Prototype

Factory method*

Lazy initialization

Object pool

7

Page 8: Design Patterns

Families : Structural Patterns

Ease relationships between entities Adapter*

Decorator*

Composite*

Aggregate

Façade*

Proxy

8

Page 9: Design Patterns

Families : Behavioral Patterns

Increase flexibility and communication between objects Chain of responsibility*

Command

Iterator

Observer

Visitor*

Strategy*

9

Page 10: Design Patterns

And what about the famous IoC ?

Inversion of Control is not a pattern, it’s a programming technique.

Coupling is not known at compile time, only at runtime

Hands-on : Using a factory pattern

Using a service locator pattern

Using a dependency injection, for example:

• A constructor injection

• Parameter injection

• A setter injection

• An interface injection

Using a contextualized lookup

Using Template method design pattern

Using strategy design pattern

10

Page 11: Design Patterns

11

Page 12: Design Patterns

12

Page 13: Design Patterns

Singleton

Restricts instanciation of a class to one object.

Provides a global point of access to it

13Note : be careful with multithread, use (double) lock pattern

Page 14: Design Patterns

Singleton - Code

14

public static class Utils{

private static IUtilsInstance _instance;

public static IUtilsInstance Instance{

get{

if (_instance != null)_instance = new UtilsInstance();

}return _instance;

}}

}

Naive implementation

Page 15: Design Patterns

Singleton - Code

15

public static class Utils{

private static volatile object _lock = new object();

private static IUtilsInstance _instance;

public static IUtilsInstance Instance{

get{

if (_instance != null)return _instance;

lock (_lock){

if (_instance != null){

return _instance;}_instance = new UtilsInstance();return _instance;

}}set { _instance = value; }

}}

Page 16: Design Patterns
Page 17: Design Patterns

Builder

Separate construction of a complex object from its representation

Solution to the telescoping constructor anti-pattern Many parameters, mandatory or optional

17

Page 18: Design Patterns

Without Builder

public class BadCar

{

public bool HasGPS { get; private set; }

public bool IsCityCar { get; private set; }

public bool IsSportCar { get; private set; }

public bool IsCabrioletCar { get; private set; }

public int Seats { get; private set; }

public BadCar(bool hasGps);

public BadCar(bool hasGps, bool isCityCar);

public BadCar(bool isCabrioletCar, int seats);

public BadCar(bool hasGps, bool isCityCar, bool isSportCar, bool isCabrioletCar, int seats);

}

18

Program :

public void main()

{

var car = new BadCar(false, false, true, false, 2);

}

Page 19: Design Patterns

Without Builder

19

public class BadCabriolet : BadCar{

public BadCabriolet(bool hasGps) : base(hasGps) { }

public BadCabriolet(bool hasGps, bool isCityCar) : base(hasGps, isCityCar) { }

public BadCabriolet(bool isCabrioletCar, int seats) : base(isCabrioletCar, seats) { }

public BadCabriolet(bool hasGps, bool isCityCar, bool isSportCar, bool isCabrioletCar, int seats): base(hasGps, isCityCar, isSportCar, isCabrioletCar, seats)

{}

}

Issue with polymorphism :

Page 20: Design Patterns

With Builder

20

public class Car

{

public bool HasGPS { get; set; }

public bool IsCityCar { get; set; }

public bool IsSportCar { get; set; }

public bool IsCabrioletCar { get; set; }

public int Seats { get; set; }

}

public class CarBuilder{

private Car Car = new Car());

public Car GetCar(){

return Car;}

public CarBuilder SetSeats(int nbSeats){

Car.Seats = nbSeats;return this;

}

public CarBuilder SetSportsCar(){

Car.IsSportCar = true;return this;

}

public CarBuilder SetCabriolet();public CarBuilder SetGps();

}

• Wrap properties set into methods

• Really easy to make it « fluent »

public class Car

{

public bool HasGPS { get; private set; }

public bool IsCityCar { get; private set; }

public bool IsSportCar { get; private set; }

public bool IsCabrioletCar { get; private set; }

public int Seats { get; private set; }

public CarBuilder Builder { get; private set; }

private Car(CarBuilder Builder);

}

Page 21: Design Patterns

With Builder

21

public class Prog{

public void Main(){

var builder = new CarBuilder();

builder.SetSeats(2);builder.SetSportsCar();

var car = builder.GetCar();

...

var fluentCar = builder.SetSeats(2).SetSportsCar().SetGps().GetCar();}

}

• Initialization is wordy

• Extension is easy

• Polymorphism

Page 22: Design Patterns
Page 23: Design Patterns

Factory Method

Define an interface for creating a single object, but let subclasses decide which class to instantiate

Can be used to ease TDD mocking

3 different implementations Subclassing

Interface

Static

23

Note : Subclassing implementation depends on private constructor = class cannot be extended

if protected constructor = subclass have to redefine all factory methods !

Page 24: Design Patterns

Example

24

public interface ICar{

string GetType();}

public interface ICarFactory{

ICar MakeCar(int nbDoors);}

class Sedan : ICar{

public string GetType() { return "Sedan"; }}

class Coupe : ICar{

public string GetType() { return "Coupe"; }}

class CarFactory : ICarFactory{

public ICar MakeCar(int nbDoors){

return (nbDoors > 2) ? (ICar)new Sedan() : new Coupe();}

}

public class Proog

{public void Main(){

var f = new CarFactory();ICar coupe = f.MakeCar(2);ICar sedan = f.MakeCar(5);

}}

Page 25: Design Patterns
Page 26: Design Patterns

Adapter

Convert the interface of a class into another interface clients expect

Helps two incompatible interfaces to work together

26

Page 27: Design Patterns

Without adapter

27

public class DataParser{

private string Data;

public void SetData(string data){

this.Data = data;}

public void ParseData(){

Console.WriteLine(this.Data.Replace(" - ", " / "));}

}

public class DataProvider{

public string[] Datas;

public string GetStringData(){

return this.Datas.Aggregate(string.Empty, (current, data) => current + (data + " - "));}

}

public class Prog{

public void Main(){

var a = new DataParser();var b = new DataProvider();

a.SetData(b.GetStringData());a.ParseData();

}}

Page 28: Design Patterns

With adapter

28

public class DataParserFormat1Adapter{

public DataProvider B { get; set; }

public DataParserFormat1Adapter(DataProvider b){

this.B = b;}

public string GetStringData(){

return this.B.Datas.Aggregate(string.Empty, (current, data) => current + (data + " - "));}

}

public class Prog{

public void Main(){

var a = new DataParser();var b = new DataProvider();

var adapter = new DataParserFormat1Adapter(b);var data = adapter.GetStringData();

a.SetData(data);a.ComputeData();

}}

Page 29: Design Patterns
Page 30: Design Patterns

Decorator

Attach additional responsibilities to an object dynamically keeping the same interface

30

Page 31: Design Patterns

Without Decorator

31

public interface IArmor{

void Fight();

string GetDescription();}

public class SimpleArmor : IArmor{

public virtual void Fight(){

//Launch Simple missile}

public virtual string GetDescription(){

return "Armor Mark I";}

}

public class SimpleArmorWithLaser : SimpleArmor{

public override void Fight(){

base.Fight();LaunchLaser();

}

private void LaunchLaser(){

// Enable BBQ LAser}

public virtual string GetDescription(){

return "Mark II with Laser";}

}

Page 32: Design Patterns

Without Decorator

32

public class SimpleArmorWithTazer : SimpleArmor{

public override void Fight(){

base.Fight();this.EnableTazer();

}

private void EnableTazer(){

// Enable Heart Attack Tazer}

public override string GetDescription(){

return "Mark II with Tazer";}

}

Page 33: Design Patterns

Without Decorator

33

public class SimpleArmorWithTazer : SimpleArmor{

public override void Fight(){

base.Fight();this.EnableTazer();

}

private void EnableTazer(){

// Enable Heart Attack Tazer}

public override string GetDescription(){

return "Mark II with Tazer";}

}

public class SimpleWindowWithLaserAndTazer : SimpleArmorWithLaser{

public override void Fight(){

base.Fight();this.EnableTazer();

}

private void EnableTazer(){

// Enable Heart Attack Tazer}

public override string GetDescription(){

return base.GetDescription() + " and with Tazer";}

}

Page 34: Design Patterns

With Decorator

34

public abstract class ArmorDecorator : IArmor{

public IArmor DecoratedArmor { get; private set; }

public ArmorDecorator(IArmor decoratedArmor){

this.DecoratedArmor = decoratedArmor;}

public virtual void Fight(){

DecoratedArmor.Fight();}

public virtual string GetDescription(){

return DecoratedArmor.GetDescription();}

}

Page 35: Design Patterns

With Decorator

35

public class LaserDecorator : ArmorDecorator{

public LaserDecorator(IArmor decoratedArmor) : base(decoratedArmor) { }

public override void Fight(){

base.Fight();LaunchLaser();

}

private void LaunchLaser(){

// Enable BBQ Laser}

public override string GetDescription(){

return base.GetDescription() + " with Laser";}

}

Page 36: Design Patterns

With Decorator

36

public class LaserDecorator : ArmorDecorator{

public LaserDecorator(IArmor decoratedArmor) : base(decoratedArmor) { }

public override void Fight(){

base.Fight();LaunchLaser();

}

private void LaunchLaser(){

// Enable BBQ Laser}

public override string GetDescription(){

return base.GetDescription() + " with Laser";}

}

public class TazerDecorator : ArmorDecorator{

public TazerDecorator(IArmor decoratedArmor) : base(decoratedArmor) { }

public override void Fight(){

base.Fight();EnableTazer();

}

private void EnableTazer(){

// Enable Heazrt Attack Tazer}

public override string GetDescription(){

return base.GetDescription() + " with Tazer";}

}

Page 37: Design Patterns

With Decorator

37

public class Jarvis{

public void Main(){

IArmor ironman = new TazerDecorator(new LaserDecorator(new SimpleArmor()));

Console.WriteLine(ironman.GetDescription());}

}

Page 38: Design Patterns
Page 39: Design Patterns

Composite

Compose objects into tree structures to represent part-whole hierarchies

39

Page 40: Design Patterns

Composite Example

40

public interface IDrawable{

void Render();}

public class Ellipse : IDrawable{

public void Render(){

Console.WriteLine("Ellipse");}

}

public class Square: IDrawable{

public void Render(){

Console.WriteLine("Square");}

}

Page 41: Design Patterns

41

public class CompositeGraphic : IDrawable{

//Collection of Graphics.private readonly List<IDrawable> graphics;

public CompositeGraphic(){

//initialize generic Collection(Composition)graphics = new List<IDrawable>();

}

public void Add(IDrawable graphic);public void AddRange(params IDrawable[] graphic);public void Delete(IDrawable graphic);

//Render the graphic.public void Render(){

foreach (var childGraphic in graphics){

childGraphic.Render();}

}}

Page 42: Design Patterns

42

public class FrankensteinReturn{

public void Main(){

var eyes = new CompositeGraphic(new Square(), new Square());var mouth = new Ellipse();var head = new CompositeGraphic(new Square(), new Square(), new Square());

var frankenstein = new CompositeGraphic(head, eyes, mouth);}

}

Page 43: Design Patterns

43

Page 44: Design Patterns

Façade

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

BC example : Register in Global

44

Page 45: Design Patterns

Façade example

45

/* Complex parts */class CPU {

public void freeze() { ... }public void jump(long position) { ... }public void execute() { ... }

}

class Memory {public void load(long position, byte[] data) { ... }

}

class HardDrive {public byte[] read(long lba, int size) { ... }

}

Page 46: Design Patterns

Façade example

46

class ComputerFacade{

private CPU processor;private Memory ram;private HardDrive hd;

public ComputerFacade() {this.processor = new CPU();this.ram = new Memory();this.hd = new HardDrive();

}

public void Start() {processor.freeze();ram.load(BOOT_ADDRESS, hd.read(BOOT_SECTOR, SECTOR_SIZE));processor.jump(BOOT_ADDRESS);processor.execute();

}}

/* ServiceDesk */

class You {public static void main() {

var computer = new ComputerFacade();computer.Start();

}}

Page 47: Design Patterns
Page 48: Design Patterns

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.

Good practice : Loose coupling

BC example : login, register processes

48

Page 49: Design Patterns

Chain of responsibility example - pipeline

49

ProcessorTask

TaskTask

RequestLogin

ProcessorAuthentication

Task

Login = «testuser»

Password = « pwd123 »

Status = ok

User = null

Request

Login = «testuser»

Password = « pwd123 »

Status = ok

User = null

FraudTask

Request

Login

Password

Status = Forbidden by Fraud

User = null

Request

Infos

Status

Page 50: Design Patterns

50

Page 51: Design Patterns

Strategy

Define a family of algorithms, encapsulate each one, and make them interchangeable.

Strategy lets the algorithm vary independently from clients that use it.

O from SOLID : Open for extension but closed for modification.

51Note : For more information, key words : Policy-based design

Page 52: Design Patterns

Strategy example

52

interface DepositStrategy{

decimal Execute(decimal amount); };

class Eiole : DepositStrategy{

private decimal feeAmount = 10;

public decimal Execute(decimal amount) {

return amount + feeAmount;}

};

class Metacharge : DepositStrategy{

private decimal feeRate = 0,05;

public decimal Execute(decimal amount) {

return amount * (1 + feeRate);}

};

class DepositContext{

private List<DepositStrategy> strategies;...

private DepositStrategy PickStrategyFor(decimal amount) { // strategy with minimum fees; }

public decimal ExecuteStrategy(decimal amount) {

return this.strategy.Execute(amount);}

};

Page 53: Design Patterns

Strategy example

53

class DepositService{

public void Deposit(decimal amount) {

var context = new DepositContext();context.strategies.add(new Eiole());context.strategies.add(new Metacharge());

var totalAmount = context.ExecuteStrategy(amount);}

};

0 -> 200 € => Metacharge> 200 € => Eiole

Page 54: Design Patterns
Page 55: Design Patterns

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.

55Note : Implementation may have a real impact on performance !

Page 56: Design Patterns

Visitor example

56

interface IArticleVisitor{

void Visit(SportArticle sport);void Visit(PokerArticle poker);void Visit(TurfArticle turf);

}

interface IArticle{

string GetContent();...void Accept(IArticleVisitor visitor);

}

class SportArticle : IArticle{

public string GetContent()...

public void Accept(IArticleVisitor visitor) { visitor.Visit(this); }}

class SumUpArticleVisitor : IArticleVisitor{

private string Summary { get; set; }public string GetSummary() { return this.Summary; }

void Visit(SportArticle sport) { this.Summary += sport.GetContent().Substring(0, 200); }void Visit(PokerArticle poker) { this.Summary += poker.GetContent().Substring(0, 200); }void Visit(TurfArticle turf) { this.Summary += turf.GetContent().Substring(0, 200); }

public string BuildSummary(List<IArticle> articles) {

foreach(var article in articles) {article.Accept(this);

}return Summary;

}}

Page 57: Design Patterns

Visitor example

57

class SportArticle : IArticle{

public string MatchId { get; }

public void Accept(IArticleVisitor visitor) { visitor.Visit(this); }}

class UpdateStatusArticleVisitor : IArticleVisitor{

void Visit(SportArticle sport) { this.IsLive = Amelco.GetStatus(sport.MatchId) == 2; }

void Visit(PokerArticle poker) { }

void Visit(TurfArticle turf) { this.IsLive = PMC.GetStatus(turf.RaceId) == 99; }

public bool IsReferenceLive(IArticle article) {

article.Accept(this);return this.IsLive;

}}

class TurfArticle : IArticle{

public string RaceId { get; }

public void Accept(IArticleVisitor visitor) { visitor.Visit(this); }}

Page 58: Design Patterns

Conclusion

“With great power, comes great responsibilities” – Uncle Ben

• Design patterns are powerful tools, don’t hesitate to use them but beware of :

– Complexity

– Performance

58

Page 59: Design Patterns

59

Page 60: Design Patterns

Find out more

• On https://techblog.betclicgroup.com/

Page 61: Design Patterns

About Betclic• Betclic Everest Group, one of the world leaders in online gaming, has a unique portfolio

comprising various complementary international brands: Betclic, Everest Gaming, bet-at-home.com, Expekt…

• Active in 100 countries with more than 12 million customers worldwide, the Group is committed to promoting secure and responsible gaming and is a member of several international professional associations including the EGBA (European Gaming and Betting Association) and the ESSA (European Sports Security Association).

• Through our brands, Betclic Everest Group places expertise, technological know-how and security at the heart of our strategy to deliver an on-line gaming offer attuned to the passion of our players.