// Decorator design pattern. // A beefed-up object adapter using System; interface Component // Original Interface { void f(); } class ConcreteComponent : Component // Original Object { public void f() { Console.WriteLine("I can only do f"); } } abstract class Decorator : Component { protected Component C; // component object to be adopted public void f() { C.f(); } // like an object adapter } class ConcreteDecorator : Decorator { public ConcreteDecorator(Component cc) { C = cc; } // add additional functionality public void g() { Console.WriteLine("now I can do g too!"); } } public class decorator { public static void Main() { Component c = new ConcreteComponent(); ConcreteDecorator cd = new ConcreteDecorator(c); cd.f(); cd.g(); } } /// How is this better than just extending the original class? /// Supposedly decorators are applied on a per-object basis, whereas /// subclassing is static, compile-time modification. The decorator /// does not change the object c itself, so it can be adopated in various ways. /// Do I buy this argument? Not really, because inheritance itself can be /// emulated using something similar to the decorator. You still have /// to define a ConcreteDecorator class, except it extends Decorator instead /// of ConcreteComponent. // What are the drawbacks of this approach? // Doesn't work for recursive data structures like exp tree, or any other tree. // for existing substructures need to be decorated. // What if something needs to change, but in multiple ways? a subclass can // only override a function in one way. // Does not address "Crosscutting concerns" that are relevant to many // classes, and methods. // Introduce AOP Concepts, AOP approach to modular programming. // Separation of Concerns // Crosscutting Concerns // Join Points // Weaving // Advice and Pointcuts // Intertype declarations.