igritco
11/30/2015 - 5:49 PM

Design patterns

Design patterns

---SINGLETON---
http://csharpindepth.com/Articles/General/Singleton.aspx#dcl
First version of code 
// Bad code! Do not use!
public sealed class Singleton
{
    private static Singleton instance = null;
    private static readonly object padlock = new object();

    Singleton()
    {
    }

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

The most simple implementation is this -  in this case the environment makes sure that the problems with lock and threads are solved
public sealed class Singleton
{
    private static readonly Singleton instance = new Singleton();

    // Explicit static constructor to tell C# compiler
    // not to mark type as beforefieldinit
    static Singleton()
    {
    }

    private Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            return instance;
        }
    }
}

Recommended >.NET 4
public sealed class Singleton
{
    private static readonly Lazy<Singleton> lazy =
        new Lazy<Singleton>(() => new Singleton());
    
    public static Singleton Instance { get { return lazy.Value; } }

    private Singleton()
    {
    }
}
https://en.wikipedia.org/wiki/Null_Object_pattern
Mediator poate fi folosit cand dorim sa avem mai multe componente care sa nu fie legate direct intre ele. 
De exemplu, daca am avea o aplicatie desktop cu un combo box si in functie de ce alegem sa se modifice alte doua componente.
In mod simplist, am adauga event handler pentru combobox si cand se schimba valoarea am modifica celelalte componente.
Dar, asta inseamna o cuplare foarte mare!

Cu mediator, noi putem crea o clasa intermediara de tip singleton, care va avea un event, de exemplu OnComboChanged, iar in event handlerul de 
combobox changed noi pur si simplu vom apela delegate-ul eventului. In felul asta noi putem subscrie la acel event numeroare functii si se vor actiona in acelasi timp
toate metodele.
Delegate a = new Delegate();
a.OnComboChanged+=FunctiaX;
a.OnComboChanged+=FunctiaY;
a.OnComboChanged+=FunctiaZ;

E ca si cum am notifica toate celelalte elemente care au instanta de mediator, ca s-a schimbat ceva!

https://en.wikipedia.org/wiki/Mediator_pattern
http://www.codeproject.com/Tips/620215/Four-Ways-to-Implement-Lazy-Loading-in-Csharp
http://www.codeproject.com/Articles/362986/Understanding-and-Implementing-the-Iterator-Patter
http://www.dofactory.com/net/interpreter-design-pattern
http://www.dofactory.com/net/flyweight-design-pattern
class Program
{
    static void Main(string[] args)
    {
        Worker a = new Worker("Worker Tom", 5);
        Supervisor b = new Supervisor("Supervisor Mary", 6);
        Supervisor c = new Supervisor("Supervisor Jerry", 7);
        Supervisor d = new Supervisor("Supervisor Bob", 9);
        Worker e = new Worker("Worker Jimmy", 8);

        //set up the relationships
        b.AddSubordinate(a); //Tom works for Mary
        c.AddSubordinate(b); //Mary works for Jerry
        c.AddSubordinate(d); //Bob works for Jerry
        d.AddSubordinate(e); //Jimmy works for Bob

        //Jerry shows his happiness and asks everyone else to do the same
        if (c is IEmployee)
            (c as IEmployee).ShowHappiness();
    }
}

public interface IEmployee
{
    void ShowHappiness();
}

public class Worker : IEmployee
{
    private string name;
    private int happiness;

    public Worker(string name, int happiness)
    {
        this.name = name;
        this.happiness = happiness;
    }

    void IEmployee.ShowHappiness()
    {
        Console.WriteLine(name + " showed happiness level of " + happiness);
    }
}

public class Supervisor : IEmployee
{
    private string name;
    private int happiness;

    private List<iemployee> subordinate = new List<iemployee>();

    public Supervisor(string name, int happiness)
    {
        this.name = name;
        this.happiness = happiness;
    }

    void IEmployee.ShowHappiness()
    {
        Console.WriteLine(name + " showed happiness level of " + happiness);
        //show all the subordinate's happiness level
        foreach (IEmployee i in subordinate)
            i.ShowHappiness();
    }

    public void AddSubordinate(IEmployee employee)
    {
        subordinate.Add(employee);
    }
}
namespace CommandPattern
{
    using System; 
    public interface ICommand
    {
        void Execute();
    }

    /* The Invoker class */
    public class Switch
    {
        ICommand _closedCommand;
        ICommand _openedCommand;

        public Switch(ICommand closedCommand, ICommand openedCommand)
        {
            this._closedCommand = closedCommand;
            this._openedCommand = openedCommand;
        }

        //close the circuit/power on
        public void Close()
        {
           this._closedCommand.Execute();
        }

