Skip to content

Instantly share code, notes, and snippets.

@jsheridanwells
Last active February 19, 2021 09:25
Show Gist options
  • Save jsheridanwells/fb74f6fefa7be134eb12e1ab50a8ffce to your computer and use it in GitHub Desktop.
Save jsheridanwells/fb74f6fefa7be134eb12e1ab50a8ffce to your computer and use it in GitHub Desktop.
CSharp Design Patters

C# Design Patterns

Desde aqui.

Categories

Creational: Concerned w/ creating objects

  • Abstract
  • Factory - define an interface for creating an object, let subclasses decide which class to instantiate.
  • Singleton

Structural: Class and object composition

  • Decorator

Behavioral: Communication between object

  • Iterator
  • Observer

Factory:

Allows developer to request a object, type is created an returned behind the scenes.

Abstract Factory Factory for creating factories

Singleton:

Instantiates an object from a single point.

Eliminates option of creating more than one of the same object.

(If you are working with an insurance policy instance, you want to work on the same instance the whole time).

Non-Thread-Safe Implementation:

public class MySingleton
{
  private static MySingleTon _instance
  public static MySingleton Instance
  {
    get
    {
      if (_instance == null) _instance = new MySingleton();
      return _instance;
    }
  }
}

This works, but if two threads hit at the same time, it still creates two objects.

Thread-safe:

public class ThreadSafeSingleton
{
  private static readonly ThreadSafeSingleton _instance = new ThreadSafeSingleton();
  public static ThreadSafeSingleton Instance
  {
    get { return _instance; }
  }
}

Decorator Pattern (Wrapper Pattern)

Attaches additional responsibilities to an object dynamically.

Provides flexible alternative to subclassing for extending functionality.

Simplifies object relationships:

BaseClass -> DerivedClass -> Decorator.

public abstract class Car
{
  public string description { get; set; }
  public abstract string GetDescription();
  public abstract double GetPrice();
}

public class CarDecorator : Car
{
  protected Car _car;
  public CarDecorator(Car car)
  {
    _car = car;
  }
  public override double GetCarPrice() => _car.GetCarPrice();
  public override string GetCarDescription( => _car.GetDescription();
}

public class CompactCar : Car
{
  public CompactCar()
  {
    Description = "I'm a compact car";
  }
  public override string GetDescription() => Description;
  public override double GetCarPrice() => 10000.00;
}

public class LeatherSeats : CarDecorator
{
  public LeatherSeats(Car car) : base(car)
  {
    Description = "Leather Seats";
  }
  public override string GetDescription => $"{ _car.GetDescription() }, { Description }"; // Compact Car, Leather Seats
  public override double GetCarPrice => _car.GetCarPrice() + 2500;  //  12500.00
}

class Program 
{
  static voide Main(string[] args)
  {
    Car myCar = new CompactCar();
    theCar = new LeatherSeats(theCar);
  }
}

Iterator Pattern

  • Provides a way to access elements of an aggregate object without exposing its underlying representation

or...

  • A way to access collections regardless of type.
public interface INewspaper
{
  IIterator CreateIterator();
}

public class LAPaper : INewspaper
{
  _reporters = new[]
  {
    "reporter 1",
    "reporter 2",
    "reporter 3"
  }
  public IIterator CreateIterator()
  {
    return new LAPaperIterator(_reporters);
  }  
}

public interface IITerator
{
  void First();
  string Next();
  bool IsDone();
  string CurrentItem();
}

public class LAPaperIterator : IIterator
{
  private string[] _reporters;
  private int _current;
  
  public LAPaperIterator(string[] _reporters)
  {
    this._reporters = _reporters;
    _current = 0;
  }
  
  public string CurrentItems()
  {
    return _reports[_current;]
  }
  
  public void First()
  {
    _current = 0;
  }
  
  public void Next()
  {
    return _reporters[_current++];
  }
  
  public bool IsDone()
  {
    return _current >= reporters.Length;
  }
}

class Program
{
  static void Main(string[] args)
  {
    INewpaper lat = new LAPaper();
    IIterator lapIterator = lat.CreateIterator();
    Console.WriteLine("--- LA Paper");
    PrintReporters(lapIterator);
  }
  
  static void PrintReporters(IIterator iterator)
  {
    iterator.First();
    while(!iterator.IsDone())
    {
      Console.WriteLine(iterator.Next());
    }
  }
}

#3 Observer Pattern (Publisher/Subscriber)

One-to-many dependency. When one object is changed, dependents reflec that change.

AbstractSubject -> __AbstractObserver Attach(Observer) Update() Detach(Observer) Notify() -> o in observers, update()

ImplementedSubject -> ImplementedObserver GetState() SetState() Update() observerState = subject.GetState()

Repository Pattern

Separating business logic from data layer.

Cient -> Business Entity -> Repo(dataMapper) + Repo(Query Object) -> Data Source

Unit of Work

A list of objects affected by a business transaction, coordinates the writing out of changes and the resolution of concurrency problems.

Makes it possible to update data across repositories in only one transaction to the database.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment