Take advantage of the Decorator design pattern to add extensibility either dynamically or statically to your application Design patterns are solutions to recurring problems and complexities in software design and are classified into three distinct categories: creational, structural, and behavioral. The Decorator design pattern is a structural pattern and can be used to add functionality to an object dynamically sans the need of modifying the structure of the object. In essence, you can leverage the Decorator pattern to attach functionality or behavior to an object dynamically or statically sans the need to altering the object’s structure. Note that the Decorator design pattern follows the Open Closed Principle, one of the SOLID principles. Incidentally, the Open Closed Principle is used to design classes that are open for extensions but closed for modifications. Conformance to the Open Closed Principle facilitates building applications that are reusable and can be maintained easily. The Gang of Four (GOF) at Dofactory states: “Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.” A bit of code In this section we will explore how we can implement the Decorator design pattern in C#. The participants in a typical implementation of the Decorator design pattern include: Component — this represents the base type of the actual or the concrete type Concrete Component — this represents the concrete type that extends the base component. Note that the additional responsibilities or functionalities are added in this type. Decorator — this represents a reference to a component. The dynamic functionalities are added in this type. Now, let’s consider the following class. public abstract class Employee { public abstract string Display(); } Note that when using the Decorator design pattern, you extend the behavior of an existing class but it doesn’t necessarily mean that you have to use abstract types — the types may or may not be abstract. You can also implement the Decorator design pattern using interfaces, or even by using methods that are virtual in your concrete classes. In essence, you are not constrained to use only abstract classes when implementing the Decorator design pattern. We are using an abstract class here just for the sake of simplicity. The EmployeeConcrete class extends the Employee class and adds additional properties to it. Here’s how this class would look like. public class EmployeeConcrete : Employee { public string FirstName { set; get; } public string LastName { set; get; } public string Address { set; get; } public override string Display() { StringBuilder data = new StringBuilder(); data.Append("First name: " + FirstName); data.Append("nLast name: " + LastName); data.Append("nAddress: " + Address); return data.ToString(); } } The EmployeeDecorator class extends the Employee class, accepts an instance of the component class named Employee, and overrides the Display() method. Here’s how this class would look like. public class EmployeeDecorator : Employee { Employee employee = null; protected EmployeeDecorator(Employee employee) { this.employee = employee; } public override string Display() { return employee.Display(); } } Now that the component, concrete component and the decorator class is ready, you can now extend the EmployeeDecorator class to create a concrete decorator class. The following code listing shows how this class would look like. public class PermanentEmployeeDecorator : EmployeeDecorator { //Add properties relevant to a permanent employee private double PF { get; set; } public PermanentEmployeeDecorator(Employee employee) : base(employee) { } public override string Display() { return base.Display() + "nEmployee type: Permanent"; } } And, that’s all you need to do! You can now create an instance of PermanentEmployeeDecorator and use it as shown in the code snippet below. static void Main(string[] args) { EmployeeConcrete employeeConcrete = new EmployeeConcrete { FirstName = "Joydip", LastName = "Kanjilal", Address = "Hyderabad, India" }; PermanentEmployeeDecorator employeeDecorator = new PermanentEmployeeDecorator(employeeConcrete); Console.WriteLine(employeeDecorator.Display()); Console.Read(); } You can also have another type of employee — a contractual employee. To represent it, you would need to create another class named ContractEmployeeDecorator that extends the EmployeeDecorator class. Refer to the code snippet given below. public class ContractEmployeeDecorator : EmployeeDecorator { //Add properties relevant to a contract employee private double RatePerHour { get; set; } public ContractEmployeeDecorator(Employee employee) : base(employee) { } public override string Display() { return base.Display() + "nEmployee type: Contractual"; } } The following code snippet illustrates how you can use the ContractEmployeeDecorator class. static void Main(string[] args) { EmployeeConcrete employeeConcrete = new EmployeeConcrete { FirstName = "Joydip", LastName = "Kanjilal", Address = "Hyderabad, India" }; ContractEmployeeDecorator employeeDecorator = new ContractEmployeeDecorator(employeeConcrete); Console.WriteLine(employeeDecorator.Display()); Console.Read(); } Related content feature 14 great preprocessors for developers who love to code Sometimes it seems like the rules of programming are designed to make coding a chore. Here are 14 ways preprocessors can help make software development fun again. By Peter Wayner Nov 18, 2024 10 mins Development Tools Software Development feature Designing the APIs that accidentally power businesses Well-designed APIs, even those often-neglected internal APIs, make developers more productive and businesses more agile. By Jean Yang Nov 18, 2024 6 mins APIs Software Development news Spin 3.0 supports polyglot development using Wasm components Fermyon’s open source framework for building server-side WebAssembly apps allows developers to compose apps from components created with different languages. By Paul Krill Nov 18, 2024 2 mins Microservices Serverless Computing Development Libraries and Frameworks news Go language evolving for future hardware, AI workloads The Go team is working to adapt Go to large multicore systems, the latest hardware instructions, and the needs of developers of large-scale AI systems. By Paul Krill Nov 15, 2024 3 mins Google Go Generative AI Programming Languages Resources Videos