Showing posts with label Gang Of Four. Show all posts
Showing posts with label Gang Of Four. Show all posts

Saturday, August 16, 2014

Building Blocks - Gang of Four Decorator Pattern Simple Sample


A Decorator class is a class that extends the functionality of another class at run-time without inheriting it :  is one of the 23 software patterns researched by the Gang of Four in their 1995 classic book. The Decorator Pattern become really useful in an MVC application, when you want to add functionality to many classes , respecting the Open-Closed Software Principle, therefore without touching any existing code.
The Open-Closed Principle, stated by Meyer in 1988, specifies that any class once completed, could only be modified in order to fix errors, but any new or appended functionality would require an extension new class to be created.This pattern allows you to create absolutely loosely-coupled relationships between classes, since it works without the standard inheritance mechanism known as "sub-classing" : instead of extending functionality at compile time through a sub-class, the Decorator wraps another objects at a runtime dynamic basis.
This pattern is materialized using interfaces or abstract classes. In this example, we'll use an abstract class, because it will be preferable in real world applications (see this article comparing interfaces vs abstract classes).

The following lines contain the code for the Decorator. Just use it as a bootstrap in your Model's classes :

Suppose you have this given parent-child classes to be extended with a Decorator:

abstract class Parent
{
   public abstract void DoIt();
}


class Child : Parent
{
  public override void DoIt()
  {
    Console.WriteLine("You are at 
Child .DoIt()");
  }
}


And when called, the output will be :

Child child = new Child();
child.DoIt();

You are at Child .DoIt()

Step #1 : Create an abstract Decorator class:


abstract class DecoratorBase : Parent
{
  protected Parent component;

  public void Setup(Parent component)
  {
    this.component = component;
  }
  public override void DoIt()
  {
    if (component != null)
    {
      component.DoIt();
    }
  }
}

The abstract base decorator wraps the old class as a component, and overrides the methods to extend , simultaneously respecting the old functionality.

Step #2 : Create as many Decorators as you wish : 


class Decorator1 : 
DecoratorBase 
{
  public override void DoIt()
  {
    base.DoIt();
    ExtendedFunctionality();
    Console.WriteLine("You are at 
Decorator1 .DoIt()");
  }

  void 
ExtendedFunctionality()
  {
    // TODO
  }
}

The functional decorator does two things:
1) calls the method's base of the old class (through the abstract decorator)
2) adds new behavior to the old functionality 
Thus , the old class is now a component of the decorator. 

Call & output:

Child child = new Child();
Decorator1 dec1 = new 
Decorator1 ();

dec1.Setup(child);
dec1.DoIt();

You are at Child.DoIt()
You are at Decorator1 .DoIt()

Yet another Decorator :

class Decorator2 : DecoratorBase 
{
  public override void DoIt()
  {
    base.DoIt();
    ExtendedFunctionality();
    Console.WriteLine("You are at 
Decorator2 .DoIt()");
  }

  void 
ExtendedFunctionality()
  {
    // TODO
  }
}

Call and output:

Child child = new Child();
Decorator1 dec1 = new 
Decorator1 ();Decorator2 dec2 = new Decorator2 ();
dec1.Setup(child);

dec2.Setup(dec1);
dec2.DoIt();





You are at Child.DoIt()
You are at Decorator1.DoIt()

You are at Decorator2 .DoIt()



That means, with this design pattern we can not just decorate twice an old class, but also decorate another decorator, which now becomes a component of a newer decorator class.

Important:
We practically didn't touch the old code : the old class is now a component of the new decorator/s.
All we did was adding an abstract parent to the extended class, thus respecting the Open-Close Principle.

That's all!!  
Happy programming.....
        By Carmel Schvartzman
כתב: כרמל שוורצמן

Wednesday, August 13, 2014

Singleton Data Repository - Gang of Four Singleton Pattern Simple Sample


In this article we create a singleton Data Repository for MVC. A Singleton class is a class of which only a single instance can exist: is one of the 23 software patterns by the Gang of Four. The Singleton Pattern become really useful in an MVC application, because instead of re-creating the Repository 1) each time a request comes to the MVC app, and 2) also for every different user which browser to the site, it is created ONLY ONE time and kept for the whole lifetime of the MVC application, that means, until the IIS application pool is reset.
First i give you the whole c# code to create a Singleton Data Repository for Asp.Net MVC. It will be  connected to a single XML file , and will be exposing all CRUD operations, using the XDocument class. The basic class will be "Message", and the Repository , "IMessagesRepository". The initial XML file is placed at the end of this post, if you want to use it as bootstrap.
After giving you the Repository code for COPY-PASTE, we'll explain how it works, and we'll compare its behavior with a non-singleton MVC application.

  The whole application can show as follows (i'm using the Twitter Bootstrap: HERE you have a tutorial for installing it in 5 minutes):




This is the code for the Singleton Data Repository. Just COPY-PASTE it in your Models folder and use it inside the Controller: 


namespace RichFormApplication.Models
{

    public class Message
    {
        public int ID { get; set; }
        public string To { get; set; }
        public string Sender { get; set; }
        public string Title { get; set; }
        public string Contents { get; set; }
    }


    public interface IMessagesRepository
    {
        IEnumerable GetAll();
        Message Get(int id);
        Message Add(Message item);
        bool Update(Message item);
        bool Delete(int id);
    }


    public class MessagesRepository : IMessagesRepository
    {
        static private int test;
        private List<Message> Messages = new List<Message>();
        private int iNumberOfMsgs = 1;
        private XDocument doc;

        #region Singleton Init
        private static MessagesRepository _RepositoryInstance = new MessagesRepository();
        public static MessagesRepository RepositoryInstance
        {
            get
            {
                test = 1;
                return _RepositoryInstance;
            }
        }
        #endregion

        private MessagesRepository()
        {
            doc = XDocument.Load(HttpContext.Current.Server.MapPath("~/App_Data/data.xml"));
            foreach (var node in doc.Descendants("note"))
            {
                Messages.Add(new Message
                {
                    ID = Int32.Parse(node.Descendants("id").FirstOrDefault().Value),
                    To = node.Descendants("to").FirstOrDefault().Value,
                    Sender = node.Descendants("from").FirstOrDefault().Value,
                    Title = node.Descendants("heading").FirstOrDefault().Value,
                    Contents = node.Descendants("body").FirstOrDefault().Value
                });
            }

            iNumberOfMsgs = Messages.Count;
        }

        public IEnumerable GetAll()
        {
            return Messages;
        }
        public Message Get(int id)
        {
            return Messages.Find(p => p.ID == id);
        }
        public Message Add(Message item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }

            item.ID = iNumberOfMsgs++;

            XElement newNode = new XElement("note");
            XElement id = new XElement("id"); id.Value = item.ID.ToString();
            XElement to = new XElement("to"); to.Value = item.To;
            XElement from = new XElement("from"); from.Value = item.Sender;
            XElement Title = new XElement("heading"); Title.Value = item.Title;
            XElement Contents = new XElement("body"); Contents.Value = item.Contents;
            newNode.Add(id, to, from, Title, Contents);
            doc.Root.Add(newNode);
            SaveToXML();
            return item;
        }
        public bool Update(Message item)
        {            
            XElement Message = doc.Descendants("Message").Where(n => Int32.Parse(n.Descendants("id").FirstOrDefault().Value) == item.ID).FirstOrDefault();
            Message.Descendants("to").FirstOrDefault().Value = item.To;
            Message.Descendants("from").FirstOrDefault().Value = item.Sender;
            Message.Descendants("heading").FirstOrDefault().Value = item.Title;
            Message.Descendants("body").FirstOrDefault().Value = item.Contents;
            SaveToXML();
            return true;
        }
        public bool Delete(int id)
        {
            doc.Root.Descendants("note").Where(n => Int32.Parse(n.Descendants("id").First().Value) == id).Remove();
            SaveToXML();
            return true;
        }

        private void SaveToXML()
        {
            doc.Save(HttpContext.Current.Server.MapPath("~/App_Data/data.xml"));
        }
    }
}

Take a look at the red code : the steps for creating the Singleton are:
1) change the "public" for a "private" constructor;
2) declare a "public static" property which returns an INSTANCE of the class
3) that static instance will be created by the .Net CLR runtime , at the private static field containing the
         instance, at the precise instant in which someone calls at least one of the properties or methods
         of the class. The static instance of the class will survive for all lifetime of the MVC application.

To use the Repository just type the following code in the Controller:

        public ActionResult Index()
        {
            return View(MessagesRepository.RepositoryInstance.GetAll());
        }

Now let's test the singleton: browse to the website and put in debugger two breakpoints inside the Repository:


There is no initialization of the Repository , as it is static and its constructor is private.
You'll see that the first time some user browse to the site, the repository is initialized:





Try a second time, refreshing the web page: the repository will not be created again, because it already exists:



Try now as a new user, opening a second session in another browser tab, to see that you keep using the same repository as the first user does.

This is the XML initial file:



<?xml version="1.0" encoding="utf-8"?>
<notes>
  <note>
    <id>0</id>
    <to>Fry</to>
    <from>Leela</from>
    <heading>Reminder</heading>
    <body>Don't forget me this weekend!!!</body>
  </note>
  <note>
    <id>1</id>
    <to>Leela</to>
    <from>Fry</from>
    <heading>Finally!!!</heading>
    <body>Leela, have you asked permission from the Professor?</body>
  </note>
  <note>
    <id>2</id>
    <to>Fry</to>
    <from>Leela</from>
    <heading>Rejection</heading>
    <body>You know what? In second thoughts, i'm going out with Lars this weekend. Sorry...</body>
  </note>

</notes>

That's all concerning to the Singleton Repository.

If you are asking yourself about the XML related code, some relevant points about the XML include:
 We are using the Descendants("") method and the Load() method, for reading the XML file into memory and then inside the List<>.
The Get methods use Find(p => p):


To add a new node, we CREATE an XElement with all its XElement CHILDREN , and then add it to the ROOT (be careful adding them to the root) of the XDocument:




That's all!!  
Happy programming.....
        By Carmel Schvartzman
כתב: כרמל שוורצמן