        //open the circuit/power off
        public void Open()
        {
            this._openedCommand.Execute();
        }
    }
    
    /* An interface that defines actions that the receiver can perform */
    public interface ISwitchable
    {
        void PowerOn();
        void PowerOff();
    }

    /* The Receiver class */
    public class Light : ISwitchable
    {
        public void PowerOn()
        {
            Console.WriteLine("The light is on");
        }

        public void PowerOff()
        {
            Console.WriteLine("The light is off");
        }
    }

    /* The Command for turning on the device - ConcreteCommand #1 */
    public class CloseSwitchCommand: ICommand
    {
        private ISwitchable _switchable;

        public CloseSwitchCommand(ISwitchable switchable)
        {
            _switchable = switchable;
        }

        public void Execute()
        {
            _switchable.PowerOn();
        }
    }

    /* The Command for turning off the device - ConcreteCommand #2 */
    public class OpenSwitchCommand : ICommand
    {
        private ISwitchable _switchable;

        public OpenSwitchCommand(ISwitchable switchable)
        {
            _switchable = switchable;
        }

        public void Execute()
        {
            _switchable.PowerOff();
        }
    }

    /* The test class or client */
    internal class Program
    {
        public static void Main(string[] args)
        {
            string arg = args.Length > 0 ? args[0].ToUpper() : null;

            ISwitchable lamp = new Light();

            //Pass reference to the lamp instance to each command
            ICommand switchClose = new CloseSwitchCommand(lamp);
            ICommand switchOpen = new OpenSwitchCommand(lamp);

            //Pass reference to instances of the Command objects to the switch
            Switch @switch = new Switch(switchClose, switchOpen);
            
            if (arg == "ON")
            {
                // Switch (the Invoker) will invoke Execute() (the Command) on the command object - _closedCommand.Execute();
                @switch.Close();
            }
            else if (arg == "OFF")
            {
                //Switch (the Invoker) will invoke the Execute() (the Command) on the command object - _openedCommand.Execute();
                @switch.Open();
            }
            else
            {
                Console.WriteLine("Argument \"ON\" or \"OFF\" is required.");
            }
        }
    }
}
public abstract class Handler
{
 protected Handler _successor;
 
 public abstract void HandleRequest(int request);
 
 public void SetSuccessor(Handler successor)
 {
 _successor = successor;
 }
}
 
public class ConcreteHandlerA : Handler
{
 public override void HandleRequest(int request)
 {
 if (request == 1)
 Console.WriteLine("Handled by ConcreteHandlerA");
 else if (_successor != null)
 _successor.HandleRequest(request);
 }
}
 
public class ConcreteHandlerB : Handler
{
 public override void HandleRequest(int request)
 {
 if (request > 10)
 Console.WriteLine("Handled by ConcreteHandlerB");
 else if (_successor != null)
 _successor.HandleRequest(request);
 }
}
//Represents a product created by the builder
public class Car
{
    public Car()
    {
    }

    public int Wheels { get; set; }

    public string Colour { get; set; }
}

//The builder abstraction
public interface ICarBuilder
{
    // Adding NotNull attribute to prevent null input argument
    void SetColour([NotNull]string colour);

    // Adding NotNull attribute to prevent null input argument
    void SetWheels([NotNull]int count);

    Car GetResult();
}

//Concrete builder implementation
public class CarBuilder : ICarBuilder
{
    private Car _car;

    public CarBuilder()
    {
        this._car = new Car();
    }

    public void SetColour(string colour)
    {
        this._car.Colour = colour;
    }

    public void SetWheels(int count)
    {
        this._car.Wheels = count;
    }

    public Car GetResult()
    {
        return this._car;
    }
}

//The director
public class CarBuildDirector
{
    public Car Construct()
    {
        CarBuilder builder = new CarBuilder();

        builder.SetColour("Red");
        builder.SetWheels(4);

        return builder.GetResult();
    }
}
/// <summary>
/// The 'Abstraction' class
/// </summary>
public abstract class Message
{
 public IMessageSender MessageSender { get; set; }
 public string Subject { get; set; }
 public string Body { get; set; }
 public abstract void Send();
}
 
/// <summary>
/// The 'RefinedAbstraction' class
/// </summary>
public class SystemMessage : Message
{
 public override void Send()
 {
 MessageSender.SendMessage(Subject, Body);
 }
}
 
/// <summary>
/// The 'RefinedAbstraction' class
/// </summary>
public class UserMessage : Message
{
 public string UserComments { get; set; }
 
 public override void Send()
 {
 string fullBody = string.Format("{0}\nUser Comments: {1}", Body, UserComments);
 MessageSender.SendMessage(Subject, fullBody);
 }
}
 
