Decorator Design Pattern – Object Oriented Design – C Sharp

Decorator design pattern in object oriented design enables a way of attaching new state and behavior to an object dynamically. The object does not know it is being “decorated,” which makes this a useful pattern for evolving systems. A key implementation point in the Decorator pattern is that decorators both inherit the original class and contain an instantiation of it.

decorator-design-pattern-uml-diagram

decorator-design-pattern-uml-diagram

 

Decorator Pattern

Interface IComponent

Class Component Implements IComponent

Class Decorator Implements IComponent

Class Client

Member Variables Member Variables Member Variables Member Variables
IComponent

Added State

IComponent component

IComponent decorator

Member Functions Member Functions Member Functions Member Functions
Operation Operation Operation

Added Behavior

 

Use it when
You have Existing component that cannot be subclassed.
You want
  1. Attach additional state without changing
  2. Change only few object’s behaviour without changing others
  3. Don’t want subclass as that will create lot many classes
Consider using
  1. Adapter to connect different interfaces
  2. Proxy which controls access to object
  3. Composite which aggregates components without inheriting interface
  4. Strategy pattern who changes object rather than wrapping it

Example of Decorator Design Pattern:

    class MainApp
    {
        static void Main()
        {
            // Create video
            var video = new MovieVideo("Spielberg", "Terminator 2", 23, 92);
            video.Display();

            // Make video borrowable, then borrow and display
            Console.WriteLine("\nMaking video borrowable:");

            var borrow = new Borrowable(video);
            borrow.BorrowItem("Customer #1");
            borrow.BorrowItem("Customer #2");

            borrow.Display();
            Console.ReadKey();
        }
    }
	abstract class LibraryItem
    {
		public static int NumCopies { get; set; }
		public abstract void Display();
    }
	class MovieVideo: LibraryItem
    {
        private string _director;
        private string _title;
        private int _playTime;

        // Constructor
        public MovieVideo(string director, string title,
            int numCopies, int playTime)
        {
            this._director = director;
            this._title = title;
            NumCopies = numCopies;
            this._playTime = playTime;
        }

        public override void Display()
        {
            Console.WriteLine("\nMovieVideo----- ");
            Console.WriteLine(" Director: {0}", _director);
            Console.WriteLine(" Title: {0}", _title);
            Console.WriteLine(" # Copies: {0}", NumCopies);
            Console.WriteLine(" Playtime: {0}\n", _playTime);
        }
    }
	abstract class Decorator : LibraryItem
    {
        private LibraryItem _libraryItem;
        // Constructor
        public Decorator(LibraryItem libraryItem)
        {
            _libraryItem = libraryItem;
        }
        public override void Display()
        {
            _libraryItem.Display();
        }
    }
	class Borrowable : Decorator
    {
        private List _borrowers = new List();
		public Borrowable(LibraryItem libraryItem)
            : base(libraryItem)
        {
        }
        public void BorrowItem(string name)
        {
            _borrowers.Add(name);
            NumCopies--;
        }
        public void ReturnItem(string name)
        {
            _borrowers.Remove(name);
            NumCopies++;
        }
        public override void Display()
        {
            base.Display();
            _borrowers.ForEach(b =>  Console.WriteLine(" borrower: " + b));
        }
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *