diff --git a/Program.cs b/Program.cs index ac77235..35d44e7 100644 --- a/Program.cs +++ b/Program.cs @@ -12,6 +12,8 @@ using design_patterns.structural.bridge; using design_patterns.structural.composite; using design_patterns.structural.decorator; using design_patterns.structural.facade; +using design_patterns.structural.flyweight; +using design_patterns.structural.proxy; namespace design_patterns { @@ -35,7 +37,9 @@ namespace design_patterns // await BridgeSample.Run(); // await CompositeSample.Run(); // await DecoratorSample.Run(); - await FacadeSample.Run(); + // await FacadeSample.Run(); + // await FlyweightSample.Run(); + await ProxySample.Run(); } catch (System.Exception ex) { diff --git a/structural/flyweight/FlyweightSample.cs b/structural/flyweight/FlyweightSample.cs new file mode 100644 index 0000000..8c25fa4 --- /dev/null +++ b/structural/flyweight/FlyweightSample.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace design_patterns.structural.flyweight +{ + /// + /// Flyweight is a structural design pattern that lets you + /// fit more objects into the available amount of RAM + /// by sharing common parts of state between multiple objects + /// instead of keeping all of the data in each object. + /// + /// - to avoid redundancy of stored data + /// + public class FlyweightSample + { + private static readonly string[] availableNames = {"alfa", "beta", "gama"}; + + public static async Task Run() + { + Console.WriteLine("Structural - Flyweight"); + + Random rnd = new Random(); + List lst = new List(); + for (int i = 0; i < 100000; i++) + { + lst.Add(new Person(availableNames[rnd.Next(0,2)])); + } + System.Console.WriteLine($"lst has {lst.Count} persons."); + } + + public class Person { + + // data storage + private static List names = new List(); + + private int nameIndex = -1; + public Person(string name) { + Name = name; + } + + public string Name { + get { + return names[nameIndex]; + } + set { + // optimize names storage by place it into + // a centralized storage and reference data + // by an index + nameIndex = GetIndex(value); + } + } + + private static int GetIndex(string name) { + var idx = names.IndexOf(name); + if(idx==-1) { + names.Add(name); + idx = names.Count-1; + } + return idx; + } + } + } +} \ No newline at end of file diff --git a/structural/proxy/ProxySample.cs b/structural/proxy/ProxySample.cs new file mode 100644 index 0000000..7bba390 --- /dev/null +++ b/structural/proxy/ProxySample.cs @@ -0,0 +1,78 @@ +using System.Collections.Concurrent; +using System; +using System.Threading.Tasks; + +namespace design_patterns.structural.proxy +{ + /// + /// Proxy is a structural design pattern that lets you + /// provide a substitute or placeholder for another object. + /// A proxy controls access to the original object, + /// allowing you to perform something either before or after + /// the request gets through to the original object. + /// + /// - Create a new proxy class with the same interface + /// as an original service object. + /// - Then you update your app so that it passes the proxy object + /// to all of the original object’s clients. + /// - Upon receiving a request from a client, the proxy creates + /// a real service object and delegates all the work to it. + /// + /// Usages: + /// - Lazy initialization (virtual proxy). + /// - Access control (protection proxy). + /// - Local execution of a remote service (remote proxy). + /// - Logging requests (logging proxy). + /// - Caching request results (caching proxy). + /// - Smart reference. To dismiss a object/rsource once there are no clients using it. + /// + public class ProxySample + { + public static async Task Run() + { + Console.WriteLine("Structural - Proxy"); + + var proxy = new ProxyService(); + var data = Guid.NewGuid().ToString(); + proxy.ProcessData(data); + proxy.ProcessData(data); + } + + public interface IService { + public bool ProcessData(string input); + } + + public class RealService : IService + { + public bool ProcessData(string input) + { + System.Console.WriteLine($"Real service with input: {input}"); + return input.Length % 2 == 0; + } + } + + public class ProxyService : IService + { + // can do lazy loading + private Lazy realService = + new Lazy(() => new RealService()); + + private static ConcurrentDictionary cache = new ConcurrentDictionary(); + public bool ProcessData(string input) + { + // can log info + System.Console.WriteLine($"Proxy service started with input {input}"); + var service = realService.Value; + + // could cache the result for later user + if(!cache.TryGetValue(input, out bool result)){ + result = service.ProcessData(input); + cache[input] = result; + } + // can log info + System.Console.WriteLine($"Proxy service ended with result {result}"); + return result; + } + } + } +} \ No newline at end of file