Design Patterns

Bilel Msekni

Who am I ?

Bilel Msekni

Tech Lead & Frontend Expert

"A general, reusable solution to a commonly occurring problem"

- Wikipedia

Singleton Pattern

(Creational)

Solution:

Create a class responsible for instanciating and returning the instance on subsequent calls.

Problem:

How can we guarantee that one and only one

instance of a class can be created?

Singleton Pattern

(Creational)

public sealed class Singleton {

 private static readonly Singleton instance = new Singleton();

 private Singleton() {}

 public static Singleton Instance => instance

}
...
private static readonly object padlock = new object();

public static Singleton Instance {
 get {
  if (instance == null) {
   lock(padlock) {
    if (instance == null) instance = new Singleton();
   }
  }
  return instance;
 }
}

The good...

  • A class has only a single instance.
  • A global access point to that instance.
  • Initialized only when it’s requested for the first time.

And the bad

  • Violates the Single Responsibility Principle
  •  Special treatment in a multithreaded environment
  •  It may be difficult to unit test

Singleton Pattern

(Creational)

Facade Pattern

(Structural)

Problem:

How can we access a large number of classes with a complex internal interaction in a simple but safe way?

Solution:

Introduce a dedicated interface class that simplifies the view of the class collection

Facade Pattern

(Structural)

Suppliers

Payment

Delivery

...

Facade

Facade Pattern

(Structural)

public class Facade {
 private Suppliers _suppliers;
 private Payment _payment;

 public Facade(Suppliers suppliers, Payment payment) {
  this._suppliers = suppliers;
  this._payment = payment;
 }

 public void Purchase(string id, int quantity) {
  Command command = _suppliers.provision(id, quantity);
  Payment payment = _payment.pay(command.Amount);
 }
}

class Client {
 public void Buy(Facade facade) {
  string id = GetElementId();
  int quantity = GetQuantity();
  facade.Purchase(id, quantity);
 }
}
class Client {
 private Suppliers _suppliers;
 private Payment _payment;

 public Client(Suppliers suppliers, Payment payment) {
  this._suppliers = suppliers;
  this._payment = payment;
 }
 
 public void Buy(Facade facade) {
  string id = GetElementId();
  int quantity = GetQuantity();
  Command command = _suppliers.provision(id, quantity);
  Payment payment = _payment.pay(command.Amount);
 }
}

The Good...

  • Isolate the complexity of a subsystem

And the bad

  • Over time a facade can evolve into a God Object.

Facade Pattern

(Structural)

  • Use only what you need strategy
  • The full capability of the underlying APIs will often not be available

Mediator Pattern

(Behavior)

Problem:

How can we deal with two or more classes which sometimes interact, but can also be used separately?

Solution:

Keep objects from referring to one another explicitly by puting each interaction between objects in a separate (Mediator) class.

Mediator Pattern

(Behavior)

Mediator Pattern

(Behavior)

Demo time

Mediator Pattern

(Behavior)

The Good...

  •  Single Responsibility Principle

And the bad

Over time a mediator can evolve into a God Object.

  •  Open/Closed Principle
  •  Reduce coupling between various components

To read

To watch

Thank you

Made with Slides.com