Thursday, August 6, 2015

Шаблоны Проектирования


Основные
Делегирования •
 Функционального дизайна •
 Неизменяемый объект • 
Интерфейс
Порождающие
Абстрактная фабрика • 
Строитель • 
Фабричный метод • 
Прототип • 
Одиночка • 
Отложенная инициализация • 
Объектный пул
Структурные
Адаптер • 
Мост • 
Компоновщик • 
Декоратор • 
Фасад • 
Заместитель • 
Приспособленец • 
Выделение частного класса данных
Поведения
Цепочка обязанностей • 
Команда • 
Интерпретатор • 
Итератор • 
Посредник • 
Хранитель • 
Наблюдатель • 
Состояние • 
Стратегия • 
Шаблонный метод • 
Посетитель
Параллельного
программирования
Блокировка с двойной проверкой • 
Планировщик • 
Однопоточное выполнение




ОСНОВНЫЕ


Шаблон делегирования

В разработке ПО, шаблон делегирования (англ. delegation pattern) — это способ, которым объект внешне выражает некоторое поведение, но в реальности передаёт ответственность за выполнение этого поведения связанному объекту. Шаблон делегирования является фундаментальной абстракцией, которая поддерживает композицию (также называемую агрегацией),примеси (mixins) и аспекты (aspects).

namespace Patterns{
interface I
{
   void f();
   void g();
}

class A 
 : I
{
   public void f()
   {
       System.Console.WriteLine("A: вызываем метод f()");
   }
   public void g()
   {
       System.Console.WriteLine("A: вызываем метод g()");
   }
}

class B 
 : I
{
   public void f()
   {
       System.Console.WriteLine("B: вызываем метод f()");
   }
   public void g()
   {
       System.Console.WriteLine("B: вызываем метод g()");
   }
}

class C 
 : I
{
   // Создаём объект, методы которого будем делегировать
   I i = new A();

   public void f()
   {
       i.f();
   }
   public void g()
   {
       i.g();
   }

   // Этими методами меняем поле-объект, чьи методы будем делегировать
   public void toA()
   {
       i = new A();
   }
   public void toB()
   {
       i = new B();
   }
}

class DelegatePattern
{
   static void Main( string[] args )
   {
       C c = new C();
       c.f();
       c.g();
       c.toB();
       c.f();
       c.g();
       System.Console.ReadKey();
   }
}
}

Шаблон функционального дизайна

Шаблон функционального дизайна (англ. Functional design) — это шаблон проектирования использующийся для упрощения проектирования ПО. Функциональный дизайн гарантирует, что каждый модуль компьютерной программы имеет только одну обязанность и исполняет её с минимумом побочных эффектов на другие части программы. Функционально разработанные модули имеют очень маленькое сцепление.

Системы с функционально-спроектированными частями легче модифицировать, потому что каждая часть делает только то, для чего она предназначена. Так как поддержка программы занимает больше 3/4 жизни успешной системы, эта особенность является решающим преимуществом. Это также делает систему лёгкой для понимания и документирования, что также упрощает обучение. Результатом является то, что практическое время жизни функциональной системы больше. Преимуществом для реализации является то, что если программный модуль имеет единственное предназначение, он будет проще и тем самым — легче и менее дорогостоящим для проектирования и реализации. В программных системах, функциональный модуль будет легче использовать многократно потому что он менее вероятно будет иметь побочные эффекты, которые проявятся в других частях системы.

Неизменяемый объект

Неизменяемый объект (англ. Immutable object) — в объектно-ориентированном программировании объект, который не может быть изменён после своего создания.

Объект может быть неизменяемым как полностью, так и частично. Например, применение директивы const к какому-либо члену класса в C++ делает объект частично неизменяемым. В некоторых случаях объект считается неизменяемым с точки зрения пользователя класса, даже если изменяются его внутренние поля. Как правило, неизменяемый объект получает все внутренние значения во время инициализации, либо значения устанавливаются в несколько этапов, но до того, как объект будет использован.

Интерфейс

В информатике, шаблон интерфейса не является особым шаблоном среди шаблонов проектирования. Он является общим методом для структурирования компьютерных программ для того, чтобы их было проще понять. В общем, интерфейс — это класс, который обеспечивает программисту простой или более программно-специфический способ доступа к другим классам. Интерфейс может содержать набор объектов и обеспечивать простую, высокоуровневую функциональность для программиста (например, Шаблон Фасад); он может обеспечивать более чистый или более специфический способ использования сложных классов («класс-обёртка»); он может использоваться в качестве «клея» между двумя различными API (Шаблон Адаптер); и для многих других целей. Другими типами интерфейсных шаблонов являются: Шаблон делегирования, Шаблон компоновщик, и Шаблон мост.

interface IInterface
{
 object Param1 { get; set; }
}

Порождающие

Абстрактная фабрика

Абстрактная фабрика (англ. Abstract factory) — порождающий шаблон проектирования, позволяющий изменять поведение системы, варьируя создаваемые объекты, при этом сохраняя интерфейсы. Он позволяет создавать целые группы взаимосвязанных объектов, которые, будучи созданными одной фабрикой, реализуют общее поведение. Шаблон реализуется созданием абстрактного класса Factory, который представляет собой интерфейс для создания компонентов системы (например, для оконного интерфейса он может создавать окна и кнопки). Затем пишутся наследующиеся от него классы, реализующие этот интерфейс.


using System;

  class MainApp
  {
public static void Main()
{
 // Abstract factory #1
 AbstractFactory factory1 = new ConcreteFactory1();
 Client c1 = new Client(factory1);
 c1.Run();

 // Abstract factory #2
 AbstractFactory factory2 = new ConcreteFactory2();
 Client c2 = new Client(factory2);
 c2.Run();

 // Wait for user input
 Console.Read();
}
  }

  // "AbstractFactory"

  abstract class AbstractFactory
  {
public abstract AbstractProductA CreateProductA();
public abstract AbstractProductB CreateProductB();
  }

  // "ConcreteFactory1"

  class ConcreteFactory1 : AbstractFactory
  {
public override AbstractProductA CreateProductA()
{
 return new ProductA1();
}
public override AbstractProductB CreateProductB()
{
 return new ProductB1();
}
  }

  // "ConcreteFactory2"

  class ConcreteFactory2 : AbstractFactory
  {
public override AbstractProductA CreateProductA()
{
 return new ProductA2();
}
public override AbstractProductB CreateProductB()
{
 return new ProductB2();
}
  }

  // "AbstractProductA"

  abstract class AbstractProductA
  {
  }

  // "AbstractProductB"

  abstract class AbstractProductB
  {
public abstract void Interact(AbstractProductA a);
  }

  // "ProductA1"

  class ProductA1 : AbstractProductA
  {
  }

  // "ProductB1"

  class ProductB1 : AbstractProductB
  {
public override void Interact(AbstractProductA a)
{
 Console.WriteLine(this.GetType().Name +
   " interacts with " + a.GetType().Name);
}
  }

  // "ProductA2"

  class ProductA2 : AbstractProductA
  {
  }

  // "ProductB2"

  class ProductB2 : AbstractProductB
  {
public override void Interact(AbstractProductA a)
{
 Console.WriteLine(this.GetType().Name +
   " interacts with " + a.GetType().Name);
}
  }

  // "Client" - the interaction environment of the products

  class Client
  {
private AbstractProductA abstractProductA;
private AbstractProductB abstractProductB;

// Constructor
public Client(AbstractFactory factory)
{
 abstractProductB = factory.CreateProductB();
 abstractProductA = factory.CreateProductA();
}

public void Run()
{
 abstractProductB.Interact(abstractProductA);
}
  }

Строитель

Отделяет конструирование сложного объекта от его представления, так что в результате одного и того же процесса конструирования могут получаться разные представления.


using System;
using System.Collections.Generic;

namespace Builder
{

  public class MainApp
  {
public static void Main()
{
 // Create director and builders
 Director director = new Director();

 Builder b1 = new ConcreteBuilder1();
 Builder b2 = new ConcreteBuilder2();

 // Construct two products
 director.Construct(b1);
 Product p1 = b1.GetResult();
 p1.Show();

 director.Construct(b2);
 Product p2 = b2.GetResult();
 p2.Show();

 // Wait for user
 Console.Read();
}
  }

  // "Director"

  class Director
  {
// Builder uses a complex series of steps
public void Construct(Builder builder)
{
 builder.BuildPartA();
 builder.BuildPartB();
}
  }

  // "Builder"

  abstract class Builder
  {
public abstract void BuildPartA();
public abstract void BuildPartB();
public abstract Product GetResult();
  }

  // "ConcreteBuilder1"

  class ConcreteBuilder1 : Builder
  {
private readonly Product product = new Product();

public override void BuildPartA()
{
 product.Add("PartA");
}

public override void BuildPartB()
{
 product.Add("PartB");
}

public override Product GetResult()
{
 return product;
}
  }

  // "ConcreteBuilder2"

  class ConcreteBuilder2 : Builder
  {
private readonly Product product = new Product();

public override void BuildPartA()
{
 product.Add("PartX");
}

public override void BuildPartB()
{
 product.Add("PartY");
}

public override Product GetResult()
{
 return product;
}
  }

  // "Product"

  class Product
  {
private readonly List parts = new List();

public void Add(string part)
{
 parts.Add(part);
}

public void Show()
{
 Console.WriteLine("\nProduct Parts -------");
 foreach (string part in parts)
   Console.WriteLine(part);
}
  }
 }

Фабричный метод

Фабричный метод (англ. Factory Method) — порождающий шаблон проектирования, предоставляющий подклассам интерфейс для создания экземпляров некоторого класса. В момент создания наследники могут определить, какой класс инстанциировать. Иными словами, Фабрика делегирует создание объектов наследникам родительского класса. Это позволяет использовать в коде программы не специфические классы, а манипулировать абстрактными объектами на более высоком уровне. Также известен под названием виртуальный конструктор.


using System;

class MainApp
{
  static void Main()
  {
// An array of creators
Creator[] creators = new Creator[2];
creators[0] = new ConcreteCreatorA();
creators[1] = new ConcreteCreatorB();

// Iterate over creators and create products
foreach(Creator creator in creators)
{
 Product product = creator.FactoryMethod();
 Console.WriteLine("Created {0}",
   product.GetType().Name);
}

// Wait for user
Console.Read();
  }
}

// "Product"

abstract class Product
{
}

// "ConcreteProductA"

class ConcreteProductA : Product
{
}

// "ConcreteProductB"

class ConcreteProductB : Product
{
}

// "Creator"

abstract class Creator
{
  public abstract Product FactoryMethod();
}

// "ConcreteCreatorA"

class ConcreteCreatorA : Creator
{
  public override Product FactoryMethod()
  {
return new ConcreteProductA();
  }
}

// "ConcreteCreatorB"

class ConcreteCreatorB : Creator
{
  public override Product FactoryMethod()
  {
return new ConcreteProductB();
  }
}

Прототип

Задаёт виды создаваемых объектов с помощью экземпляра-прототипа и создаёт новые объекты путём копирования этого прототипа. Проще говоря, это паттерн создания объекта через клонирование другого объекта вместо создания через конструктор.


using System;

 namespace Prototype
 {  
  class MainApp
  {    
static void Main()
{
 // Create two instances and clone each

 Prototype p1 = new ConcretePrototype1("I");
 Prototype c1 = p1.Clone();
 Console.WriteLine ("Cloned: {0}", c1.Id);

 Prototype p2 = new ConcretePrototype2("II");
 Prototype c2 = p2.Clone();
 Console.WriteLine ("Cloned: {0}", c2.Id);

 // Wait for user
 Console.Read();
}
  }

  // "Prototype"

  abstract class Prototype
  {
private string id;

// Constructor
public Prototype(string id)
{
 this.id = id;
}

// Property
public string Id
{
 get{ return id; }
}

public abstract Prototype Clone();
  }

  // "ConcretePrototype1"

  class ConcretePrototype1 : Prototype
  {
// Constructor
public ConcretePrototype1(string id) : base(id)
{
}

public override Prototype Clone()
{
 // Shallow copy
 return (Prototype)this.MemberwiseClone();
}
  }

  // "ConcretePrototype2"

  class ConcretePrototype2 : Prototype
  {
// Constructor
public ConcretePrototype2(string id) : base(id)
{
}

public override Prototype Clone()
{
 // Shallow copy
 return (Prototype)this.MemberwiseClone();
}
  }
 }

Одиночка 

Гарантирует, что у класса есть только один экземпляр, и предоставляет к нему глобальную точку доступа. Существенно то, что можно пользоваться именно экземпляром класса, так как при этом во многих случаях становится доступной более широкая функциональность. Например, к описанным компонентам класса можно обращаться через интерфейс, если такая возможность поддерживается языком.

/// Singleton class
public class Singleton where T : class
{
  /// Защищенный конструктор по умолчанию необходим для того, чтобы
  /// предотвратить создание экземпляра класса Singleton
  protected Singleton() { }

  /// Фабрика используется для отложенной инициализации экземпляра класса
  private sealed class SingletonCreator where S : class
  {
//Используется Reflection для создания экземпляра класса без публичного конструктора
private static readonly S instance = (S) typeof(S).GetConstructor(
           BindingFlags.Instance | BindingFlags.NonPublic,
           null,
           new Type[0],
           new ParameterModifier[0]).Invoke(null);

public static S CreatorInstance
{
 get { return instance; }
}
  }

  public static T Instance
  {
get { return SingletonCreator.CreatorInstance; }
  }

}

/// Использование Singleton
public class TestClass : Singleton
{
private TestClass() { }

public string TestProc()
{
   return "Hello World";
}
}

Отложенная инициализация

Отложенная (ленивая) инициализация (англ. Lazy initialization). Приём в программировании, когда некоторая ресурсоёмкая операция (создание объекта, вычисление значения) выполняется непосредственно перед тем, как будет использован её результат. Таким образом, инициализация выполняется «по требованию», а не заблаговременно. Аналогичная идея находит применение в самых разных областях: например, компиляция «на лету» и логистическая концепция «Точно в срок». Частный случай ленивой инициализации — создание объекта в момент обращения к нему — является одним из порождающих шаблонов проектирования. Как правило, он используется в сочетании с такими шаблонами как Фабричный метод, Одиночка и Заместитель.

public class LazyInitialization where T : new()
{
protected LazyInitialization() { }

private static T _instance;
public static T Instance
{
   get
   {
       if (_instance == null)
       {
           lock (typeof(T))
           {
               if (_instance == null)
                   _instance = new T();
           }
       }
       return _instance;
   }
}
}

public sealed class BigObject: LazyInitialization
{
   public BigObject()
   {
 //Большая работа
 System.Threading.Thread.Sleep(3000);
 System.Console.WriteLine("Экземпляр BigObject создан");   
   }
}

class Program
{
static void Main(string[] args)
{
 System.Console.WriteLine("Первое обращение к экземпляру BigObject...");

 //создание объекта происходит только при этом обращении к объекту
 System.Console.WriteLine(BigObject.Instance);

 System.Console.WriteLine("Второе обращение к экземпляру BigObject...");
 System.Console.WriteLine(BigObject.Instance);

 //окончание программы
 System.Console.ReadLine();
}
}
using System;

public class BigObject
{
   private static BigObject instance;

   private BigObject()
   {
 //Большая работа
 System.Threading.Thread.Sleep(3000);

 Console.WriteLine("Экземпляр BigObject создан");
   }

   public override string ToString()
   {
 return "Обращение к BigObject";
   }

   // Метод возвращает экземпляр BigObject, при этом он
   // создаёт его, если тот ещё не существует
   public static BigObject GetInstance()
   {
 // для исключения возможности создания двух объектов 
 // при многопоточном приложении
 if (instance == null)
 {
    lock (typeof(BigObject))
    {
       if (instance == null)
          instance = new BigObject();
    }
 }

 return instance;
   }

   public static void Main()
   {
 Console.WriteLine("Первое обращение к экземпляру BigObject...");

 //создание объекта происходит только при этом обращении к объекту
 Console.WriteLine(BigObject.GetInstance());

 Console.WriteLine("Второе обращение к экземпляру BigObject...");
 Console.WriteLine(BigObject.GetInstance());

 //окончание программы
 Console.ReadLine();
   }
}

Объектный пул

Объектный пул (англ. object pool) — порождающий шаблон проектирования, набор инициализированных и готовых к использованию объектов. Когда системе требуется объект, он не создаётся, а берётся из пула. Когда объект больше не нужен, он не уничтожается, а возвращается в пул.



Структурные

Адаптер 

Адаптер, Adapter или Wrapper/Обёртка - структурный шаблон проектирования, предназначенный для организации использования функций объекта, недоступного для модификации, через специально созданный интерфейс.

Мост

Bridge, Мост — шаблон проектирования, используемый в проектировании программного обеспечения чтобы «разделять абстракцию и реализацию так, чтобы они могли изменяться независимо». Шаблон bridge (от англ. — мост) использует инкапсуляцию, агрегирование и может использовать наследование для того, чтобы разделить ответственность между классами.


using System;

namespace Bridge
{

  // MainApp test application

  class MainApp
  {
static void Main()
{
 Abstraction ab = new RefinedAbstraction();

 // Set implementation and call
 ab.Implementor = new ConcreteImplementorA();
 ab.Operation();

 // Change implemention and call
 ab.Implementor = new ConcreteImplementorB();
 ab.Operation();

 // Wait for user
 Console.Read();
}
  }

  ///
  /// Abstraction - абстракция
  ///
  ///
  ///
  •   /// определяем интерфейс абстракции;
      /// хранит ссылку на объект
      ///
      ///
      class Abstraction
      {
    protected Implementor implementor;

    // Property
    public Implementor Implementor
    {
     set{ implementor = value; }
    }

    public virtual void Operation()
    {
     implementor.Operation();
    }
      }

      ///
      /// Implementor - реализатор
      ///
      ///
      ///
  •   /// определяет интерфейс для классов реализации. Он не обязан точно
      /// соотведствовать интерфейсу класса Abstraction. На самом деле оба
      /// интерфейса могут быть совершенно различны. Обычно интерфейс класса
      /// представляет только примитивные операции, а класс
      /// определяет операции более высокого уровня, 
      /// базирующиеся на этих примитивах;
      ///
      ///
      abstract class Implementor
      {
    public abstract void Operation();
      }

      ///
      /// RefinedAbstraction - уточненная абстракция
      ///
      ///
      ///
  •   /// расширяет интерфейс, определенный абстракцией
      ///
      ///
      class RefinedAbstraction : Abstraction
      {
    public override void Operation()
    {
     implementor.Operation();
    }
      }

      ///
      /// ConcreteImplementor - конкретный реализатор
      ///
      ///
      /// содержит конкретную реализацию интерфейса Implementor
      ///
      class ConcreteImplementorA : Implementor
      {
    public override void Operation()
    {
     Console.WriteLine("ConcreteImplementorA Operation");
    }
      }

      // "ConcreteImplementorB"

