Software Development Tricky

Wednesday 13 December 2017

Decorator Pattern


  •  Decorator pattern attach additional functionalities or responsibility to an existing object at the runtime.
  •  It adds new behaviour to an individual object without affecting other objects of the same class.
  •  New behaviour or functionalities can be added dynamically at the run time
Example:

Consider you are developing student management application. First you’re creating
basic responsibility to handle and print information like name, age, gender & grade etc…

After a while you have got a new requirement to add functionality to maintain lab reports
for science students. Basically how will do this? May be extend the Student class to create
ScienceStudent subclass for this responsibility. It’s good enough for this requirement.

You have got another requirement to add functionality to maintaining game reports for
sports students. Again you may want to extend the Student class to create a
SportsStudent subclass for this responsibility.

You have got another requirement to maintain information of the student who is studying
science and also playing sports. You will have to maintain lab reports, game reports
along with name, age, gender and grade. You have already created two subclass's for
science students and sports students, but there is no way you can reuse them in this
scenario. You are left with no option but to create a subclass for ScienceSportsStudent and
this is a problem. How many subclasses you keep creating? Decorator pattern solves this
problem.

Sample Demo Diagram:


UML Diagram:



Drawbacks:

  • Decorators can cause issues if the client relies heavily on the components concrete type
  •  Decorators can complicate the process of instantiating the component because you not only have to instantiate the component but wrap it in a number of decorators
  •  It can be complicated to have decorators keep track of other decorators because to look back into multiple layers of the decorator chain starts to push the decorator pattern beyond it’s true intent

Sample Demo Program:

         The following participant are involved in given program

1.       Component – This is the base interface of actual or concrete object. In this object additional functionalities will be added dynamically. In implementation, it could be an abstract class or interface
2.       Concrete Component: This is the actual object in which additional functionality will be added. In implementation, it would implement or extend the component
3.       Decorator – This is the interface of all the dynamic functionalities that would be added to the component. It maintains reference of the component object and defines interface for new dynamic functionalities.
4.       Concrete Decorator – This will add dynamic functionalities to the component.


Entire Code Structure:

        1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
using System;
namespace DecoratorPattern
{
    /// <summary>
    /// Student Component
    /// </summary>
    public abstract class Student
    {
        public abstract string DisplayStudentInformation();
    }

    /// <summary>
    /// concrete component for student
    /// </summary>
    public class StudentConcrete : Student
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public string Gender { get; set; }
        public string Grade { get; set; }

        public override string DisplayStudentInformation()
        {
            string whois = ((Gender == "Male") ? "He" : "She");
            return Name + ". " + whois + " is " + Age + " years old. " + "Grade is " + Grade + ".";
        }
    }

    /// <summary>
    /// base student decorator for all dynamic functionalities
    /// </summary>
    public class StudentDecorator: Student
    {
        Student baseStudent = null;
        protected StudentDecorator(Student s)
        {
            baseStudent = s;
        }
        public override string DisplayStudentInformation()
        {
            string baseStudentInformation = baseStudent.DisplayStudentInformation();
            return baseStudentInformation;
        }
    }

    /// <summary>
    /// science student concrete decorator for dynamic functionality
    /// </summary>
    public class ScienceStudentDecorator : StudentDecorator
    {
        public string Labs { get; set; }
        public ScienceStudentDecorator(Student baseStudent) : base(baseStudent) { }

        public override string DisplayStudentInformation()
        {
            var result = base.DisplayStudentInformation();
            result = result + " Labs are " + Labs + ".";
            return result;
        }
    }

    /// <summary>
    /// sports student concrete decorator for dynamic functionality
    /// </summary>
    public class SportsStudentDecorator : StudentDecorator
    {
        public string Games { get; set; }
        public SportsStudentDecorator(Student baseStudent) : base(baseStudent) { }

        public override string DisplayStudentInformation()
        {
            var result = base.DisplayStudentInformation();
            result = result + " Games are " + Games + ".";
            return result;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            //normal student
            StudentConcrete stdKumar = new StudentConcrete { Name = "Kumar", Age = 10, Gender = "Male", Grade = "B" };
            var stdKumarInformation = stdKumar.DisplayStudentInformation();
            Console.WriteLine("---------------------Normal Student--------------------");
            Console.WriteLine(stdKumarInformation);

            //science student
            StudentConcrete stdKavitha = new StudentConcrete { Name = "Kavitha", Age = 10, Gender = "FeMale", Grade = "A" };
            ScienceStudentDecorator stdScienceKavitha = new ScienceStudentDecorator(stdKavitha) { Labs = "Computer Science, Biology" };
            var stdScienceKavithaInformation = stdScienceKavitha.DisplayStudentInformation();
            Console.WriteLine("\n---------------------Science Student--------------------");
            Console.WriteLine(stdScienceKavithaInformation);

            //games student
            StudentConcrete stdArun = new StudentConcrete { Name = "Arun", Age = 10, Gender = "Male", Grade = "C" };
            SportsStudentDecorator stdSportArun = new SportsStudentDecorator(stdArun) { Games = "Cricket, Football" };
            var stdSportsArunInformation = stdSportArun.DisplayStudentInformation();
            Console.WriteLine("\n---------------------Sport Student--------------------");
            Console.WriteLine(stdSportsArunInformation);

            //science & sports student
            StudentConcrete stdMani = new StudentConcrete { Name = "Mani", Age = 10, Gender = "Male", Grade = "A" };
            ScienceStudentDecorator stdScienceMani = new ScienceStudentDecorator(stdMani) { Labs = "Computer Science, Biology" };
            SportsStudentDecorator stdSportScienceMani = new SportsStudentDecorator(stdScienceMani) { Games = "Cricket, Football" };
            var stdSportScienceManiInformation = stdSportScienceMani.DisplayStudentInformation();
            Console.WriteLine("\n---------------------Science & Sport Student--------------------");
            Console.WriteLine(stdSportScienceManiInformation);

            Console.Write("\nPress any key to exist...");
            Console.ReadKey();
        }
    }
}

Final Output:


Click here to download sample program

If you like this post. Kindly share your valuable comments.

1 comment:

Followers