বুধবার, ২০ নভেম্বর, ২০১৩

Upcoming Posts

Dear readers
Successfully completed some patterns that defined in Martin Fowler's Patterns of Enterprise Architecture (PEA). Next we will discuss about
  1. Command and Query Responsibility Segregation (CQRS) Pattern  
  2. Event Sourcing(ES) pattern
  3. Messaging Pattern

Wish all of yours cooperation and suggestion.

Thanks for reading
Mojammel Haque

Identity Map



  • Ensure Kiv nq †h cÖwZwU object GKeviB gvÎ loaded n‡q‡Q|
  • GRb¨ cÖwZwU loaded object ‡K GKwU map Gi g‡a¨ ivLv nq|
  • hLb †Kvb object ‡K  refer Kiv nq ZLb Dnv‡K GB map Gi g‡a¨ †LuvRv nq  |
  •  hw` map Gi g‡a¨ cvIqv hvq Z‡e †mLvb †_‡K return Ki‡e bZzev database ‡_‡K object data load Ki‡e| AZtci D³ loaded data map G store Ki‡e| Then map ‡_‡K return Ki‡e|
  • Identity map use K‡i wb‡¤œv³ benefit mg~n cvIqv hvq-
    •  Resource consumption reduce K‡i| 
    •  Database Gi same object data Gi duplicate retrieval prevent Kivi Rb¨ Bnv context-specific, in-memory cache provide K‡i| d‡j performance improve nq| 

Example:
public abstract class Entity
{
        private readonly int _id;
       
        public int Id
        {
               get { return _id; }
        }
       
        internal Entity(int id)
        {
               _id = id;
        }
}
       
public sealed class Widget : Entity
{
        private static readonly EntityMap<Widget> _map = new EntityMap<Widget>(id => new Widget(id));
       
        public static EntityMap<Widget> Map
        {
               get { return _map; }
        }
       
        private Widget(int id) : base(id) { }
}
       
public sealed class Gadget : Entity
{
        private static readonly EntityMap<Gadget> _map = new EntityMap<Gadget>(id => new Gadget(id));
       
        public static EntityMap<Gadget> Map
        {
               get { return _map; }
        }
       
        private Gadget(int id) : base(id) { }
}
       
public class EntityMap<T> where T : Entity
{
        private readonly Dictionary<int, T> _entities = new Dictionary<int, T>();
        private readonly object _getLock = new object();
        private readonly Func<int, T> _entityGenerator;
       
        public T Get(int id)
        {
               lock (_getLock)
               {
                       T entity;
       
                       if (!_entities.TryGetValue(id, out entity))
                               _entities[id] = entity = _entityGenerator(id);
       
                       return entity;
               }
        }
       
        internal EntityMap(Func<int, T> entityGenerator)
        {
               _entityGenerator = entityGenerator;
        }
}
  • Client code G wb‡b¥v³fv‡e call Kiv n‡e-
// The following line results in a compilation error
// because Widget has no public constructors.
Widget badWidget = new Widget(1);
        
// Same for this one.
EntityMap<Widget> badWidgets = new EntityMap<Widget>();
        
// A Widget is properly retrieved like so...
Widget widget = Widget.Map.Get(1);



Memento Pattern



·         KL‡bv KL‡bv GKwU object Gi wewfbœ c‡q‡›Ui internal state capture Kivi cÖ‡qvRb c‡o Ges cieZ©x‡Z D³ state restore Ki‡Z nq|
·         Error wKsev failure Gi †ÿ‡Î Bnv LyeB Kvh©Kix|

Intent

  • Memento pattern Gi g~j intent  n‡”Q Bnv encapsulation violate bv K‡i GKwU object Gi internal state capture K‡i Ges cÖ‡qvRbvbyhvqx D³ state restore K‡i|

Non Software Example:

  • Microsoft Ward e¨envi K‡i document prepare Kiv nq|
  • GB document preparation Gi mgq Microsoft Ward GKwU specific session Gi  user KZ…©K type K…Z ward I sentences সমূহ internally capture K‡i iv‡L|
  • D³ session G user Zvi cÖ‡qvRbvbyhvqx Zvi typed document undo/Redo Ki‡Z cv‡i|

UML Diagram:




Memento:
  • Originator Object Gi internal state store K‡i|
Originator
  • Memento create K‡i  hvnv Originator  Gi current internal state Gi GKwU snapshot contain K‡i|
  • cÖ‡qvRbvbyhvqx Memento ‡_‡K wb‡Ri c~e©eZ©x  internal state restore K‡i|
Caretaker:

  • Memento object mg~n store K‡i| G‡ÿ‡Î actual objects details m¤ú‡K© Rvbvi cÖ‡qvRb c‡o bv|
 
Code Example:
  • cÖ_‡g IOriginator bv‡g GKwU Interface create Kwi Ges Dnv‡K ICloneable interface Øviv inherit Kwi|
public interface IOriginator:ICloneable
{
   
}
  • AZtci Av‡iKwU Interface create Kwi Dnvi bvg IMemento. Bnv GKwU generic interface. Gi definition wb¤œiƒc-
public interface IMemento<T> where T:IOriginator
{
}
  • Then IOriginator Interface modify Kwi wb¤œiƒ‡c-
public interface IOriginator:ICloneable
    {
        IMemento<IOriginator> CreateMemento();
        void RestoreMemento(IMemento<IOriginator> memento);
    }
  • Then ICaretaker Interface create Kwi
public interface ICaretaker
{
        void AddMemento<TOriginator>(TOriginator originator)
            where TOriginator : IOriginator;

        TOriginator GetMemento<TOriginator>(MementoType type)
            where TOriginator : IOriginator;
}


  • Then Memento class define Kwi| G‡ÿ‡Î Memento class IMemento interface ‡K implement Ki‡e (Bnv GKwU generic class)-
public class Memento<T>:IMemento<T> where T:IOriginator
   {
        public T State { get; private set; }

        public Memento(T originator)
        {
            State = (T)originator.Clone();
        }
   }
  •  GLb Avgiv IOriginator interface ‡K implement K‡i Originator class create Ki‡ev wb¤œiƒ‡c-
    public abstract class Originator:IOriginator
    {
        public abstract object Clone();

        public abstract void RestoreMemento(IMemento<IOriginator> memento);

        public IMemento<IOriginator> CreateMemento()
        {
            return new Memento<IOriginator>(this);
        }
    }
  • GLb Avgiv MementoType bv‡g GKwU enum create Ki‡ev wb¤œiƒ‡c-
public enum MementoType
{
   Undo,
   Redo
}
  • GB ch©v‡q Avgiv ICaretaker interface implement K‡i Caretaker class create Ki‡ev wb¤œiƒ‡c
public class Caretaker:ICaretaker
{
        public IDictionary<Type, Stack<IOriginator>> _redoItems = new Dictionary<Type, Stack<IOriginator>>();
        public IDictionary<Type, Stack<IOriginator>> _undoItems = new Dictionary<Type, Stack<IOriginator>>();

        public void AddMemento<TOriginator>(TOriginator originator)
            where TOriginator : IOriginator
        {
            Stack<IOriginator> currentStack = GetStack<TOriginator>(MementoType.Undo);
            GetStack<TOriginator>(MementoType.Redo).Clear();
            currentStack.Push(originator);
        }

        public TOriginator GetMemento<TOriginator>(MementoType type)
            where TOriginator : IOriginator
        {
            Stack<IOriginator> currentStack = GetStack<TOriginator>(type);

            if (currentStack.Count == 0)
            {
                throw new KeyNotFoundException(
                    string.Format("The memento was not found in the dictionary, {0}", typeof(TOriginator).FullName));
            }

            IOriginator current = currentStack.Pop();
            GetOppositeStack<TOriginator>(type).Push(current);

            return (TOriginator)current;
        }

        private Stack<IOriginator> GetStack<TOriginator>(MementoType type)
            where TOriginator : IOriginator
        {
            IDictionary<Type, Stack<IOriginator>> currentMapping = GetMapping(type);

            return GetStack(currentMapping, typeof(TOriginator));
        }

        private IDictionary<Type, Stack<IOriginator>> GetMapping(MementoType type)
        {
            IDictionary<Type, Stack<IOriginator>> currentMapping = null;
            switch (type)
            {
                case MementoType.Undo:
                    currentMapping = _undoItems;
                    break;
                case MementoType.Redo:
                    currentMapping = _redoItems;
                    break;
            }

            return currentMapping;
        }

        private Stack<IOriginator> GetOppositeStack<TOriginator>(MementoType type)
            where TOriginator : IOriginator
        {
            return GetStack(GetMapping(GetOppositeType(type)), typeof(TOriginator));
        }

        private MementoType GetOppositeType(MementoType type)
        {
            MementoType oppositeType;
            switch (type)
            {
                case MementoType.Undo:
                    oppositeType = MementoType.Redo;
                    break;
                case MementoType.Redo:
                    oppositeType = MementoType.Undo;
                    break;
                default:
                    throw new NotImplementedException();
            }

            return oppositeType;
        }

        private Stack<IOriginator> GetStack(IDictionary<Type, Stack<IOriginator>> mapping, Type mementoType)
        {
            Stack<IOriginator> currentStack = null;
            if (mapping.ContainsKey(mementoType))
            {
                currentStack = mapping[mementoType];
            }
            else
            {
                currentStack = new Stack<IOriginator>();
                mapping.Add(mementoType, currentStack);
            }

            return currentStack;
        }
}