      class ConcreteImplementorB : Implementor
      {
    public override void Operation()
    {
     Console.WriteLine("ConcreteImplementorB Operation");
    }
      }
    }

    Компоновщик 

    Компоновщик (англ. Composite pattern) - шаблон проектирования, объединяет объекты в древовидную структуру для представления иерархии от частного к целому. Компоновщик позволяет клиентам обращаться к отдельным объектам и к группам объектов одинаково. Паттерн определяет иерархию классов, которые одновременно могут состоять из примитивных и сложных объектов, упрощает архитектуру клиента, делает процесс добавления новых видов объекта более простым.




    Декоратор

    Decorator - структурный шаблон проектирования, предназначенный для динамического подключения дополнительного поведения к объекту. Шаблон Декоратор предоставляет гибкую альтернативу практике создания подклассов с целью расширения функциональности. Известен также под менее распространённым названием Обёртка (Wrapper), которое во многом раскрывает суть реализации шаблона. Объект, который предполагается использовать, выполняет основные функции. Однако может потребоваться добавить к нему некоторую дополнительную функциональность, которая будет выполняться до, после или даже вместо основной функциональности объекта.

    using System;

    namespace Decorator
    {

      class MainApp
      {
    static void Main()
    {
     // Create ConcreteComponent and two Decorators
     ConcreteComponent c = new ConcreteComponent();
     ConcreteDecoratorA d1 = new ConcreteDecoratorA();
     ConcreteDecoratorB d2 = new ConcreteDecoratorB();

     // Link decorators
     d1.SetComponent(c);
     d2.SetComponent(d1);

     d2.Operation();

     // Wait for user
     Console.Read();
    }
      }

      ///
      /// Component - компонент
      ///
      ///
      ///
  •   /// определяем интерфейс для объектов, на которые могут быть динамически 
      /// возложены дополнительные обязанности;
      ///
      ///
      abstract class Component
      {
    public abstract void Operation();
      }

      ///
      /// ConcreteComponent - конкретный компонент
      ///
      ///
      /// определяет объект, на который возлагается дополнительные обязанности
      ///
      class ConcreteComponent : Component
      {
    public override void Operation()
    {
     Console.WriteLine("ConcreteComponent.Operation()");
    }
      }

      ///
      /// Decorator - декоратор
      ///
      ///
      ///
  •   /// хранит ссылку на объект и определяет интерфейс,
      /// соответствующий интерфейсу
      ///
      ///
      abstract class Decorator : Component
      {
    protected Component component;

    public void SetComponent(Component component)
    {
     this.component = component;
    }

    public override void Operation()
    {
     if (component != null)
     {
       component.Operation();
     }
    }
      }

      ///
      /// ConcreteDecorator - конкретный декоратор
      ///
      ///
      ///
  •   /// возглагает дополнительные обязанности на компонент.
      ///
      ///
      class ConcreteDecoratorA : Decorator
      {
    private string addedState;

    public override void Operation()
    {
     base.Operation();
     addedState = "New State";
     Console.WriteLine("ConcreteDecoratorA.Operation()");
    }
      }

      // "ConcreteDecoratorB"

      class ConcreteDecoratorB : Decorator
      {
    public override void Operation()
    {
     base.Operation();
     AddedBehavior();
     Console.WriteLine("ConcreteDecoratorB.Operation()");
    }

    void AddedBehavior()
    {
    }
      }
    }

    Фасад 

    Шаблон Facade (Фасад) - позволяет скрыть сложность системы путем сведения всех возможных внешних вызовов к одному объекту, делегирующему их соответствующим объектам системы. Определить одну точку взаимодействия с подсистемой - фасадный объект, обеспечивающий общий интерфейс с подсистемой и возложить на него обязанность по взаимодействию с её компонентами. Фасад - это внешний объект, обеспечивающий единственную точку входа для служб подсистемы. Реализация других компонентов подсистемы закрыта и не видна внешним компонентам. Фасадный объект обеспечивает реализацию паттерна Устойчивый к изменениям (Protected Variations) с точки зрения защиты от изменений в реализации подсистемы.

    using System;

    namespace Library
    {

    internal class SubsystemA
    {
       internal string A1()
       {
           return "Subsystem A, Method A1\n";
       }
       internal string A2()
       {
           return "Subsystem A, Method A2\n";
       }
    }
    internal class SubsystemB
    {
       internal string B1()
       {
           return "Subsystem B, Method B1\n";
       }
    }
    internal class SubsystemC
    {
       internal string C1()
       {
           return "Subsystem C, Method C1\n";
       }
    }
    }

    // Facade - фасад
    public static class Facade
    {
    static Library.SubsystemA a = new Library.SubsystemA();
    static Library.SubsystemB b = new Library.SubsystemB();
    static Library.SubsystemC c = new Library.SubsystemC();

    public static void Operation1()
    {
       Console.WriteLine("Operation 1\n" +
       a.A1() +
       a.A2() +
       b.B1());
    }
    public static void Operation2()
    {
       Console.WriteLine("Operation 2\n" +
       b.B1() +
       c.C1());
    }
    }

    class Program
    {
    static void Main(string[] args)
    {
       Facade.Operation1();
       Facade.Operation2();

       // Wait for user
       Console.Read();
    }
    }

    Заместитель

    Шаблон Proxy (определяет объект-заместитель) - шаблон проектирования, который предоставляет объект, который контролирует доступ к другому объекту через перехват всех вызовов (выполняет функцию контейнера). «Заместитель» хранит ссылку, которая позволяет заместителю обратиться к реальному субъекту (объект класса «Заместитель» может обращаться к объекту класса «Субъект», если интерфейсы «Реального Субъекта» и «Субъекта» одинаковы). Поскольку интерфейс «Реального Субъекта» идентичен интерфейсу «Субъекта», так, что «Заместителя» можно подставить вместо «Реального Субъекта», контролирует доступ к «Реальному Субъекту», может отвечать за создание или удаление «Реального Субъекта». «Субъект» определяет общий для «Реального Субъекта» и «Заместителя» интерфейс, так, что «Заместитель» может быть использован везде, где ожидается «Реальный Субъект». При необходимости запросы могут быть переадресованы «Заместителем» «Реальному Субъекту».


    Шаблон proxy бывает нескольких видов, а именно:
    • Удаленный заместитель (remote proxies) обеспечивает связь с «Субъектом», который находится в другом адресном пространстве или на удалённой машине. Так же может отвечать за кодирование запроса и его аргументов и отправку закодированного запроса реальному «Субъекту»,
    • Виртуальный заместитель (англ. virtual proxies): обеспечивает создание реального «Субъекта» только тогда, когда он действительно понадобится. Так же может кэшировать часть информации о реальном «Субъекте», чтобы отложить его создание,
    • Копировать-при-записи: обеспечивает копирование «субъекта» при выполнении клиентом определённых действий (частный случай «виртуального прокси»).
    • Защищающий заместитель (англ. protection proxies): может проверять, имеет ли вызывающий объект необходимые для выполнения запроса права.
    • Кэширующий прокси: обеспечивает временное хранение результатов расчёта до отдачи их множественным клиентам, которые могут разделить эти результаты.
    • Экранирующий прокси: защищает «Субъект» от опасных клиентов (или наоборот).
    • Синхронизирующий прокси: производит синхронизированный контроль доступа к «Субъекту» в асинхронной многопоточной среде.
    • Smart reference proxy: производит дополнительные действия, когда на «Субъект» создается ссылка, например, рассчитывает количество активных ссылок на «Субъект».

    using System;
    using System.Threading;

      class MainApp
      {
    static void Main()
    {
     // Create math proxy
     IMath p = new MathProxy();

     // Do the math
     Console.WriteLine("4 + 2 = " + p.Add(4, 2));
     Console.WriteLine("4 - 2 = " + p.Sub(4, 2));
     Console.WriteLine("4 * 2 = " + p.Mul(4, 2));
     Console.WriteLine("4 / 2 = " + p.Div(4, 2));

     // Wait for user
     Console.Read();
    }
      }

      ///
      /// Subject - субъект
      ///
      ///
      ///
  •   /// определяет общий для и интерфейс, так что класс
      /// можно использовать везде, где ожидается
      ///
      ///
      public interface IMath
      {
    double Add(double x, double y);
    double Sub(double x, double y);
    double Mul(double x, double y);
    double Div(double x, double y);
      }
      
      ///
      /// RealSubject - реальный объект
      ///
      ///
      ///
  •   /// определяет реальный объект, представленный заместителем
      ///
      ///
      class Math : IMath
      {
    public Math()
    {
       Console.WriteLine("Create object Math. Wait...");
       Thread.Sleep(1000);
    }

    public double Add(double x, double y){return x + y;}
    public double Sub(double x, double y){return x - y;}
    public double Mul(double x, double y){return x * y;}
    public double Div(double x, double y){return x / y;}
      }

      ///
      /// Proxy - заместитель
      ///
      ///
      ///
  •   /// хранит ссылку, которая позволяет заместителю обратиться к реальному
      /// субъекту. Объект класса MathProxy может обращаться к объекту класса IMath, если интерфейсы классов Math и IMath одинаковы;
      /// предоставляет интерфейс, идентичный интерфейсу IMath, так что заместитель
      /// всегда может быть предоставлен вместо реального субъекта;
      /// контролирует доступ к реальному субъекту и может отвечать за его создание 
      /// и удаление;
      /// прочие обязанности зависят от вида заместителя:
      ///
  •   /// удаленный заместитель отвечает за кодирование запроса и его аргументов
      /// и отправление закодированного запроса реальному субъекту в
      /// другом адресном пространстве;
      /// виртуальный заместитель может кэшировать дополнительную информацию
      /// о реальном субъекте, чтобы отложить его создание.
      /// защищающий заместитель проверяет, имеет ли вызывающий объект 
      /// необходимые для выполнения запроса права;
      ///
      ///
      ///
      ///
      class MathProxy : IMath
      {
    Math math;

    public MathProxy()
    {
     math = null;
    }

    ///
    /// Быстрая операция - не требует реального субъекта
    ///
    ///
    ///
    ///
    public double Add(double x, double y)
    {
     return x + y;
    }

    public double Sub(double x, double y)
    {
     return x - y;
    }

    ///
    /// Медленная операция - требует создания реального субъекта
    ///
    ///
    ///
    ///
    public double Mul(double x, double y)
    {
     if (math == null)
         math = new Math();
     return math.Mul(x, y);
    }

    public double Div(double x, double y)
    {
     if (math == null)
         math = new Math();
     return math.Div(x, y);
    }
      }

    Приспособленец

    Приспособленец (англ. Flyweight) - это объект, представляющий себя как уникальный экземпляр в разных местах программы, но по факту не являющийся таковым. Flyweight используется для уменьшения затрат при работе с большим количеством мелких объектов. При проектировании приспособленца, необходимо разделить его свойства на внешние и внутренние. Внутренние неизменны в разных местах применения приспособленца, тогда как внешние могут быть разными и должны быть вынесены за пределы приспособленца. Flyweight дополняет паттерн Factory, используя его таким образом, что Factory, при обращении к ней Клиента, перед созданием нового объекта, ищет уже созданный объект с такими же параметрами, что и у требуемого. Затем возвращает его Клиенту, Если такого объекта нет, то фабрика создаст новый.




    ПОВЕДЕНИЯ

    Цепочка обязанностей

    Цепочка обязанностей - поведенческий шаблон проектирования, предназначенный для организации в системе уровней ответственности.
    Шаблон рекомендован для использования в условиях:
    • в разрабатываемой системе имеется группа объектов, которые могут обрабатывать сообщения определенного типа;
    • все сообщения должны быть обработаны хотя бы одним объектом системы;
    • сообщения в системе обрабатываются по схеме «обработай сам либо перешли другому», то есть одни сообщения обрабатываются на том уровне, где они получены, а другие пересылаются объектам иного уровня.

    Команда 

    Команда - шаблон проектирования, используемый при объектно-ориентированном программировании, представляющий действие. Объект команды заключает в себе само действие и его параметры. Создание структуры, в которой класс-отправитель и класс-получатель не зависят друг от друга напрямую. Организация обратного вызова к классу, который включает в себя класс-отправитель. Обеспечивает обработку команды в виде объекта, что позволяет сохранять её, передавать в качестве параметра методам, а также возвращать её в виде результата, как и любой другой объект. Например, библиотека печати может иметь класс PrintJob. Для его использования можно создать объект PrintJob, установить необходимые параметры, и вызвать метод, непосредственно отсылающий задание на печать.

    using System;
    using System.Collections.Generic;

    namespace Command
    {

      class MainApp
      {
    static void Main()
    {
     // Создаем пользователя.
     User user = new User();

     // Пусть он что-нибудь сделает.
     user.Compute('+', 100);
     user.Compute('-', 50);
     user.Compute('*', 10);
     user.Compute('/', 2);

     // Отменяем 4 команды
     user.Undo(4);

     // Вернём 3 отменённые команды.
     user.Redo(3);

     // Ждем ввода пользователя и завершаемся.
     Console.Read();
    }
      }

      // "Command" : абстрактная Команда

      abstract class Command
      {
    public abstract void Execute();
    public abstract void UnExecute();
      }

      // "ConcreteCommand" : конкретная команда

      class CalculatorCommand : Command
      {
    char @operator;
    int operand;
    Calculator calculator;

    // Constructor
    public CalculatorCommand(Calculator calculator, 
                char @operator, int operand)
    {
     this.calculator = calculator;
     this.@operator = @operator;
     this.operand = operand;
    }

    public char Operator
    {
     set{ @operator = value; }
    }

    public int Operand
    {
     set{ operand = value; }
    }

    public override void Execute()
    {
     calculator.Operation(@operator, operand);
    }

    public override void UnExecute()
    {
     calculator.Operation(Undo(@operator), operand);
    }

    // Private helper function : приватные вспомогательные функции
    private char Undo(char @operator)
    {
     char undo;
     switch(@operator)
     {
       case '+': undo = '-'; break;
       case '-': undo = '+'; break;
       case '*': undo = '/'; break;
       case '/': undo = '*'; break;
       default : undo = ' '; break;
     }
     return undo;
    }
      }

      // "Receiver" : получатель

      class Calculator
      {
    private int curr = 0;

    public void Operation(char @operator, int operand)
    {
     switch(@operator)
     {
       case '+': curr += operand; break;
       case '-': curr -= operand; break;
       case '*': curr *= operand; break;
       case '/': curr /= operand; break;
     }
     Console.WriteLine(
       "Current value = {0,3} (following {1} {2})",
       curr, @operator, operand);
    }
      }

      // "Invoker" : вызывающий

      class User
      {
    // Initializers
    private Calculator calculator = new Calculator();
    private List commands = new List();

    private int current = 0;

    public void Redo(int levels)
    {
     Console.WriteLine("\n---- Redo {0} levels ", levels);

     // Делаем возврат операций
     for (int i = 0; i < levels; i++)
       if (current < commands.Count - 1)
         commands[current++].Execute();
    }

    public void Undo(int levels)
    {
     Console.WriteLine("\n---- Undo {0} levels ", levels);

     // Делаем отмену операций
     for (int i = 0; i < levels; i++)
       if (current > 0)
         commands[--current].UnExecute();
    }

    public void Compute(char @operator, int operand)
    {

     // Создаем команду операции и выполняем её
     Command command = new CalculatorCommand(
       calculator, @operator, operand);
     command.Execute();

     // Добавляем операцию к списку отмены
     commands.Add(command);
     current++;
    }
      }
    }

    Интерпретатор 

    Шаблон Interpreter (Интерпретатор) - Поведенческий шаблон (Behavioral).
    Решает часто встречающуюся, подверженную изменениям задачу.

    Итератор

    Iterator (Cursor) - представляет собой объект, позволяющий получить последовательный доступ к элементам объекта-агрегата без использования описаний каждого из объектов, входящий в состав агрегации. Например, такие элементы как дерево, связанный список, хэш-таблица и массив могут быть пролистаны (и модифицированы) с помощью паттерна (объекта) Итератор.

    Посредник 

    Шаблон Mediator (Посредник) - обеспечивает взаимодействие множества объектов, сформировав при этом слабую связанность и избавив объекты от необходимости явно ссылаться друг на друга.


    Хранитель 

    Хранитель (Memento, Token, Лексема) - поведенческий шаблон проектирования. Позволяет не нарушая инкапсуляцию зафиксировать и сохранить внутреннее состояния объекта так, чтобы позднее восстановить его в этом состоянии.

    Структура: Originator - "Создатель", Caretaker - "Опекун", Memento - "Хранитель".

    Наблюдатель 

    Наблюдатель, Observer («подчинённые» Dependents, «издатель-подписчик» Publisher-Subscriber) - поведенческий шаблон проектирования. Определяет зависимость типа «один ко многим» между объектами таким образом, что при изменении состояния одного объекта все зависящие от него оповещаются об этом событии.


    При реализации шаблона «наблюдатель» обычно используются следующие классы.
    • Observable - интерфейс, определяющий методы для добавления, удаления и оповещения наблюдателей.
    • Observer - интерфейс, с помощью которого наблюдаемый объект оповещает наблюдателей.
    • ConcreteObservable - конкретный класс, который реализует интерфейс Observable.
    • ConcreteObserver - конкретный класс, который реализует интерфейс Observer.

    Применяется в тех случаях, когда система обладает следующими свойствами:
    • существует, как минимум, один объект, рассылающий сообщения.
    • имеется не менее одного получателя сообщений, причём их количество и состав могут изменяться во время работы приложения.
    • нет надобности очень сильно связывать взаимодействующие объекты, что полезно для повторного использования.
    Данный шаблон часто применяют в ситуациях, в которых отправителя сообщений не интересует, что делают получатели с предоставленной им информацией.

    using System;
    using System.Collections;
    using System.Threading;

    namespace Observer
    {
    ///
    /// Observer Pattern Judith Bishop Jan 2007
    /// 
    /// The Subject runs in a thread and changes its state
    /// independently. At each change, it notifies its Observers.
    ///
    class Program
    {
       static void Main(string[] args)
       {
           Subject subject = new Subject();
           Observer Observer = new Observer(subject,"Center","\t\t");
           Observer observer2 = new Observer(subject,"Right","\t\t\t\t");
           subject.Go();

           // Wait for user
           Console.Read();
       }

    }

    class Simulator : IEnumerable {
       string [] moves = {"5", "3", "1", "6", "7"};

       public IEnumerator GetEnumerator() 
       {
           foreach( string element in moves )
               yield return element;
       }
    }

    class Subject {

       public delegate void Callback (string s);

       public event Callback Notify;

       Simulator simulator = new Simulator( );

       const int speed = 200;

       public string SubjectState { get; set; }

       public void Go() 
       {
           new Thread(new ThreadStart(Run)).Start( );
       }

       void Run () 
       {
           foreach (string s in simulator) 
           {
               Console.WriteLine("Subject: " + s);
               SubjectState = s;
               Notify(s);
               Thread.Sleep(speed); // milliseconds
           }
       }
    }

    interface IObserver 
    {
       void Update(string state);
    }

    class Observer : IObserver
    {
       string name;

       Subject subject;

       string state;

       string gap;

       public Observer(Subject subject, string name, string gap)
       {
           this.subject = subject;
           this.name = name;
           this.gap = gap;
           subject.Notify += Update;
       }

       public void Update(string subjectState)
       {
           state = subjectState;
           Console.WriteLine(gap + name + ": " + state);
       }
    }
    }

    Состояние 

    Состояние (англ. State) — шаблон проектирования. Используется в тех случаях, когда во время выполнения программы объект должен менять свое поведение в зависимости от своего состояния. Паттерн состоит из 3 блоков:
    • Widget — класс, объекты которого должны менять свое поведение в зависимости от состояния.
    • IState — интерфейс, который должно реализовать каждое из конкретных состояний. Через этот интерфейс объект Widget взаимодействует с состоянием, делегируя ему вызовы методов. Интерфейс должен содержать средства для обратной связи с объектом, поведение которого нужно изменить. Для этого используется событие (паттерн Publisher — Subscriber). Это необходимо для того, чтобы в процессе выполнения программы заменять объект состояния при появлении событий. Возможны случаи, когда сам Widget периодически опрашивает объект состояние на наличие перехода.
    • StateA … StateZ — классы конкретных состояний. Должны содержать информацию о том, при каких условиях и в какие состояния может переходить объект из текущего состояния. Например, из StateA объект может переходить в состояние StateB и StateC, а из StateB — обратно в StateA и так далее. Объект одного из них должен содержать Widget при создании.

    using System;
    namespace Digital_Patterns.Behavioral.State
    {
    public interface IAutomatState
    {
       String GotApplication();
       String CheckApplication();
       String RentApartment();
       String DispenseKeys();
    }

    public interface IAutomat
    {
       void GotApplication();
       void CheckApplication();
       void RentApartment();

       void SetState(IAutomatState s);
       IAutomatState GetWaitingState();
       IAutomatState GetGotApplicationState();
       IAutomatState GetApartmentRentedState();
       IAutomatState GetFullyRentedState();

       Int32 Count { get; set; }
    }

    public class Automat : IAutomat
    {
       private IAutomatState _waitingState;
       private IAutomatState _gotApplicationState;
       private IAutomatState _apartmentRentedState;
       private IAutomatState _fullyRentedState;
       private IAutomatState _state;
       private Int32 _count;

       public Automat(Int32 n)
       {
           _count = n;
           _waitingState = new WaitingState(this);
           _gotApplicationState = new GotApplicationState(this);
           _apartmentRentedState = new ApartmentRentedState(this);
           _fullyRentedState = new FullyRentedState(this);
           _state = _waitingState;
       }

       public void GotApplication()
       {
           Console.WriteLine(_state.GotApplication());
       }

       public void CheckApplication()
       {
           Console.WriteLine(_state.CheckApplication());
       }

       public void RentApartment()
       {
           Console.WriteLine(_state.RentApartment());
           Console.WriteLine(_state.DispenseKeys());
       }

       public void SetState(IAutomatState s) { _state = s; }

       public IAutomatState GetWaitingState() { return _waitingState; }

       public IAutomatState GetGotApplicationState() { return _gotApplicationState; }

       public IAutomatState GetApartmentRentedState() { return _apartmentRentedState; }

       public IAutomatState GetFullyRentedState() { return _fullyRentedState; }

       public int Count 
       { 
           get { return _count; }
           set { _count = value; }
       }
    }

    public class WaitingState : IAutomatState
    {
       private Automat _automat;

       public WaitingState(Automat automat)
       {
           _automat = automat;
       }

       public String GotApplication()
       {
           _automat.SetState(_automat.GetGotApplicationState());
           return "Thanks for the application.";
       }

       public String CheckApplication() { return "You have to submit an application."; }

       public String RentApartment() { return "You have to submit an application."; }

       public String DispenseKeys() { return "You have to submit an application."; }
    }

    public class GotApplicationState : IAutomatState
    {
       private Automat _automat;
       private readonly Random _random;

       public GotApplicationState(Automat automat)
       {
           _automat = automat;
           _random = new Random(System.DateTime.Now.Millisecond);
       }

       public String GotApplication() { return "We already got your application."; }

       public String CheckApplication()
       {
           var yesNo = _random.Next() % 10;

           if (yesNo > 4 && _automat.Count > 0)
           {
               _automat.SetState(_automat.GetApartmentRentedState());
               return "Congratulations, you were approved.";
           }
           else
           {
               _automat.SetState(_automat.GetWaitingState());
               return "Sorry, you were not approved.";
           }
       }

       public String RentApartment() { return "You must have your application checked."; }

       public String DispenseKeys() { return "You must have your application checked."; }
    }

    public class ApartmentRentedState : IAutomatState
    {
       private Automat _automat;

       public ApartmentRentedState(Automat automat)
       {
           _automat = automat;
       }

       public String GotApplication() { return "Hang on, we'ra renting you an apartmeny."; }

       public String CheckApplication() { return "Hang on, we'ra renting you an apartmeny."; }

       public String RentApartment()
       {
           _automat.Count = _automat.Count - 1;
           return "Renting you an apartment....";
       }

       public String DispenseKeys()
       {
           if(_automat.Count <= 0)
               _automat.SetState(_automat.GetFullyRentedState());
           else
               _automat.SetState(_automat.GetWaitingState());
           return "Here are your keys!";
       }
    }

    public class FullyRentedState : IAutomatState
    {
       private Automat _automat;

       public FullyRentedState(Automat automat)
       {
           _automat = automat;
       }

       public String GotApplication() { return "Sorry, we're fully rented."; }

       public String CheckApplication() { return "Sorry, we're fully rented."; }

       public String RentApartment() { return "Sorry, we're fully rented."; }

       public String DispenseKeys() { return "Sorry, we're fully rented."; }
    }

    class Program
    {
       static void Main(string[] args)
       {
           var automat = new Automat(9);

           automat.GotApplication();
           automat.CheckApplication();
           automat.RentApartment();
       }
    }
    }

    Стратегия 

    Стратегия Strategy - предназначен для определения семейства алгоритмов, инкапсуляции каждого из них и обеспечения их взаимозаменяемости. Это позволяет выбирать алгоритм путем определения соответствующего класса. Шаблон Strategy позволяет менять выбранный алгоритм независимо от объектов-клиентов, которые его используют.

    Мотивы
    • Программа должна обеспечивать различные варианты алгоритма или поведения
    • Нужно изменять поведение каждого экземпляра класса
    • Необходимо изменять поведение объектов на стадии выполнения
    • Введение интерфейса позволяет классам-клиентам ничего не знать о классах, реализующих этот интерфейс и инкапсулирующих в себе конкретные алгоритмы
    Способ решения - Отделение процедуры выбора алгоритма от его реализации. Это позволяет сделать выбор на основании контекста.
    Участники:
    • Класс Strategy определяет как будут использоваться различные алгоритмы.
    • Конкретные классы ConcreteStrategy реализуют эти различные алгоритмы.
    • Класс Context использует конкретные классы ConcreteStrategy посредством ссылки на конкретный тип абстрактного класса Strategy. Классы Strategy и Context взаимодействуют с целью реализации выбранного алгоритма (в некоторых случаях классу Strategy требуется посылать запросы классу Context). Класс Context пересылает классу Strategy запрос, поступивший от его класса-клиента.

    using System;

    namespace DesignPatterns.Behavioral.Strategy
    {
    ///
    /// Интерфейс «Стратегия» определяет функциональность (в данном примере это метод
    /// Algorithm), которая должна быть реализована
    /// конкретными классами стратегий. Другими словами, метод интерфейса определяет
    /// решение некой задачи, а его реализации в конкретных классах стратегий определяют,
    /// КАК, КАКИМ ПУТЁМ эта задача будет решена.
    ///
    public interface IStrategy
    {
       void Algorithm();
    }

    ///
    /// Первая конкретная реализация-стратегия.
    ///
    public class ConcreteStrategy1 : IStrategy
    {
       public void Algorithm()
       {
           Console.WriteLine("Выполняется алгоритм стратегии 1.");
       }
    }

    ///
    /// Вторая конкретная реализация-стратегия.
    /// Реализаций может быть сколько угодно много.
    ///
    public class ConcreteStrategy2 : IStrategy
    {
       public void Algorithm()
       {
           Console.WriteLine("Выполняется алгоритм стратегии 2.");
       }
    }

    ///
    /// Контекст, использующий стратегию для решения своей задачи.
    ///
    public class Context
    {
       ///
       /// Ссылка на интерфейс IStrategy
       /// позволяет автоматически переключаться между конкретными реализациями
       /// (другими словами, это выбор конкретной стратегии).
       ///
       private IStrategy _strategy;

       ///
       /// Конструктор контекста.
       /// Инициализирует объект стратегией.
       ///
       ///
       /// Стратегия.
       ///
       public Context(IStrategy strategy)
       {
           _strategy = strategy;
       }

       ///
       /// Метод для установки стратегии.
       /// Служит для смены стратегии во время выполнения.
       /// В C# может быть реализован также как свойство записи.
       ///
       ///
       /// Новая стратегия.
       ///
       public void SetStrategy(IStrategy strategy)
       {
           _strategy = strategy;
       }

       ///
       /// Некоторая функциональность контекста, которая выбирает
       /// стратегию и использует её для решения своей задачи.
       ///
       public void ExecuteOperation()
       {
           _strategy.Algorithm();
       }
    }

    ///
    /// Класс приложения.
    /// В данном примере выступает как клиент контекста.
    ///
    public static class Program
    {
       ///
       /// Точка входа в программу.
       ///
       public static void Main()
       {
           // Создём контекст и инициализируем его первой стратегией.
           Context context = new Context(new ConcreteStrategy1());
           // Выполняем операцию контекста, которая использует первую стратегию.
           context.ExecuteOperation();
           // Заменяем в контексте первую стратегию второй.
           context.SetStrategy(new ConcreteStrategy2());
           // Выполняем операцию контекста, которая теперь использует вторую стратегию.
           context.ExecuteOperation();
       }
    }
    }

    Шаблонный метод 

    Шаблонный метод (Template method) - определяет основу алгоритма и позволяет наследникам переопределять некоторые шаги алгоритма, не изменяя его структуру в целом. Применимость шаблона:
    • Однократное использование инвариантной части алгоритма, с оставлением изменяющейся части на усмотрение наследникам.
    • Локализация и вычленение общего для нескольких классов кода для избежания дублирования.
    • Разрешение расширения кода наследниками только в определенных местах.
    Участники: 
    • Abstract class (абстрактный класс) - определяет абстрактные операции, замещаемые в наследниках для реализации шагов алгоритма; реализует шаблонный метод, определяющий скелет алгоритма. Шаблонный метод вызывает замещаемые и другие, определенные в Abstract class, операции.
    • Concrete class (конкретный класс) - реализует замещаемые операции необходимым для данной реализации способом.

    /**
     * An abstract class that is common to several games in
     * which players play against the others, but only one is
     * playing at a given time.
     */

    abstract class Game {

    protected int playersCount; 
    abstract void initializeGame(); 
    abstract void makePlay(int player); 
    abstract boolean endOfGame(); 
    abstract void printWinner();

    /* A template method : */
    final void playOneGame(int playersCount) {
       this.playersCount = playersCount;
       initializeGame();
       int j = 0;
       while (!endOfGame()) {
           makePlay(j);
           j = (j + 1) % playersCount;
       }
       printWinner();
    }
    }

    //Now we can extend this class in order to implement actual games:

    class Monopoly extends Game {

    /* Implementation of necessary concrete methods */

    void initializeGame() {
       // Initialize money
    }

    void makePlay(int player) {
       // Process one turn of player
    }

    boolean endOfGame() {
       // Return true of game is over according to Monopoly rules
    }

    void printWinner() {
       // Display who won
    }

    /* Specific declarations for the Monopoly game. */ 
    // ... 
    }

    class Chess extends Game {

    /* Implementation of necessary concrete methods */

    void initializeGame() {
       // Put the pieces on the board
    }

    void makePlay(int player) {
       // Process a turn for the player
    }

    boolean endOfGame() {
       // Return true if in Checkmate or Stalemate has been reached
    }

    void printWinner() {
       // Display the winning player
    }

    /* Specific declarations for the chess game. */
    // ...
    }

    Посетитель

    Шаблон Посетитель (Visitor) - описывает операцию, которая выполняется над объектами других классов. При изменении Visitor нет необходимости изменять обслуживаемые классы. Для полной независимости посетители имеют отдельную от обслуживаемых структур иерархию. Структуры должны иметь некий интерфейс взаимодействия. При необходимости добавления новых операций необходимо создать новый класс ConcreteVisitor и поместить его в цепочку обхода обслуживаемых структур.




    Параллельное программирование

    Блокировка с двойной проверкой

    Double checked locking (блокировка с двойной проверкой) - шаблон применяющийся в параллельном программировании. Он предназначен для уменьшения накладных расходов, связанных с получением блокировки. Сначала проверяется условие блокировки без какой-либо синхронизации; поток делает попытку получить блокировку только если результат проверки говорит о том, что ни один другой поток не владеет блокировкой. На некоторых языках и/или на некоторых машинах невозможно безопасно реализовать данный шаблон. Поэтому иногда его называют анти-паттерном. Обычно он используется для уменьшения накладных расходов при реализации ленивой инициализации в многопоточных программах, например в составе шаблона проектирования Одиночка. При ленивой инициализации переменной, инициализация откладывается до тех пор, пока значение переменной действительно понадобится при вычислениях.

    Пример использования в С#:
    public sealed class Singleton
    {
       private Singleton()
       {
     // инициализировать новый экземпляр объекта
       }

       private static volatile Singleton singletonInstance;

       private static readonly Object syncRoot = new Object();

       public static Singleton GetInstance()
       {
     // создан ли объект
     if(singletonInstance == null)
     {
        // нет, не создан
        // только один поток может создать его
        lock(syncRoot))
        {
           // проверяем, не создал ли объект другой поток
           if(singletonInstance == null)
           {
              // нет не создал — создаём
              singletonInstance = new Singleton();
           }
        }
     }
     return singletonInstance;
       }
    }


    Планировщик

    Планировщик (англ. Scheduler) - обеспечивает механизм реализации политики планирования, но при этом не зависящий ни от одной конкретной политики. Управляет порядком, в соответствии с которым потокам предстоит выполнить последовательный код, используя для этого объект, который явным образом задаёт последовательность ожидающих потоков.


    Однопоточное выполнение

    Однопоточное выполнение (Single Threaded Execution) — известный также под названием англ. Critical Section. Шаблон проектирования препятствующий конкурентному вызову метода, тем самым запрещая параллельное выполнение этого метода.

    No comments:

    Post a Comment