/// <summary>
/// The 'Bridge/Implementor' interface
/// </summary>
public interface IMessageSender
{
 void SendMessage(string subject, string body);
}
 
/// <summary>
/// The 'ConcreteImplementor' class
/// </summary>
public class EmailSender : IMessageSender
{
 public void SendMessage(string subject, string body)
 {
 Console.WriteLine("Email\n{0}\n{1}\n", subject, body);
 }
}
 
/// <summary>
/// The 'ConcreteImplementor' class
/// </summary>
public class MSMQSender : IMessageSender
{
 public void SendMessage(string subject, string body)
 {
 Console.WriteLine("MSMQ\n{0}\n{1}\n", subject, body);
 }
}
 
/// <summary>
/// The 'ConcreteImplementor' class
/// </summary>
public class WebServiceSender : IMessageSender
{
 public void SendMessage(string subject, string body)
 {
 Console.WriteLine("Web Service\n{0}\n{1}\n", subject, body);
 }
}
 
/// <summary>
/// Bridge Design Pattern Demo
/// </summary>
class Program
{
 static void Main(string[] args)
 {
 IMessageSender email = new EmailSender();
 IMessageSender queue = new MSMQSender();
 IMessageSender web = new WebServiceSender();
 
 Message message = new SystemMessage();
 message.Subject = "Test Message";
 message.Body = "Hi, This is a Test Message";
 
 message.MessageSender = email;
 message.Send();
 
 message.MessageSender = queue;
 message.Send();
 
 message.MessageSender = web;
 message.Send();
 
 UserMessage usermsg = new UserMessage();
 usermsg.Subject = "Test Message";
 usermsg.Body = "Hi, This is a Test Message";
 usermsg.UserComments = "I hope you are well";
 
 usermsg.MessageSender = email;
 usermsg.Send();
 
 Console.ReadKey();
 }
}
Now let’s look at an example to see how adapter pattern works. Imagine an online shopping portal which displays the products for selling on its home page. These products are coming from a third party vendor with which the portal has tied hands to sell products. The third party vendor already has an inventory system in place which can give the list of products it is selling There is no interface available to online shopping portal with which the portal can call the third party vendor’s inventor code.

Since we want to call the third party vendor’s code which is incompatible with client (online shopping portal) code we can apply “Adapter design pattern” here. Let’s first fit in various participants of an adapter pattern in our scenario.
ITarget: Method which the online shopping portal calls to get the list of products. Here getting the list of products is the functionality which this portal wants to achieve and this request has been encapsulated in this interface. In short- Functionality to achieve is exposed through this interface.
Adaptee: The third party vendor’s code which gives us the list of products.
Adapter: The wrapper which would implement ITarget and would call third party vendor’s code.
Client: The online shopping portal code which gets the list of products and then displays them.
Let’s have a look at the code demonstrating adapter pattern depicting the above scenario then we would revisit the various classes to map them to the adapter pattern participant’s.
Hide   Shrink    Copy Code
interface ITarget
{
  List<string> GetProducts();
}


public class VendorAdaptee
{
   public List<string> GetListOfProducts()
   {
      List<string> products = new List<string>();
      products.Add("Gaming Consoles");
      products.Add("Television");
      products.Add("Books");
      products.Add("Musical Instruments");
      return products;
   }
}


class VendorAdapter:ITarget
{
   public List<string> GetProducts()
   {
      VendorAdaptee adaptee = new VendorAdaptee();
      return adaptee.GetListOfProducts();
   }
}


class ShoppingPortalClient
{
   static void Main(string[] args)
   {
      ITarget adapter = new  VendorAdapter();
      foreach (string product in adapter.GetProducts())
      {
        Console.WriteLine(product);
      }
      Console.ReadLine();
   }
}
In the above code the participants are mapped as: ITarget: interface ITarget Adapter: class VendorAdapter, implementing the ITarget interface and acting as a wrapper/link between VendorAdaptee and ShoppingPortalClient. Adaptee: class VendorAdaptee, this is the code which ShoppingPortalClient is interested in calling. Client: class ShoppingPortalClient, the client wants to call the code of VendorAdptee. The code above is self-explanatory, the client which has access to the interface ITarget wants to call the method VendorAdaptee.GetListOfProduct() but since VendorAdaptee does not have an ITarget interface there was a need to create an adapter VendorAdapter. The VendorAdapter implements ITarget interface and calls the method of adaptee.
https://en.wikipedia.org/wiki/Abstract_factory_pattern
http://www.dofactory.com/net/facade-design-pattern
http://www.codeproject.com/Articles/812461/Event-Aggregator-Pattern