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 What is Rust? Safe, fast, and easy software development Unlike most programming languages, Rust doesn't make you choose between speed, safety, and ease of use. Find out how Rust delivers better code with fewer compromises, and a few downsides to consider before learning Rust. By Serdar Yegulalp Nov 20, 2024 11 mins Rust Programming Languages Software Development how-to Kotlin for Java developers: Classes and coroutines Kotlin was designed to bring more flexibility and flow to programming in the JVM. Here's an in-depth look at how Kotlin makes working with classes and objects easier and introduces coroutines to modernize concurrency. By Matthew Tyson Nov 20, 2024 9 mins Java Kotlin Programming Languages analysis Azure AI Foundry tools for changes in AI applications Microsoft’s launch of Azure AI Foundry at Ignite 2024 signals a welcome shift from chatbots to agents and to using AI for business process automation. By Simon Bisson Nov 20, 2024 7 mins Microsoft Azure Generative AI Development Tools news Microsoft unveils imaging APIs for Windows Copilot Runtime Generative AI-backed APIs will allow developers to build image super resolution, image segmentation, object erase, and OCR capabilities into Windows applications. By Paul Krill Nov 19, 2024 2 mins Generative AI APIs Development Libraries and Frameworks Resources Videos