Design Patterns Training
02/2014
Agenda





What’s a design pattern…
Pros / Cons
Families
Patterns x10

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

2
Homework
 Object-Oriented Design :






Coupling
Cohesion
Inheritance
Interface
Polymorphism

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

3
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
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
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
Families : Creational Patterns
 Control object creation mechanisms








Singleton*
Builder*
Abstract Factory
Prototype
Factory method*
Lazy initialization
Object pool

7
Families : Structural Patterns
 Ease relationships between entities







Adapter*
Decorator*
Composite*
Aggregate
Façade*
Proxy

8
Families : Behavioral Patterns
 Increase flexibility and communication between objects







Chain of responsibility*
Command
Iterator
Observer
Visitor*
Strategy*

9
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
11
12
Singleton
 Restricts instanciation of a class to one object.
 Provides a global point of access to it

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

13
Singleton - Code
Naive implementation

public static class Utils
{
private static IUtilsInstance _instance;
public static IUtilsInstance Instance
{
get
{
if (_instance != null)
_instance = new UtilsInstance();
}
return _instance;
}
}
}

14
Singleton - Code
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; }
}
}

15
Builder
 Separate construction of a complex object from its representation
 Solution to the telescoping constructor anti-pattern


Many parameters, mandatory or optional

17
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
public
public
public

BadCar(bool
BadCar(bool
BadCar(bool
BadCar(bool

hasGps);
hasGps, bool isCityCar);
isCabrioletCar, int seats);
hasGps, bool isCityCar, bool isSportCar, bool isCabrioletCar, int seats);

}

Program :
public void main()
{
var car = new BadCar(false, false, true, false, 2);
}

18
Without Builder
Issue with polymorphism :
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)
{
}
}

19
With Builder
public class
{
public
public
public
public
public
}

Car

bool HasGPS { get; set; }
bool IsCityCar { get; set; }
bool IsSportCar { get; set; }
bool IsCabrioletCar { get; set; }
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 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 SetSportsCar()
{
Car.IsSportCar = true;
return this;
}

public CarBuilder Builder { get; private set; }
private Car(CarBuilder Builder);
}

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

}

• Wrap properties set into methods
• Really easy to make it « fluent »
20
With Builder

public class Prog
{
public void Main()
{
var builder = new CarBuilder();

• Initialization is wordy
• Extension is easy
• Polymorphism

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

21
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

Note : Subclassing implementation depends on private constructor = class cannot be extended
if protected constructor = subclass have to redefine all factory methods !
23
Example
public interface ICar
{
string GetType();
}

class Sedan : ICar
{
public string GetType() { return "Sedan"; }
}

public interface ICarFactory
{
ICar MakeCar(int nbDoors);
}

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

24
Adapter
 Convert the interface of a class into another interface clients expect
 Helps two incompatible interfaces to work together

26
Without adapter
public class DataParser
{
private string Data;
public void SetData(string data)
{
this.Data = data;
}
public void ParseData()
{
Console.WriteLine(this.Data.Replace(" - ", " / "));
}

public class Prog
{
public void Main()
{
var a = new DataParser();
var b = new DataProvider();
a.SetData(b.GetStringData());
a.ParseData();
}
}

}

public class DataProvider
{
public string[] Datas;
public string GetStringData()
{
return this.Datas.Aggregate(string.Empty, (current, data) => current + (data + " - "));
}
}

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

28
Decorator
 Attach additional responsibilities to an object dynamically keeping the same interface

30
Without Decorator
public interface IArmor
{
void Fight();
string GetDescription();
}

public class SimpleArmor : IArmor
{
public virtual void Fight()
{
//Launch Simple missile
}

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

public virtual string GetDescription()
{
return "Armor Mark I";
}
}

31
Without Decorator
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";
}
}

32
Without Decorator
public class SimpleArmorWithTazer : SimpleArmor
{
public override void Fight()
{ public class SimpleWindowWithLaserAndTazer : SimpleArmorWithLaser
base.Fight();
{
this.EnableTazer();
public override void Fight()
}
{
base.Fight();
private void EnableTazer()
this.EnableTazer();
{
}
// Enable Heart Attack Tazer
}
private void EnableTazer()

}

{
public override string GetDescription()
// Enable Heart Attack Tazer
{
}
return "Mark II with Tazer";
}
public override string GetDescription()
{
return base.GetDescription() + " and with Tazer";
}
}
33
With Decorator
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();
}
}

34
With Decorator
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";
}
}

35
With Decorator
public class LaserDecorator : ArmorDecorator
{
public LaserDecorator(IArmor decoratedArmor) : base(decoratedArmor) { }
public override void Fight()
{
base.Fight();
public class TazerDecorator : ArmorDecorator
{ LaunchLaser();
}
public TazerDecorator(IArmor decoratedArmor) : base(decoratedArmor) { }

}

private void override void Fight()
public LaunchLaser()
{
{
// Enable BBQ Laser
base.Fight();
}
EnableTazer();
}
public override string GetDescription()
{
private void EnableTazer()
return base.GetDescription() + " with Laser";
{
}
// Enable Heazrt Attack Tazer
}
public override string GetDescription()
{
return base.GetDescription() + " with Tazer";
}
}
36
With Decorator
public class Jarvis
{
public void Main()
{
IArmor ironman = new TazerDecorator(new LaserDecorator(new SimpleArmor()));
Console.WriteLine(ironman.GetDescription());
}
}

37
Composite
 Compose objects into tree structures to represent part-whole hierarchies

39
Composite Example
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");
}
}

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

42
43
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
Façade example
/* 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) { ... }
}

45
Façade example
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();
}
}

46
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
Chain of responsibility example - pipeline
Task
Task
Task

Processor

Login
Processor

Request
Login = «testuser»
Password = « pwd123 »
Status = ok
User = null

Authentication
Task

Request
Login = «testuser»
Password = « pwd123 »
Status = ok
User = null

Request
Infos
Status

Fraud
Task

Request
Login
Password
Status = Forbidden by Fraud
User = null

49
50
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.

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

51
Strategy example
interface DepositStrategy
{
decimal Execute(decimal amount);
};
class Eiole : DepositStrategy
{
private decimal feeAmount = 10;

class Metacharge : DepositStrategy
{
private decimal feeRate = 0,05;

public decimal Execute(decimal amount)
{
return amount + feeAmount;
}
};

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

52
Strategy example
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

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

Note : Implementation may have a real impact on performance !

55
Visitor example
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;
}
}

56
Visitor example
class SportArticle : IArticle
{
public string MatchId { get; }
public void Accept(IArticleVisitor visitor) { visitor.Visit(this); }
}
class TurfArticle : IArticle
{
public string RaceId { 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;
}

}

57
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
59
Find out more
• On https://techblog.betclicgroup.com/
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-athome.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.

Design Patterns

  • 1.
  • 2.
    Agenda     What’s a designpattern… Pros / Cons Families Patterns x10 All photos and pictures included in those slides are courtesy and copyright of their respective owners. 2
  • 3.
    Homework  Object-Oriented Design:      Coupling Cohesion Inheritance Interface Polymorphism  S.O.L.I.D. principles  Refer A. Sauvinet mini-training 3
  • 4.
    Definition  In softwareengineering, 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
  • 5.
    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
  • 6.
    Families  3 mainfamilies :  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
  • 7.
    Families : CreationalPatterns  Control object creation mechanisms        Singleton* Builder* Abstract Factory Prototype Factory method* Lazy initialization Object pool 7
  • 8.
    Families : StructuralPatterns  Ease relationships between entities       Adapter* Decorator* Composite* Aggregate Façade* Proxy 8
  • 9.
    Families : BehavioralPatterns  Increase flexibility and communication between objects       Chain of responsibility* Command Iterator Observer Visitor* Strategy* 9
  • 10.
    And what aboutthe 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
  • 11.
  • 12.
  • 13.
    Singleton  Restricts instanciationof a class to one object.  Provides a global point of access to it Note : be careful with multithread, use (double) lock pattern 13
  • 14.
    Singleton - Code Naiveimplementation public static class Utils { private static IUtilsInstance _instance; public static IUtilsInstance Instance { get { if (_instance != null) _instance = new UtilsInstance(); } return _instance; } } } 14
  • 15.
    Singleton - Code publicstatic 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; } } } 15
  • 17.
    Builder  Separate constructionof a complex object from its representation  Solution to the telescoping constructor anti-pattern  Many parameters, mandatory or optional 17
  • 18.
    Without Builder public classBadCar { 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 public public public BadCar(bool BadCar(bool BadCar(bool BadCar(bool hasGps); hasGps, bool isCityCar); isCabrioletCar, int seats); hasGps, bool isCityCar, bool isSportCar, bool isCabrioletCar, int seats); } Program : public void main() { var car = new BadCar(false, false, true, false, 2); } 18
  • 19.
    Without Builder Issue withpolymorphism : 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) { } } 19
  • 20.
    With Builder public class { public public public public public } Car boolHasGPS { get; set; } bool IsCityCar { get; set; } bool IsSportCar { get; set; } bool IsCabrioletCar { get; set; } 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 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 SetSportsCar() { Car.IsSportCar = true; return this; } public CarBuilder Builder { get; private set; } private Car(CarBuilder Builder); } public CarBuilder SetCabriolet(); public CarBuilder SetGps(); … } • Wrap properties set into methods • Really easy to make it « fluent » 20
  • 21.
    With Builder public classProg { public void Main() { var builder = new CarBuilder(); • Initialization is wordy • Extension is easy • Polymorphism builder.SetSeats(2); builder.SetSportsCar(); var car = builder.GetCar(); ... var fluentCar = builder.SetSeats(2).SetSportsCar().SetGps().GetCar(); } } 21
  • 23.
    Factory Method  Definean 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 Note : Subclassing implementation depends on private constructor = class cannot be extended if protected constructor = subclass have to redefine all factory methods ! 23
  • 24.
    Example public interface ICar { stringGetType(); } class Sedan : ICar { public string GetType() { return "Sedan"; } } public interface ICarFactory { ICar MakeCar(int nbDoors); } 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); } } 24
  • 26.
    Adapter  Convert theinterface of a class into another interface clients expect  Helps two incompatible interfaces to work together 26
  • 27.
    Without adapter public classDataParser { private string Data; public void SetData(string data) { this.Data = data; } public void ParseData() { Console.WriteLine(this.Data.Replace(" - ", " / ")); } public class Prog { public void Main() { var a = new DataParser(); var b = new DataProvider(); a.SetData(b.GetStringData()); a.ParseData(); } } } public class DataProvider { public string[] Datas; public string GetStringData() { return this.Datas.Aggregate(string.Empty, (current, data) => current + (data + " - ")); } } 27
  • 28.
    With adapter public classDataParserFormat1Adapter { 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(); } } 28
  • 30.
    Decorator  Attach additionalresponsibilities to an object dynamically keeping the same interface 30
  • 31.
    Without Decorator public interfaceIArmor { void Fight(); string GetDescription(); } public class SimpleArmor : IArmor { public virtual void Fight() { //Launch Simple missile } 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"; } } public virtual string GetDescription() { return "Armor Mark I"; } } 31
  • 32.
    Without Decorator public classSimpleArmorWithTazer : 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"; } } 32
  • 33.
    Without Decorator public classSimpleArmorWithTazer : SimpleArmor { public override void Fight() { public class SimpleWindowWithLaserAndTazer : SimpleArmorWithLaser base.Fight(); { this.EnableTazer(); public override void Fight() } { base.Fight(); private void EnableTazer() this.EnableTazer(); { } // Enable Heart Attack Tazer } private void EnableTazer() } { public override string GetDescription() // Enable Heart Attack Tazer { } return "Mark II with Tazer"; } public override string GetDescription() { return base.GetDescription() + " and with Tazer"; } } 33
  • 34.
    With Decorator public abstractclass 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(); } } 34
  • 35.
    With Decorator public classLaserDecorator : 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"; } } 35
  • 36.
    With Decorator public classLaserDecorator : ArmorDecorator { public LaserDecorator(IArmor decoratedArmor) : base(decoratedArmor) { } public override void Fight() { base.Fight(); public class TazerDecorator : ArmorDecorator { LaunchLaser(); } public TazerDecorator(IArmor decoratedArmor) : base(decoratedArmor) { } } private void override void Fight() public LaunchLaser() { { // Enable BBQ Laser base.Fight(); } EnableTazer(); } public override string GetDescription() { private void EnableTazer() return base.GetDescription() + " with Laser"; { } // Enable Heazrt Attack Tazer } public override string GetDescription() { return base.GetDescription() + " with Tazer"; } } 36
  • 37.
    With Decorator public classJarvis { public void Main() { IArmor ironman = new TazerDecorator(new LaserDecorator(new SimpleArmor())); Console.WriteLine(ironman.GetDescription()); } } 37
  • 39.
    Composite  Compose objectsinto tree structures to represent part-whole hierarchies 39
  • 40.
    Composite Example public interfaceIDrawable { void Render(); } public class Ellipse : IDrawable { public void Render() { Console.WriteLine("Ellipse"); } } public class Square: IDrawable { public void Render() { Console.WriteLine("Square"); } } 40
  • 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(); } } } 41
  • 42.
    public class FrankensteinReturn { publicvoid 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); } } 42
  • 43.
  • 44.
    Façade  Provide aunified 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
  • 45.
    Façade example /* Complexparts */ 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) { ... } } 45
  • 46.
    Façade example class ComputerFacade { privateCPU 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(); } } 46
  • 48.
    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
  • 49.
    Chain of responsibilityexample - pipeline Task Task Task Processor Login Processor Request Login = «testuser» Password = « pwd123 » Status = ok User = null Authentication Task Request Login = «testuser» Password = « pwd123 » Status = ok User = null Request Infos Status Fraud Task Request Login Password Status = Forbidden by Fraud User = null 49
  • 50.
  • 51.
    Strategy  Define afamily 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. Note : For more information, key words : Policy-based design 51
  • 52.
    Strategy example interface DepositStrategy { decimalExecute(decimal amount); }; class Eiole : DepositStrategy { private decimal feeAmount = 10; class Metacharge : DepositStrategy { private decimal feeRate = 0,05; public decimal Execute(decimal amount) { return amount + feeAmount; } }; 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); } }; 52
  • 53.
    Strategy example class DepositService { publicvoid 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 53
  • 55.
    Visitor  Represent anoperation 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. Note : Implementation may have a real impact on performance ! 55
  • 56.
    Visitor example interface IArticleVisitor { voidVisit(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; } } 56
  • 57.
    Visitor example class SportArticle: IArticle { public string MatchId { get; } public void Accept(IArticleVisitor visitor) { visitor.Visit(this); } } class TurfArticle : IArticle { public string RaceId { 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; } } 57
  • 58.
    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
  • 59.
  • 60.
    Find out more •On https://techblog.betclicgroup.com/
  • 61.
    About Betclic • • • Betclic EverestGroup, one of the world leaders in online gaming, has a unique portfolio comprising various complementary international brands: Betclic, Everest Gaming, bet-athome.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.