Code better 2 Паттерны программирования
Что такое паттерны?.. ― Устойчивый узнаваемый способ или подход к решению часто встречающихся проблем ООП. Позволяют легко идентифицировать проблему и ее решение буквально словом или словосочетанием. Определяют эффективное и зарекомендовавшее себя решение. Позволяют улучшить качество документации и сопровождения существующих систем.
Рассматриваемые паттерны Фабричный метод ( Factory Method) Одиночка ( Singleton) Итератор ( Iterator) Адаптер/обертка ( Adapter/Wrapper) Прототип ( Prototype) Компоновщик ( Composite )
Фабричный метод (назначение) Определяет интерфейс для создания объектов, при этом выбранный класс инстанциируется подклассами. Предоставляет подклассам операции-зацепки ( hooks ) Соединяет параллельные иерархии
Фабричный метод (схема)
Фабричный метод (пример кода) using System; using System.Collections; class FactoryPattern { interface IProduct { string ShipFrom(); } class ProductA : IProduct { public String ShipFrom() { return &quot; from South Africa&quot;; } } class ProductB : IProduct { public String ShipFrom() { return &quot;from Spain&quot;; } } class DefaultProduct : IProduct { public String ShipFrom() { return &quot;not available&quot;; } } class Creator { public IProduct FactoryMethod(int month) { if (month >= 4 && month <= 11) return new ProductA(); else if (month == 1 || month == 2 || month == 12) { return new ProductB(); } else { return new DefaultProduct(); } } } static void Main() { Creator c = new Creator(); IProduct product; for (int i = 1; i <= 12; i++) { product = c.FactoryMethod(i); Console.WriteLine(&quot;Avocados &quot; + product.ShipFrom()); } } }
Одиночка (назначение) Гарантирует, что у класса есть только один экземпляр, и предоставляет к нему глобальную точку доступа. Большая гибкость чем у статических членов класса. Допускает переменное число экземпляров. Допускает уточнение операций. Уменьшает число имен.
Одиночка (схема)
Одиночка (пример кода) public class Singleton { // Private constructor Singleton() { } // Nested class for lazy instantiation class SingletonCreator { static SingletonCreator() { } // Private object instantiated with private constructor internal static readonly Singleton uniqueInstance = new Singleton(); } // Public static property to get the object public static Singleton UniqueInstance { get { return SingletonCreator.uniqueInstance; } } }
Итератор (назначение) Предоставляет способ последовательного доступа ко всем элементам составного объекта, не раскрывая его внутреннего строения. Поддерживает различные виды обхода агрегата. Одновременно для агрегата может быть активно несколько обходов.
Итератор (схема)
Итератор (пример кода) using System; using System.Collections; class IteratorPattern { class MonthCollection : IEnumerable { string[] months = { &quot;January&quot;, &quot;February&quot;, &quot;March&quot;, &quot;April&quot;, &quot;May&quot;, &quot;June&quot;, &quot;July&quot;, &quot;August&quot;, &quot;September&quot;, &quot;October&quot;, &quot;November&quot;, &quot;December&quot;}; public IEnumerator GetEnumerator() { // Generates values from the collection foreach (string element in months) yield return element; } } static void Main() { MonthCollection collection = new MonthCollection(); // Consumes values generated from collection's GetEnumerator method foreach (string n in collection) Console.Write(n + &quot; &quot;); Console.WriteLine(&quot;\n&quot;); } }
Адаптер (назначение) Преобразует интерфейс одного класса в интерфейс другого, который ожидают клиенты.
Адаптер (схема)
Адаптер (пример кода) using System; // Existing way requests are implemented class Adaptee { // Provide full precision public double SpecificRequest(double a, double b) { return a / b; } } // Required standard for requests interface ITarget { // Rough estimate required string Request(int i); } // Implementing the required standard via Adaptee class Adapter : Adaptee, ITarget { public string Request(int i) { return &quot;Rough estimate is &quot; + (int) Math.Round(SpecificRequest(i, 3)); } } class Client { static void Main() { // Showing the Adapteee in standalone mode Adaptee first = new Adaptee(); Console.Write(&quot;Before the new standard\nPrecise reading: &quot;); Console.WriteLine(first.SpecificRequest(5, 3)); // What the client really wants ITarget second = new Adapter(); Console.WriteLine(&quot;\nMoving to the new standard&quot;); Console.WriteLine(second.Request(5)); } }
Прототип (назначение) Задает виды создаваемых объектов с помощью экземпляра-прототипа, и создает новые объекты путем копирования этого прототипа. Добавление и удаление продуктов во время выполнения. Спецификация новых объектов путем изменения значений или структуры. Динамическое конфигурирование приложения классами.
Прототип (схема)
Прототип (пример кода) using System; using System.Collections.Generic; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; [Serializable()] public abstract class IPrototype<T> { // Shallow copy public T Clone() { return (T) this.MemberwiseClone(); } // Deep Copy public T DeepCopy() { MemoryStream stream = new MemoryStream(); BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(stream, this); stream.Seek(0, SeekOrigin.Begin); T copy = (T) formatter.Deserialize(stream); stream.Close(); return copy; } }
Компоновщик (назначение ) Компонует объекты в древовидные структуры для представления иерархии часть-целое. Позволяет клиентам единообразно трактовать индивидуальные и составные объекты. Упрощает архитектуру клиента. Облегчает добавление новых видов компонентов. Способствует созданию общего дизайна.
Компоновщик (схема)
Компоновщик (пример кода) public class Component<T> : IComponent<T> { public T Name { get; set;} public Component(T name) { Name = name; } public void Add(IComponent<T> c) { Console.WriteLine(&quot;Cannot add to an item&quot;); } public IComponent<T> Remove(T s) { Console.WriteLine(&quot;Cannot remove directly&quot;); return this; } public IComponent<T> Find(T s) { return (s.Equals(Name)) ? this : null; } } public class Composite<T> : IComponent<T> { List<IComponent<T>> list; public T Name { get; set;} public Composite(T name) { Name = name; list = new List<IComponent<T>>(); } public void Add(IComponent<T> c) { list.Add(c); } IComponent<T> holder = null; public void Remove(T s) { ... (holder as Composite<T>).list.Remove(Find(s)); } public IComponent<T> Find(T s) { ... return found; } }
Литература Judith Bishop. C# 3.0 Design Patterns Гамма, Хелм, Джонсон и др. Приемы объектно-ориентированного программирования: паттерны программирования Buschmann, Henney, Schmidt. Pattern-Oriented Software Architecture. Christopher Lasater. Design Patterns.

паттерны программирования

  • 1.
    Code better 2Паттерны программирования
  • 2.
    Что такое паттерны?..― Устойчивый узнаваемый способ или подход к решению часто встречающихся проблем ООП. Позволяют легко идентифицировать проблему и ее решение буквально словом или словосочетанием. Определяют эффективное и зарекомендовавшее себя решение. Позволяют улучшить качество документации и сопровождения существующих систем.
  • 3.
    Рассматриваемые паттерны Фабричныйметод ( Factory Method) Одиночка ( Singleton) Итератор ( Iterator) Адаптер/обертка ( Adapter/Wrapper) Прототип ( Prototype) Компоновщик ( Composite )
  • 4.
    Фабричный метод (назначение)Определяет интерфейс для создания объектов, при этом выбранный класс инстанциируется подклассами. Предоставляет подклассам операции-зацепки ( hooks ) Соединяет параллельные иерархии
  • 5.
  • 6.
    Фабричный метод (примеркода) using System; using System.Collections; class FactoryPattern { interface IProduct { string ShipFrom(); } class ProductA : IProduct { public String ShipFrom() { return &quot; from South Africa&quot;; } } class ProductB : IProduct { public String ShipFrom() { return &quot;from Spain&quot;; } } class DefaultProduct : IProduct { public String ShipFrom() { return &quot;not available&quot;; } } class Creator { public IProduct FactoryMethod(int month) { if (month >= 4 && month <= 11) return new ProductA(); else if (month == 1 || month == 2 || month == 12) { return new ProductB(); } else { return new DefaultProduct(); } } } static void Main() { Creator c = new Creator(); IProduct product; for (int i = 1; i <= 12; i++) { product = c.FactoryMethod(i); Console.WriteLine(&quot;Avocados &quot; + product.ShipFrom()); } } }
  • 7.
    Одиночка (назначение) Гарантирует,что у класса есть только один экземпляр, и предоставляет к нему глобальную точку доступа. Большая гибкость чем у статических членов класса. Допускает переменное число экземпляров. Допускает уточнение операций. Уменьшает число имен.
  • 8.
  • 9.
    Одиночка (пример кода)public class Singleton { // Private constructor Singleton() { } // Nested class for lazy instantiation class SingletonCreator { static SingletonCreator() { } // Private object instantiated with private constructor internal static readonly Singleton uniqueInstance = new Singleton(); } // Public static property to get the object public static Singleton UniqueInstance { get { return SingletonCreator.uniqueInstance; } } }
  • 10.
    Итератор (назначение) Предоставляетспособ последовательного доступа ко всем элементам составного объекта, не раскрывая его внутреннего строения. Поддерживает различные виды обхода агрегата. Одновременно для агрегата может быть активно несколько обходов.
  • 11.
  • 12.
    Итератор (пример кода)using System; using System.Collections; class IteratorPattern { class MonthCollection : IEnumerable { string[] months = { &quot;January&quot;, &quot;February&quot;, &quot;March&quot;, &quot;April&quot;, &quot;May&quot;, &quot;June&quot;, &quot;July&quot;, &quot;August&quot;, &quot;September&quot;, &quot;October&quot;, &quot;November&quot;, &quot;December&quot;}; public IEnumerator GetEnumerator() { // Generates values from the collection foreach (string element in months) yield return element; } } static void Main() { MonthCollection collection = new MonthCollection(); // Consumes values generated from collection's GetEnumerator method foreach (string n in collection) Console.Write(n + &quot; &quot;); Console.WriteLine(&quot;\n&quot;); } }
  • 13.
    Адаптер (назначение) Преобразуетинтерфейс одного класса в интерфейс другого, который ожидают клиенты.
  • 14.
  • 15.
    Адаптер (пример кода)using System; // Existing way requests are implemented class Adaptee { // Provide full precision public double SpecificRequest(double a, double b) { return a / b; } } // Required standard for requests interface ITarget { // Rough estimate required string Request(int i); } // Implementing the required standard via Adaptee class Adapter : Adaptee, ITarget { public string Request(int i) { return &quot;Rough estimate is &quot; + (int) Math.Round(SpecificRequest(i, 3)); } } class Client { static void Main() { // Showing the Adapteee in standalone mode Adaptee first = new Adaptee(); Console.Write(&quot;Before the new standard\nPrecise reading: &quot;); Console.WriteLine(first.SpecificRequest(5, 3)); // What the client really wants ITarget second = new Adapter(); Console.WriteLine(&quot;\nMoving to the new standard&quot;); Console.WriteLine(second.Request(5)); } }
  • 16.
    Прототип (назначение) Задаетвиды создаваемых объектов с помощью экземпляра-прототипа, и создает новые объекты путем копирования этого прототипа. Добавление и удаление продуктов во время выполнения. Спецификация новых объектов путем изменения значений или структуры. Динамическое конфигурирование приложения классами.
  • 17.
  • 18.
    Прототип (пример кода)using System; using System.Collections.Generic; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; [Serializable()] public abstract class IPrototype<T> { // Shallow copy public T Clone() { return (T) this.MemberwiseClone(); } // Deep Copy public T DeepCopy() { MemoryStream stream = new MemoryStream(); BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(stream, this); stream.Seek(0, SeekOrigin.Begin); T copy = (T) formatter.Deserialize(stream); stream.Close(); return copy; } }
  • 19.
    Компоновщик (назначение )Компонует объекты в древовидные структуры для представления иерархии часть-целое. Позволяет клиентам единообразно трактовать индивидуальные и составные объекты. Упрощает архитектуру клиента. Облегчает добавление новых видов компонентов. Способствует созданию общего дизайна.
  • 20.
  • 21.
    Компоновщик (пример кода)public class Component<T> : IComponent<T> { public T Name { get; set;} public Component(T name) { Name = name; } public void Add(IComponent<T> c) { Console.WriteLine(&quot;Cannot add to an item&quot;); } public IComponent<T> Remove(T s) { Console.WriteLine(&quot;Cannot remove directly&quot;); return this; } public IComponent<T> Find(T s) { return (s.Equals(Name)) ? this : null; } } public class Composite<T> : IComponent<T> { List<IComponent<T>> list; public T Name { get; set;} public Composite(T name) { Name = name; list = new List<IComponent<T>>(); } public void Add(IComponent<T> c) { list.Add(c); } IComponent<T> holder = null; public void Remove(T s) { ... (holder as Composite<T>).list.Remove(Find(s)); } public IComponent<T> Find(T s) { ... return found; } }
  • 22.
    Литература Judith Bishop.C# 3.0 Design Patterns Гамма, Хелм, Джонсон и др. Приемы объектно-ориентированного программирования: паттерны программирования Buschmann, Henney, Schmidt. Pattern-Oriented Software Architecture. Christopher Lasater. Design Patterns.