Design Patterns

https://www.dofactory.com/net/design-patterns

Creational Patterns

Singleton Pattern

Why Singletons are Evil

Strategy pattern

https://en.wikipedia.org/wiki/Strategy_pattern

The strategy pattern(also known as thepolicy pattern) is a behavioral software design patternthat enables selecting analgorithmat runtime. Deferring the decision about which algorithm to use until runtime allows the calling code to be more flexible and reusable.

According to the strategy pattern, the behaviors of a class should not be inherited. Instead they should be encapsulated using interfaces. This is compatible with the open/closed principle (OCP), which proposes that classes should be open for extension but closed for modification.

As an example, consider a car class. Two possible functionalities for car are brake and accelerate. Since accelerate and brake behaviors change frequently between models, a common approach is to implement these behaviors in subclasses. This approach has significant drawbacks: accelerate and brake behaviors must be declared in each new Car model. The work of managing these behaviors increases greatly as the number of models increases, and requires code to be duplicated across models. Additionally, it is not easy to determine the exact nature of the behavior for each model without investigating the code in each.

The strategy pattern uses composition instead of inheritance. In the strategy pattern, behaviors are defined as separate interfaces and specific classes that implement these interfaces. This allows better decoupling between the behavior and the class that uses the behavior. The behavior can be changed without breaking the classes that use it, and the classes can switch between behaviors by changing the specific implementation used without requiring any significant code changes. Behaviors can also be changed at run-time as well as at design-time.

public class StrategyPatternWiki
{
    public static void Main(String[] args)
    {
        // Prepare strategies
        IBillingStrategy normalStrategy    = new NormalStrategy();
        IBillingStrategy happyHourStrategy = new HappyHourStrategy();

        Customer firstCustomer = new Customer(normalStrategy);

        // Normal billing
        firstCustomer.Add(1.0, 1);

        // Start Happy Hour
        firstCustomer.Strategy = happyHourStrategy;
        firstCustomer.Add(1.0, 2);

        // New Customer
        Customer secondCustomer = new Customer(happyHourStrategy);
        secondCustomer.Add(0.8, 1);
        // The Customer pays
        firstCustomer.PrintBill();

        // End Happy Hour
        secondCustomer.Strategy = normalStrategy;
        secondCustomer.Add(1.3, 2);
        secondCustomer.Add(2.5, 1);
        secondCustomer.PrintBill();
    }
}


class Customer
{
    private IList<double> drinks;

    // Get/Set Strategy
    public IBillingStrategy Strategy { get; set; }

    public Customer(IBillingStrategy strategy)
    {
        this.drinks = new List<double>();
        this.Strategy = strategy;
    }

    public void Add(double price, int quantity)
    {
        drinks.Add(Strategy.GetActPrice(price * quantity));
    }

    // Payment of bill
    public void PrintBill()
    {
        double sum = 0;
        foreach (double i in drinks)
        {
            sum += i;
        }
        Console.WriteLine("Total due: " + sum);
        drinks.Clear();
    }
}

interface IBillingStrategy
{
    double GetActPrice(double rawPrice);
}

// Normal billing strategy (unchanged price)
class NormalStrategy : IBillingStrategy
{
    public double GetActPrice(double rawPrice)
    {
        return rawPrice;
    }

}

// Strategy for Happy hour (50% discount)
class HappyHourStrategy : IBillingStrategy
{
    public double GetActPrice(double rawPrice)
    {
        return rawPrice * 0.5;
    }
}

State pattern

https://en.wikipedia.org/wiki/State_pattern

https://www.dofactory.com/net/state-design-pattern

The state pattern is a behavioral software design pattern that implements a state machine in an object-oriented way. With the state pattern, a state machine is implemented by implementing each individual state as a derived class of the state pattern interface, and implementing state transitions by invoking methods defined by the pattern's superclass.

using System;

namespace DoFactory.GangOfFour.State.Structural
{
  /// <summary>

  /// MainApp startup class for Structural

  /// State Design Pattern.

  /// </summary>

  class MainApp

  {
    /// <summary>

    /// Entry point into console application.

    /// </summary>

    static void Main()
    {
      // Setup context in a state

      Context c = new Context(new ConcreteStateA());

      // Issue requests, which toggles state

      c.Request();
      c.Request();
      c.Request();
      c.Request();

      // Wait for user

      Console.ReadKey();
    }
  }

  /// <summary>

  /// The 'State' abstract class

  /// </summary>

  abstract class State

  {
    public abstract void Handle(Context context);
  }

  /// <summary>

  /// A 'ConcreteState' class

  /// </summary>

  class ConcreteStateA : State

  {
    public override void Handle(Context context)
    {
      context.State = new ConcreteStateB();
    }
  }

  /// <summary>

  /// A 'ConcreteState' class

  /// </summary>

  class ConcreteStateB : State

  {
    public override void Handle(Context context)
    {
      context.State = new ConcreteStateA();
    }
  }

  /// <summary>

  /// The 'Context' class

  /// </summary>

  class Context

  {
    private State _state;

    // Constructor

    public Context(State state)
    {
      this.State = state;
    }

    // Gets or sets the state

    public State State
    {
      get { return _state; }
      set

      {
        _state = value;
        Console.WriteLine("State: " +
          _state.GetType().Name);
      }
    }

    public void Request()
    {
      _state.Handle(this);
    }
  }
}

Special Case Pattern

https://martinfowler.com/eaaCatalog/specialCase.html

Null object Pattern

https://en.wikipedia.org/wiki/Null_object_pattern

/* Null object pattern implementation:
 */
using System;

// Animal interface is the key to compatibility for Animal implementations below.
interface IAnimal
{
    void MakeSound();
}

// Animal is the base case.
abstract class Animal : IAnimal
{
    // A shared instance that can be used for comparisons
    public static readonly IAnimal Null = new NullAnimal();

    // The Null Case: this NullAnimal class should be used in place of C# null keyword.
    private class NullAnimal : Animal
    {
        public override void MakeSound()
        {
            // Purposefully provides no behaviour.
        }
    }
    public abstract void MakeSound();
}

// Dog is a real animal.
class Dog : IAnimal
{
    public void MakeSound()
    {
        Console.WriteLine("Woof!");
    }
}

/* =========================
 * Simplistic usage example in a Main entry point.
 */
static class Program
{
    static void Main()
    {
        IAnimal dog = new Dog();
        dog.MakeSound(); // outputs "Woof!"

        /* Instead of using C# null, use the Animal.Null instance.
         * This example is simplistic but conveys the idea that if the Animal.Null instance is used then the program
         * will never experience a .NET System.NullReferenceException at runtime, unlike if C# null were used.
         */
        IAnimal unknown = Animal.Null;  //<< replaces: IAnimal unknown = null;
        unknown.MakeSound(); // outputs nothing, but does not throw a runtime exception        
    }
}

Enterprise Application Architecture Patterns

https://martinfowler.com/eaaCatalog/

results matching ""

    No results matching ""