diff --git a/Program.cs b/Program.cs index ad420cf..859a63d 100644 --- a/Program.cs +++ b/Program.cs @@ -10,6 +10,7 @@ using design_patterns.creational.prototype; using design_patterns.structural.adapter; using design_patterns.structural.bridge; using design_patterns.structural.composite; +using design_patterns.structural.decorator; namespace design_patterns { @@ -31,7 +32,8 @@ namespace design_patterns // structural // await AdapterSample.Run(); // await BridgeSample.Run(); - await CompositeSample.Run(); + // await CompositeSample.Run(); + await DecoratorSample.Run(); } catch (System.Exception ex) { diff --git a/structural/decorator/DecoratorSample.cs b/structural/decorator/DecoratorSample.cs new file mode 100644 index 0000000..212cbc2 --- /dev/null +++ b/structural/decorator/DecoratorSample.cs @@ -0,0 +1,133 @@ +using System; +using System.Text; +using System.Threading.Tasks; + +namespace design_patterns.structural.decorator +{ + /// + /// Decorator is a structural design pattern that lets you attach + /// new behaviors to objects by placing these objects inside + /// special wrapper objects that contain the behaviors. + /// + public class DecoratorSample + { + public static async Task Run() + { + Console.WriteLine("Structural - Decorator"); + + // example 1 + Console.WriteLine("example1 - extending with new features"); + Console.WriteLine("Service1"); + var s1 = new ServiceV1(); + s1.DoSomethingOnV1(); + + Console.WriteLine("Service2 - multiple inheritance"); + var s2 = new ServiceV2(); + s2.DoSomethingOnV1(); + s2.DoSomethingOnV2(); + + // example 2 + Console.WriteLine("example2"); + var sall = new AllExternalServices(); + sall.ServiceAddress = "ALL_Address"; + _ = sall.ProcessData1(); + _ = sall.ProcessData2(); + + //IExternalService2.DoExtra() + } + + + public class ServiceV1 + { + public void DoSomethingOnV1() { + System.Console.WriteLine($"Doing somethin on V1 from {this.GetType().Name}"); + } + } + + /// + /// this decorates ServiceV1 and adds new functionality + /// + public class ServiceV2 { + private ServiceV1 serviceV1 = new ServiceV1(); + public void DoSomethingOnV1() { + serviceV1.DoSomethingOnV1(); + } + + /// + /// extra functionality + /// + public void DoSomethingOnV2() { + System.Console.WriteLine($"Doing somethin on V2 from {this.GetType().Name}"); + } + } + + + + + // EXAMPLE 2 + public interface IExternalService1 { + public bool ProcessData1(); + public string ServiceAddress { get; set; } + } + public class ExternalService1 : IExternalService1 { + public string ServiceAddress { get; set; } + + public bool ProcessData1() { + Console.WriteLine($"ProcessData1 with address {ServiceAddress}"); + return true; + } + } + + public interface IExternalService2 { + + public static void DoExtra() { + // + } + + // default interface method + public bool ProcessData2() { + Console.WriteLine($"ProcessData2 with address {ServiceAddress}"); + return false; + } + public string ServiceAddress { get; set; } + } + public class ExternalService2 : IExternalService2 { + + public string ServiceAddress { get; set; } + + /// NOTE: this one also works + // public bool ProcessData2() { + // Console.WriteLine($"ProcessData2 changed with address {ServiceAddress}"); + // return true; + // } + } + + public class AllExternalServices : IExternalService1, IExternalService2 + { + private IExternalService1 s1 = new ExternalService1(); + private IExternalService2 s2 = new ExternalService2(); + private string serviceAddress; + + public string ServiceAddress { + get => serviceAddress; + set { + serviceAddress = value; + s1.ServiceAddress = serviceAddress; + s2.ServiceAddress = serviceAddress; + } + } + + public bool ProcessData1() + { + //forward call to s1 + return s1.ProcessData1(); + } + + public bool ProcessData2() + { + //forward call to s2 + return s2.ProcessData2(); + } + } + } +} \ No newline at end of file