SlideShare une entreprise Scribd logo
1  sur  107
Télécharger pour lire hors ligne
Темы лекции: SOLID. Паттерны проектирования
Игорь Шкулипа, к.т.н.
http://www.slideshare.net/IgorShkulipa 2
SOLID принципы
http://www.slideshare.net/IgorShkulipa 3
SOLID. Принципы проектирования классов
SOLID – это акроним названий пяти основных принципов
проектирования классов, сформулированных Робертом Мартином:
•Single responsibility (принцип одной ответственности),
•Open for extension and closed for modification (принцип
открытости/закрытости, или открытость для расширения и
закрытость для модификации),
•Liskov substitution (принцип подстановки Лисков),
•Interface segregation (принцип разделения интерфейса),
•Dependency inversion (принцип инверсии зависимостей).
http://www.slideshare.net/IgorShkulipa 4
Single Responsibility
Принцип единственной ответственности (Single Responsibility Principle)
часто определяют так: у объекта должна быть только одна причина для
изменения; чем больше файл или класс, тем труднее достичь этой
цели.
Этот принцип говорит о том, что по-хорошему каждый класс должен
решать только одну задачу. Это совсем не значит, что в классе
должен быть всего один метод. Это означает, что методы класса
должны быть связаны одной общей целью.
http://www.slideshare.net/IgorShkulipa 5
Single Responsibility
class Persone {
public string Name { get; set; }
public string Surname { get; set; }
public string Middle { get; set; }
public void LoadFromDatabase() { }
public void SaveToDatabase() { }
public void PrintToPrinter() { }
} class Persone {
public string Name { get; set; }
public string Surname { get; set; }
public string Middle { get; set; }
}
class PersoneDatabase {
public Persone LoadFromDatabase() { }
public void SaveToDatabase(Persone p) { }
}
class PersonePrinter {
public void PrintToPrinter(Persone p) { }
}
http://www.slideshare.net/IgorShkulipa 6
Open for Extension and Closed for Modification
Объекты проектирования (классы, функции, модули и т.д.) должны быть
открыты для расширения, но закрыты для модификации.
Этот принцип говорит о том, что классы нужно проектировать так, чтобы
впоследствии иметь возможность изменять поведение класса, не
изменяя его код.
http://www.slideshare.net/IgorShkulipa 7
Open for Extension and Closed for Modification
class PersonePrinter {
public void PrintToPrinter(Persone p) { }
}
class PersonePrinter {
public void PrintToPrinter(Persone p) { }
public void PrintToPrinterShortForm(Persone p) { }
public void PrintToPrinterDetailedForm(Persone p) { }
}
interface IPrintForm { List<string> Formats { get; set; } }
class PrintFormGeneral : IPrintForm {}
class PrintFormShort : IPrintForm { }
class PrintFormDetailed : IPrintForm { }
class PersonePrinter
{
public void PrintToPrinter(Persone p, IPrintForm f) { }
}
http://www.slideshare.net/IgorShkulipa 8
Liskov Substitution
Функции, которые используют ссылки на базовые классы, должны иметь
возможность использовать объекты производных классов, не зная об
этом.
http://www.slideshare.net/IgorShkulipa 9
Liskov Substitution
class PersonePrinter
{
public void PrintToPrinter(Persone p, IPrintForm f) {
//...
var shortForm = f as PrintFormShort;
if (shortForm != null) { ... }
//...
var detailedForm = f as PrintFormDetailed;
if (detailedForm != null) { ... }
//...
}
}
class PersonePrinter
{
public void PrintToPrinter(Persone p, IPrintForm f) {
//...
f.FormatReport(p);
//...
}
}
http://www.slideshare.net/IgorShkulipa 10
Interface Segregation
Принцип изоляции/разделения интерфейса говорит о том, что клиент не
должен вынужденно зависеть от элементов интерфейса, которые он не
использует.
http://www.slideshare.net/IgorShkulipa 11
Interface Segregation
interface IEmployee {
void UseComputer();
void Develop();
void Test();
}
class SoftDeveloper : IEmployee {
public void UseComputer() { }
public void Develop() { }
public void Test() {/* How??? */}
}
class SoftTester : IEmployee {
public void UseComputer() { }
public void Develop() {/* How??? */}
public void Test() { }
}
interface IEmployee {
void UseComputer();
}
interface IDeveloper {
void Develop();
}
interface ITester {
void Test();
}
class SoftDeveloper : IEmployee, IDeveloper {
public void UseComputer() { }
public void Develop() { }
}
class SoftTester : IEmployee, ITester {
public void UseComputer() { }
public void Test() { }
}
http://www.slideshare.net/IgorShkulipa 12
Dependency Inversion
• Модули верхних уровней не должны зависеть от модулей нижних
уровней.
• Оба типа модулей должны зависеть от абстракций.
• Абстракции не должны зависеть от деталей.
• Детали должны зависеть от абстракций.
http://www.slideshare.net/IgorShkulipa 13
Dependency Inversion
class SoftDeveloper {
public void Develop() { }
}
class Manager
{
private readonly SoftDeveloper dev =
new SoftDeveloper();
public void Manage() {
dev.Develop();
}
}
interface IDeveloper {
void Develop();
}
class SoftDeveloper: IDeveloper {
public void Develop() { }
}
class Manager {
private IDeveloper dev;
public Manager(IDeveloper developer) {
dev = developer;
}
public void Manage() {
dev.Develop();
}
}
http://www.slideshare.net/IgorShkulipa 14
Паттерны проектирования
http://www.slideshare.net/IgorShkulipa 15
Паттерны (шаблоны проектирования)
Паттерн описывает задачу, которая снова и снова возникает в работе, а так же
принцип ее решения, причем таким образом, что это решение можно потом
использовать много раз, ничего не изобретая заново.
В общем случае паттерн состоит из четырех основных элементов:
Имя. Присваивание паттернам имен позволяет проектировать на более высоком
уровне абстракции. С помощью имен паттернов можно вести общение с
коллегами. Назначение паттернам имен упрощает общение в профессиональной
среде.
Задача - это описание того, когда следует применять паттерн. Необходимо
сформулировать задачу и ее контекст. Может описываться конкретная проблема
проектирования, например способ представления алгоритмов в виде объектов.
Так же задача может включать перечень условий, при выполнении которых имеет
смысл применять данный паттерн.
Решение представляет собой описание элементов дизайна, отношений между
ними, функций каждого элемента. Конкретный дизайн или реализация не имеются
ввиду, поскольку паттерн – это шаблон, применимый в самых разных ситуациях.
Результаты - это следствия применения паттерна и разного рода компромиссы.
Хотя при описании проектных решений о последствиях часто не упоминают, знать
о них необходимо, чтобы можно было выбрать между различными вариантами и
оценить преимущества и недостатки данного паттерна.
http://www.slideshare.net/IgorShkulipa 16
Паттерны (шаблоны проектирования)
Паттерн описывает задачу, которая снова и снова возникает в работе, а так же
принцип ее решения, причем таким образом, что это решение можно потом
использовать много раз, ничего не изобретая заново.
В общем случае паттерн состоит из четырех основных элементов:
Имя. Присваивание паттернам имен позволяет проектировать на более высоком
уровне абстракции. С помощью имен паттернов можно вести общение с
коллегами. Назначение паттернам имен упрощает общение в профессиональной
среде.
Задача - это описание того, когда следует применять паттерн. Необходимо
сформулировать задачу и ее контекст. Может описываться конкретная проблема
проектирования, например способ представления алгоритмов в виде объектов.
Так же задача может включать перечень условий, при выполнении которых имеет
смысл применять данный паттерн.
Решение представляет собой описание элементов дизайна, отношений между
ними, функций каждого элемента. Конкретный дизайн или реализация не имеются
ввиду, поскольку паттерн – это шаблон, применимый в самых разных ситуациях.
Результаты - это следствия применения паттерна и разного рода компромиссы.
Хотя при описании проектных решений о последствиях часто не упоминают, знать
о них необходимо, чтобы можно было выбрать между различными вариантами и
оценить преимущества и недостатки данного паттерна.
http://www.slideshare.net/IgorShkulipa 17
Классификация паттернов
Паттерны проектирования программных систем делятся на
следующие категории:
Архитектурные паттерны. Описывают структурную схему
программной системы в целом. В данной схеме указываются
отдельные функциональные составляющие системы,
называемые подсистемами, а также взаимоотношения между
ними.
Паттерны проектирования. описывают схемы детализации
программных подсистем и отношений между ними, при этом они
не влияют на структуру программной системы в целом и
сохраняют независимость от реализации языка
программирования.
Идиомы - низкоуровневые паттерны, имеют дело с вопросами
реализации какой-либо проблемы с учетом особенностей
данного языка программирования.
http://www.slideshare.net/IgorShkulipa 18
Паттерны проектирования
Паттерны проектирования делятся на следующие категории:
Порождающие - шаблоны проектирования, которые
абстрагируют процесс создания объектов. Они позволяют
сделать систему независимой от способа создания, композиции
и представления объектов.
Структурные - шаблоны проектирования, в которых
рассматривается вопрос о том, как из классов и объектов
образуются более крупные структуры.
Поведенческие - шаблоны проектирования, определяющие
алгоритмы и способы реализации взаимодействия различных
объектов и классов.
http://www.slideshare.net/IgorShkulipa 19
Порождающие паттерны
• Singleton (Одиночка) - контролирует создание единственного
экземпляра некоторого класса и предоставляет доступ к нему.
• Factory Method (Фабричный метод) - В его классическом варианте
вводится полиморфный класс Factory, в котором определяется
интерфейс фабричного метода, а ответственность за создание объектов
конкретных классов переносится на производные от Factory классы, в
которых этот метод переопределяется.
• Abstract Factory (Абстрактная фабрика) - использует несколько
фабричных методов и предназначен для создания целого семейства или
группы взаимосвязанных объектов.
• Builder (Строитель) - определяет процесс поэтапного конструирования
сложного объекта, в результате которого могут получаться разные
представления этого объекта.
• Prototype (Прототип) - создает новые объекты с помощью прототипов.
Прототип - некоторый объект, умеющий создавать по запросу копию
самого себя.
• Object Pool (Пул объектов) - используется в случае, когда создание
объекта требует больших затрат или может быть создано только
ограниченное количество объектов некоторого класса.
http://www.slideshare.net/IgorShkulipa 20
Шаблон проектирования Singleton
public class Singleton
{
public static Singleton Instance
{
get
{
if (instance == null) instance = new Singleton();
return instance;
}
}
public void Method1() { Console.WriteLine("Singleton.Method1"); }
public void Method2() { Console.WriteLine("Singleton.Method2"); }
private Singleton() { }
private static Singleton instance;
}
class Program
{
static void Main(string[] args)
{
Singleton.Instance.Method1();
Singleton.Instance.Method2();
}
}
http://www.slideshare.net/IgorShkulipa 21
Применение Singleton
Применяется, когда нужен только один экземпляр класса.
Например для хранения глобальной конфигурации системы,
для ведения логов, связи с базой данных и т.д.
Основное преимущество перед глобальными переменными в
том, что экземпляр класса создается не при инициализации
программы, а по первому требованию.
http://www.slideshare.net/IgorShkulipa 22
Factory Method
Паттерн Factory Method может быть полезным в решении
следующих задач:
1. Система должна оставаться расширяемой путем добавления
объектов новых типов. Непосредственное использование
оператора new является нежелательным, так как в этом
случае код создания объектов с указанием конкретных типов
может получиться разбросанным по всему приложению. Тогда
такие операции как добавление в систему объектов новых
типов или замена объектов одного типа на другой будут
затруднительными. Паттерн Factory Method позволяет системе
оставаться независимой как от самого процесса порождения
объектов, так и от их типов.
2. Заранее известно, когда нужно создавать объект, но
неизвестен его тип.
http://www.slideshare.net/IgorShkulipa 23
Описание паттерна Factory Method
Для того, чтобы система оставалась независимой от различных типов
объектов, паттерн Factory Method использует механизм полиморфизма -
классы всех конечных типов наследуются от одного абстрактного
базового класса, предназначенного для полиморфного использования. В
этом базовом классе определяется единый интерфейс, через который
пользователь будет оперировать объектами конечных типов.
Для обеспечения относительно простого добавления в систему новых типов
паттерн Factory Method локализует создание объектов конкретных типов в
специальном классе-фабрике. Методы этого класса, посредством которых
создаются объекты конкретных классов, называются фабричными.
Существуют две разновидности паттерна Factory Method:
Обобщенный конструктор, когда в том же самом полиморфном базовом
классе, от которого наследуются производные классы всех создаваемых в
системе типов, определяется статический фабричный метод. В качестве
параметра в этот метод должен передаваться идентификатор типа
создаваемого объекта.
Классический вариант фабричного метода, когда интерфейс фабричных
методов объявляется в независимом классе-фабрике, а их реализация
определяется конкретными подклассами этого класса.
http://www.slideshare.net/IgorShkulipa 24
Классическая реализация Factory Method. Классы-
результаты фабрики
public abstract class BaseClass
{
public abstract string GetName();
}
public class DerivedClass1 : BaseClass
{
public override string GetName()
{
return "Derived Class 1";
}
}
public class DerivedClass2 : BaseClass
{
public override string GetName()
{
return "Derived Class 2";
}
}
http://www.slideshare.net/IgorShkulipa 25
Классическая реализация Factory Method. Классы
фабрик
public abstract class Factory
{
public abstract BaseClass FactoryMethod();
}
class Factory1 : Factory
{
public override BaseClass FactoryMethod()
{
return new DerivedClass1();
}
}
class Factory2 : Factory
{
public override BaseClass FactoryMethod()
{
return new DerivedClass2();
}
}
http://www.slideshare.net/IgorShkulipa 26
Классическая реализация Factory Method.
Использование
class Program
{
static void Main(string[] args)
{
Factory1 fact1 = new Factory1();
Factory2 fact2 = new Factory2();
Factory[] factories = { fact1, fact2 };
for (int i = 0; i < factories.Length; i++)
{
BaseClass bc = factories[i].FactoryMethod();
Console.WriteLine(
"Type={0}, Object={1}",
bc.GetType().ToString(), bc.GetName());
}
Console.ReadKey();
}
} Type=HelloWorld.DerivedClass1, Object=Derived Class 1
Type=HelloWorld.DerivedClass2, Object=Derived Class 2
http://www.slideshare.net/IgorShkulipa 27
Преимущества и недостатки
Преимущества паттерна Factory Method:
–Создает объекты разных типов, позволяя системе оставаться
независимой как от самого процесса создания, так и от типов
создаваемых объектов.
Недостатки паттерна Factory Method:
–В случае классического варианта паттерна даже для
порождения единственного объекта необходимо создавать
соответствующую фабрику
http://www.slideshare.net/IgorShkulipa 28
Abstract Factory
Паттерн Abstract Factory стоит использовать, когда:
–Система должна оставаться независимой как от процесса
создания новых объектов, так и от типов порождаемых
объектов. Непосредственное использование оператора new в
коде приложения нежелательно.
–Необходимо создавать группы или семейства
взаимосвязанных объектов, исключая возможность
одновременного использования объектов из разных семейств
в одном контексте.
http://www.slideshare.net/IgorShkulipa 29
Классы для 1-й фабрики
public abstract class BaseClass1
{
public abstract string GetName();
}
public class DerivedClass11 : BaseClass1
{
public override string GetName()
{
return "Derived Class 11";
}
}
public class DerivedClass21 : BaseClass1
{
public override string GetName()
{
return "Derived Class 21";
}
}
http://www.slideshare.net/IgorShkulipa 30
Классы для 2-й фабрики
public abstract class BaseClass2
{
public abstract string GetName();
}
public class DerivedClass12 : BaseClass2
{
public override string GetName()
{
return "Derived Class 12";
}
}
public class DerivedClass22 : BaseClass2
{
public override string GetName()
{
return "Derived Class 22";
}
}
http://www.slideshare.net/IgorShkulipa 31
Классы фабрик
public abstract class AbstractFactory
{
public abstract BaseClass1 FactoryMethod1();
public abstract BaseClass2 FactoryMethod2();
}
class AbstractFactory1 : AbstractFactory {
public override BaseClass1 FactoryMethod1() {
return new DerivedClass11();
}
public override BaseClass2 FactoryMethod2() {
return new DerivedClass12();
}
}
class AbstractFactory2 : AbstractFactory {
public override BaseClass1 FactoryMethod1() {
return new DerivedClass21();
}
public override BaseClass2 FactoryMethod2() {
return new DerivedClass22();
}
}
http://www.slideshare.net/IgorShkulipa 32
Использование
class Program
{
static void UseAbstractFactory(AbstractFactory af)
{
BaseClass1 bc1 = af.FactoryMethod1();
BaseClass2 bc2 = af.FactoryMethod2();
Console.WriteLine(bc1.GetName());
Console.WriteLine(bc2.GetName());
}
static void Main(string[] args)
{
AbstractFactory af1 = new AbstractFactory1();
AbstractFactory af2 = new AbstractFactory2();
UseAbstractFactory(af1);
UseAbstractFactory(af2);
Console.ReadKey();
}
}
Derived Class 11
Derived Class 12
Derived Class 21
Derived Class 22
http://www.slideshare.net/IgorShkulipa 33
Паттерн «Прототип»
Использует для создания новых объектов копию самого себя.
Паттерн Prototype (прототип) можно использовать в следующих
случаях:
–Система должна оставаться независимой как от процесса
создания новых объектов, так и от типов порождаемых
объектов. Непосредственное использование оператора new в
коде приложения считается нежелательным.
–Необходимо создавать объекты, точные классы которых
становятся известными уже на стадии выполнения
программы.
http://www.slideshare.net/IgorShkulipa 34
Интерфейс ICloneable
Поддерживает копирование, при котором создается новый экземпляр
класса с тем же значением, что и у существующего экземпляра.
Метод Clone() создает новый объект, являющийся копией текущего
экземпляра.
Метод MemberwiseClone для создания неполной копии создает новый
объект, а затем копирует в него нестатические поля текущего объекта.
Если поле относится к типу значения, выполняется побитовое
копирование полей. Если поле относится к ссылочному типу,
копируются ссылки, а не объекты, на которые они указывают;
следовательно, ссылки в исходном объекте и его клоне указывают на
один и тот же объект.
http://www.slideshare.net/IgorShkulipa 35
Пример
class DeepStructure {
public int A { get; set; }
public int B { get; set; }
}
class CloneClass {
public int X { get; set; }
public int Y { get; set; }
public DeepStructure ds;
public CloneClass()
{
ds = new DeepStructure();
}
public override string ToString()
{
return
X.ToString() + " " +
Y.ToString() + " " +
ds.A.ToString() + " " +
ds.B.ToString() + " " +
ds.GetHashCode();
}
}
class ShallowCloneClass :
CloneClass, ICloneable
{
public object Clone()
{
return
(ShallowCloneClass)this.MemberwiseClone();
}
}
class DeepCloneClass :
CloneClass, ICloneable
{
public object Clone()
{
DeepCloneClass result =
new DeepCloneClass();
result.X = this.X;
result.Y = this.Y;
result.ds = new DeepStructure();
result.ds.A = this.ds.A;
result.ds.B = this.ds.B;
return result; ;
}
}
http://www.slideshare.net/IgorShkulipa 36
Использование
3
class Program
{
static void Main(string[] args)
{
ShallowCloneClass sc1 = new ShallowCloneClass();
sc1.X = 1; sc1.Y = 2; sc1.ds.A = 3; sc1.ds.B = 4;
ShallowCloneClass sc2 = (ShallowCloneClass)sc1.Clone();
Console.WriteLine(sc1.ToString());
Console.WriteLine(sc2.ToString());
DeepCloneClass dc1 = new DeepCloneClass();
dc1.X = 1; dc1.Y = 2; dc1.ds.A = 3; dc1.ds.B = 4;
DeepCloneClass dc2 = (DeepCloneClass)dc1.Clone();
Console.WriteLine(dc1.ToString());
Console.WriteLine(dc2.ToString());
Console.ReadKey();
}
}
1 2 3 4 27226607
1 2 3 4 27226607
1 2 3 4 42549079
1 2 3 4 66790640
http://www.slideshare.net/IgorShkulipa 37
Паттерн Builder
Паттерн Builder может помочь в решении следующих задач:
–В системе могут существовать сложные объекты, создание
которых за одну операцию затруднительно или невозможно.
Требуется поэтапное построение объектов с контролем
результатов выполнения каждого этапа.
–Данные должны иметь несколько представлений. Например,
если есть некоторый исходный документ в формате RTF (Rich
Text Format), в общем случае содержащий текст,
графические изображения и служебную информацию о
форматировании (размер и тип шрифтов, отступы и др.).
Если этот документ в формате RTF преобразовать в другие
форматы (например, Microsoft Word или простой ASCII-текст),
то полученные документы и будут представлениями
исходных данных.
http://www.slideshare.net/IgorShkulipa 38
Описание паттерна Builder
Паттерн Builder отделяет алгоритм поэтапного конструирования
сложного объекта от его внешнего представления так, что с
помощью одного и того же алгоритма можно получать разные
представления этого объекта.
Для этого паттерн Builder определяет алгоритм поэтапного
создания продукта в специальном классе Director
(распорядитель), а ответственность за координацию процесса
сборки отдельных частей продукта возлагает на иерархию
классов Builder. В этой иерархии базовый класс Builder
объявляет интерфейс для построения отдельных частей
продукта, а соответствующие подклассы конкретных
строителей их реализуют подходящим образом, например,
создают или получают нужные ресурсы, сохраняют
промежуточные результаты, контролируют результаты
выполнения операций.
http://www.slideshare.net/IgorShkulipa 39
Реализация паттерна Builder. Класс Computer
class Computer
{
public string Name { get; set; }
public string CPU { get; set; }
public string RAM { get; set; }
public string HDD { get; set; }
public string VGA { get; set; }
public void Print()
{
Console.Write(
"{0}: {1}/{2}/{3}/{4}n",
Name, CPU, RAM, HDD, VGA);
}
}
http://www.slideshare.net/IgorShkulipa 40
Классы-строители
interface ICompBuilder {
Computer Build();
}
class GameCompBuilder : ICompBuilder {
private Computer computer;
public GameCompBuilder() { computer = new Computer(); }
Computer ICompBuilder.Build() {
computer.Name = "Game Computer";
computer.CPU = "Core i7 3.0 GHz";
computer.RAM = "8 Gb";
computer.HDD = "1 Tb";
computer.VGA = "GeForce GTX 560";
return computer;
} }
class OfficeCompBuilder : ICompBuilder {
private Computer computer;
public OfficeCompBuilder() { computer = new Computer(); }
Computer ICompBuilder.Build() {
computer.Name = "Office Computer";
computer.CPU = "Core i3 3.0 GHz";
computer.RAM = "2 Gb";
computer.HDD = "500 Gb";
computer.VGA = "Intel GMA 4000";
return computer;
} }
http://www.slideshare.net/IgorShkulipa 41
Класс-директор
class Director
{
private ICompBuilder builder;
public Director() { }
public void SetBuilder(ICompBuilder builder)
{
this.builder = builder;
}
public Computer GetComp()
{
return builder.Build();
}
}
http://www.slideshare.net/IgorShkulipa 42
Использование строителей
class Program
{
static void Main(string[] args)
{
Director director = new Director();
//Building Game Computer
director.SetBuilder(new GameCompBuilder());
Computer comp = director.GetComp();
comp.Print();
//Building Office Computer
director.SetBuilder(new OfficeCompBuilder());
comp = director.GetComp();
comp.Print();
Console.ReadKey();
}
}
Game Computer: Core i7 3.2 GHz/16 Gb/1 Tb/GeForce GTX 960
Office Computer: Core i3 3.0 GHz/2 Gb/500 Gb/Intel GMA 5000
http://www.slideshare.net/IgorShkulipa 43
StringBuilder
Предоставляет изменяемую строку символов.
[SerializableAttribute]
[ComVisibleAttribute(true)]
public sealed class StringBuilder : ISerializable
Операция объединения объекта String всегда создает новый объект из
существующей строки и новых данных. Объект StringBuilder
поддерживает буфер для размещения и конкатенации новых данных.
Новые данные добавляются в имеющийся буфер только в том случае,
если в нем имеется достаточное свободное пространство для их
размещения, в противном случае выделяется новый буфер
достаточного размера, данные из оригинального буфера копируются в
другой буфер, и новые данные добавляются уже в новый буфер.
http://www.slideshare.net/IgorShkulipa 44
Пример
class Program
{
static void Main(string[] args)
{
string strText1 = "Hello" + "," + " " + "World" + "!";
string strText2 = "";
StringBuilder strBuilder = new StringBuilder(strText2);
strBuilder.Append("Hello");
strBuilder.Append(",");
strBuilder.Append(" ");
strBuilder.Append("World");
strBuilder.Append("!");
strText2 = strBuilder.ToString();
Console.WriteLine(strText1);
Console.WriteLine(strText2);
Console.ReadKey();
}
}
Hello, World!
Hello, World!
http://www.slideshare.net/IgorShkulipa 45
Object Pool
Применение паттерна Object Pool может значительно повысить
производительность системы; его использование наиболее
эффективно в ситуациях, когда создание экземпляров
некоторого класса требует больших затрат, объекты в системе
создаются часто, но число создаваемых объектов в единицу
времени ограничено.
Пулы объектов (известны также как пулы ресурсов)
используются для управления кэшированием объектов. Клиент,
имеющий доступ к пулу объектов может избежать создания
новых объектов, просто запрашивая в пуле уже созданный
экземпляр. Пул объектов может быть растущим, когда при
отсутствии свободных создаются новые объекты или c
ограничением количества создаваемых объектов.
http://www.slideshare.net/IgorShkulipa 46
Реализация Object Pool на основе Singleton. Классы
объектов
abstract class IObject {
protected string Text;
public virtual void Print() {
Console.WriteLine("The Object is: {0}", Text);
}
}
class Object1 : IObject {
public Object1() {
Text = "Object 1";
}
}
class Object2 : IObject {
public Object2() {
Text = "Object 2";
}
}
class Object3 : IObject {
public Object3() {
Text = "Object 3";
}
}
class Object4 : IObject {
public Object4() {
Text = "Object 4";
}
}
http://www.slideshare.net/IgorShkulipa 47
Object Pool
class ObjectPool {
public static ObjectPool GetInstance(int size) {
if (instance == null) instance =
new ObjectPool(size);
return instance;
}
public IObject GetObject() {
for (int i = 0; i < poolSize; i++) {
if (!busyObjects[i]) {
busyObjects[i] = true;
return objectPool[i];
}
}
return null;
}
public void ReleaseObject(IObject obj) {
for (int i = 0; i < poolSize; i++) {
if (objectPool[i] == obj) {
busyObjects[i] = false;
}
}
}...
http://www.slideshare.net/IgorShkulipa 48
Object Pool
private ObjectPool(int size) {
poolSize = size; objectPool = new IObject[poolSize];
busyObjects = new bool[poolSize]; Random rand = new Random(1000);
for (int i = 0; i < poolSize; i++) {
int iObjNumber = rand.Next()%4;
switch (iObjNumber) {
case 0: objectPool[i] = new Object1(); busyObjects[i] = false;
break;
case 1: objectPool[i] = new Object2(); busyObjects[i] = false;
break;
case 2: objectPool[i] = new Object3(); busyObjects[i] = false;
break;
case 3: objectPool[i] = new Object4(); busyObjects[i] = false;
break;
}
busyObjects[i] = false;
}
}
private IObject[] objectPool; private int poolSize;
private bool[] busyObjects; private static ObjectPool instance;
}
http://www.slideshare.net/IgorShkulipa 49
Использование Object Pool
class Program {
static void Main(string[] args) {
ObjectPool op = ObjectPool.GetInstance(5);
IObject object1 = op.GetObject();
if (object1 != null) object1.Print(); else Console.WriteLine("The Object is: NULL");
IObject object2 = op.GetObject();
if (object2 != null) object2.Print(); else Console.WriteLine("The Object is: NULL");
IObject object3 = op.GetObject();
if (object3 != null) object3.Print(); else Console.WriteLine("The Object is: NULL");
IObject object4 = op.GetObject();
if (object4 != null) object4.Print(); else Console.WriteLine("The Object is: NULL");
IObject object5 = op.GetObject();
if (object5 != null) object5.Print(); else Console.WriteLine("The Object is: NULL");
IObject object6 = op.GetObject();
if (object6 != null) object6.Print(); else Console.WriteLine("The Object is: NULL");
IObject object7 = op.GetObject();
if (object7 != null) object7.Print(); else Console.WriteLine("The Object is: NULL");
op.ReleaseObject(object2);
IObject object8 = op.GetObject();
if (object8 != null) object8.Print(); else Console.WriteLine("The Object is: NULL");
Console.ReadKey();
}
}
http://www.slideshare.net/IgorShkulipa 50
Результат
The Object is: Object 2
The Object is: Object 4
The Object is: Object 3
The Object is: Object 1
The Object is: Object 2
The Object is: NULL
The Object is: NULL
The Object is: Object 4
http://www.slideshare.net/IgorShkulipa 51
Структурные шаблоны проектирования
–Adapter представляет собой программную обертку над уже
существующими классами и предназначен для преобразования их
интерфейсов к виду, пригодному для последующего использования в
новом программном проекте.
–Bridge отделяет абстракцию от реализации так, что то и другое
можно изменять независимо.
–Composite группирует схожие объекты в древовидные структуры.
Рассматривает единообразно простые и сложные объекты.
–Decorator используется для расширения функциональности
объектов. Являясь гибкой альтернативой порождению классов,
паттерн Decorator динамически добавляет объекту новые
обязанности.
–Facade предоставляет высокоуровневый унифицированный
интерфейс к набору интерфейсов некоторой подсистемы, что
облегчает ее использование.
–Flyweight использует разделение для эффективной поддержки
множества объектов.
–Proxy замещает другой объект для контроля доступа к нему.
http://www.slideshare.net/IgorShkulipa 52
Адаптер
Паттерн Adapter, представляет собой программную обертку над
существующими классами, преобразуя их интерфейсы к виду,
пригодному для последующего использования.
Пусть класс, интерфейс которого нужно адаптировать к нужному
виду, имеет имя Adaptee. Для решения задачи преобразования
его интерфейса паттерн Adapter вводит следующую иерархию
классов:
–Виртуальный базовый класс Target. Здесь объявляется
пользовательский интерфейс подходящего вида. Только этот
интерфейс доступен для пользователя.
–Производный класс Adapter, реализующий интерфейс Target.
В этом классе также имеется указатель или ссылка на
экземпляр Adaptee. Паттерн Adapter использует этот
указатель для перенаправления клиентских вызовов в
Adaptee. Так как интерфейсы Adaptee и Target несовместимы
между собой, то эти вызовы обычно требуют
преобразования.
http://www.slideshare.net/IgorShkulipa 53
Пример. Преобразование строки в структуру
class InputStringFullName
{
public string Text { get; set; }
public InputStringFullName()
{
Text = "";
}
public void Input()
{
Console.Write
("Input Full Name (Surname Name MiddleName): ");
Text = Console.ReadLine();
}
}
http://www.slideshare.net/IgorShkulipa 54
Класс структуры
class FullName
{
public string Name { get; set; }
public string Surname { get; set; }
public string Middle { get; set; }
public FullName(string surname, string name, string middle)
{
Name = name; Surname = surname; Middle = middle;
}
public void Print()
{
Console.WriteLine(Name);
Console.WriteLine(Middle);
Console.WriteLine(Surname);
}
}
http://www.slideshare.net/IgorShkulipa 55
Класс-адаптер
class FullNameAdapter : InputStringFullName
{
public FullNameAdapter(InputStringFullName stringFullName)
{
Text = stringFullName.Text;
}
public FullName GetFullName()
{
int iFirstSpace = Text.IndexOf(' ');
string strSurname = Text.Substring(0, iFirstSpace);
int iSecondSpace =
Text.Substring(iFirstSpace + 1).IndexOf(' ') + iFirstSpace + 1;
string strName =
Text.Substring(iFirstSpace, iSecondSpace - iFirstSpace);
string strMiddle = Text.Substring(iSecondSpace);
return new FullName(strSurname, strName, strMiddle);
}
}
http://www.slideshare.net/IgorShkulipa 56
Использование адаптера
class Program
{
static void Main(string[] args)
{
InputStringFullName isfn = new InputStringFullName();
isfn.Input();
FullNameAdapter fna = new FullNameAdapter(isfn);
FullName fn = fna.GetFullName();
fn.Print();
Console.ReadKey();
}
}
Результат:
Input Full Name (Surname Name MiddleName): Ivanov Ivan Ivanovich
Ivan
Ivanovich
Ivanov
http://www.slideshare.net/IgorShkulipa 57
Паттерн проектирования «Мост»
Используется для того, чтобы разделять абстракцию и реализацию так,
чтобы они могли изменяться независимо.
http://www.slideshare.net/IgorShkulipa 58
Реализация. Классы реализаторов с общим
интерфейсом
public interface Iimplementor {
void Operation();
}
class Implementor1 : Iimplementor {
void IImplementor.Operation() {
Console.WriteLine("Implementor 1");
}
}
class Implementor2 : Iimplementor {
void IImplementor.Operation() {
Console.WriteLine("Implementor 2");
}
}
http://www.slideshare.net/IgorShkulipa 59
Класс-абстракция
class Abstraction
{
protected IImplementor implementor;
public Abstraction() { }
public void SetImplementor(IImplementor implementor)
{
this.implementor = implementor;
}
public void Operation()
{
implementor.Operation();
}
}
http://www.slideshare.net/IgorShkulipa 60
Использование моста
class Program
{
static void Main(string[] args)
{
Abstraction abstr = new Abstraction();
abstr.SetImplementor(new Implementor1());
abstr.Operation();
abstr.SetImplementor(new Implementor2());
abstr.Operation();
Console.ReadKey();
}
}
Результат:
Implementor 1
Implementor 2
http://www.slideshare.net/IgorShkulipa 61
Шаблоны поведения
Паттерн Chain of Responsibility позволяет обработать запрос
нескольким объектам-получателям. Получатели связываются в цепочку,
и запрос передается по цепочке, пока не будет обработан каким-то
объектом. Паттерн Chain of Responsibility позволяет также избежать
жесткой зависимости между отправителем запроса и его получателями.
Паттерн Command преобразовывает запрос на выполнение действия в
отдельный объект-команду. Это придает системе гибкость: позволяет
осуществлять динамическую замену команд, использовать сложные
составные команды, осуществлять отмену операций.
Паттерн Iterator предоставляет механизм обхода элементов составных
объектов (коллекций) не раскрывая их внутреннего представления.
Паттерн Interpreter предназначен для решения повторяющихся задач,
которые можно описать некоторым языком. Для этого паттерн
Interpreter описывает решаемую задачу в виде предложений этого
языка, а затем интерпретирует их.
Паттерн Mediator инкапсулирует взаимодействие совокупности
объектов в отдельный объект-посредник. Уменьшает степень
связанности взаимодействующих объектов - им не нужно хранить
ссылки друг на друга.
http://www.slideshare.net/IgorShkulipa 62
Шаблоны поведения
Паттерн Memento получает и сохраняет за пределами объекта его
внутреннее состояние так, чтобы позже можно было восстановить
объект в таком же состоянии.
Паттерн Observer определяет зависимость "один-ко-многим" между
объектами так, что при изменении состояния одного объекта все
зависящие от него объекты уведомляются и обновляются
автоматически.
Паттерн State позволяет объекту изменять свое поведение в
зависимости от внутреннего состояния. Создается впечатление, что
объект изменил свой класс. Паттерн State является объектно-
ориентированной реализацией конечного автомата.
Если поведение системы настраивается согласно одному из некоторого
множества алгоритму, то применение паттерна Strategy переносит
семейство алгоритмов в отдельную иерархию классов, что позволяет
заменять один алгоритм другим в ходе выполнения программы. Кроме
того, такую систему проще расширять и поддерживать.
Паттерн Template Method определяет основу алгоритма и позволяет
подклассам изменить некоторые шаги этого алгоритма без изменения
его общей структуры.
Паттерн Visitor определяет операцию, выполняемую на каждом
элементе из некоторой структуры без изменения классов этих объектов.
http://www.slideshare.net/IgorShkulipa 63
Паттерн Chain of Responsibility
Паттерн Chain of Responsibility позволяет избежать жесткой
зависимости отправителя запроса от его получателя, при этом
запрос может быть обработан несколькими объектами.
Объекты-получатели связываются в цепочку. Запрос
передается по этой цепочке, пока не будет обработан.
Вводит конвейерную обработку для запроса с множеством
возможных обработчиков.
Объектно-ориентированный связанный список с рекурсивным
обходом.
http://www.slideshare.net/IgorShkulipa 64
Общая схема паттерна
Клиент
Обработчик 1
Обработчик 2
Обработчик 3
Обработчик ...
Обработчик n
http://www.slideshare.net/IgorShkulipa 65
Реализация цепочки. Классы событий
public abstract class IEvent{
public string EventType { get; set; }
}
class Event1 : IEvent {
public Event1() { EventType = "Event1"; }
}
class Event2 : IEvent {
public Event2() { EventType = "Event2"; }
}
class Event3 : IEvent {
public Event3() { EventType = "Event3"; }
}
class Event4 : IEvent {
public Event4() { EventType = "Event4"; }
}
class Event5 : IEvent {
public Event5() { EventType = "Event5"; }
}
class Event6 : IEvent {
public Event6() { EventType = "Event6"; }
}
http://www.slideshare.net/IgorShkulipa 66
Базовый класс-обработчик
public abstract class BaseHandler {
public BaseHandler() { Next = null; }
public virtual void Handle(IEvent ev) {
if (PrivateEvent.EventType == ev.EventType)
{
Console.WriteLine("{0} successfully handled", PrivateEvent.EventType);
} else {
Console.WriteLine("Sending event to next Handler...");
if (Next != null)
Next.Handle(ev);
else
Console.WriteLine("Unknown event. Can't handle.");
}
}
protected void SetNextHandler(BaseHandler newHandler) {
Next = newHandler;
}
protected BaseHandler Next { get; set; }
protected IEvent PrivateEvent { get; set; }
}
http://www.slideshare.net/IgorShkulipa 67
Классы-обработчики
class Handler5 : BaseHandler {
public Handler5() {
PrivateEvent = new Event5(); Next = null;
} }
class Handler4 : BaseHandler {
public Handler4() {
PrivateEvent = new Event4(); Next = new Handler5();
} }
class Handler3 : BaseHandler {
public Handler3() {
PrivateEvent = new Event3(); Next = new Handler4();
} }
class Handler2 : BaseHandler {
public Handler2() {
PrivateEvent = new Event2(); Next = new Handler3();
} }
class Handler1 : BaseHandler {
public Handler1() {
PrivateEvent = new Event1(); Next = new Handler2();
} }
http://www.slideshare.net/IgorShkulipa 68
Класс тестового приложения
public class ChainApplication {
public ChainApplication() {
eventHandler = new Handler1(); Rand = new Random();
}
public void Run(int EventCount) {
for (int i = 0; i < EventCount; i++) {
HandleEvent(GenerateRandomEvent());
} }
private void HandleEvent(IEvent ev) {
eventHandler.Handle(ev);
}
private IEvent GenerateRandomEvent() {
IEvent result;
switch (Rand.Next(1,6)) {
case 0: result = new Event1(); break; case 1: result = new Event2(); break;
case 2: result = new Event3(); break; case 3: result = new Event4(); break;
case 4: result = new Event5(); break; default: result = new Event6(); break; }
Console.WriteLine("Generated event: {0}", result.EventType);
return result; }
private BaseHandler eventHandler;
private Random Rand;
}
http://www.slideshare.net/IgorShkulipa 69
Результат цепочки ответственностей
class Program
{
static void Main(string[] args)
{
ChainApplication app = new ChainApplication();
app.Run(3);
Console.ReadKey();
}
}
Результат:
Generated event: Event4
Sending event to next Handler...
Sending event to next Handler...
Sending event to next Handler...
Event4 successfully handled
Generated event: Event6
Sending event to next Handler...
Sending event to next Handler...
Sending event to next Handler...
Sending event to next Handler...
Sending event to next Handler...
Unknown event. Can't handle.
Generated event: Event5
Sending event to next Handler...
Sending event to next Handler...
Sending event to next Handler...
Sending event to next Handler...
Event5 successfully handled
http://www.slideshare.net/IgorShkulipa 70
Команда
Паттерн Command преобразовывает запрос на выполнение
действия в отдельный объект-команду. Такая инкапсуляция
позволяет передавать эти действия другим функциям и
объектам в качестве параметра, приказывая им выполнить
запрошенную операцию. Команда – это объект, поэтому над
ней допустимы любые операции, что и над объектом.
Команда используется, если:
–Система управляется событиями. При появлении такого
события (запроса) необходимо выполнить определенную
последовательность действий.
–Необходимо параметризировать объекты выполняемым
действием, ставить запросы в очередь или поддерживать
операции отмены и повтора действий.
–Нужен объектно-ориентированный аналог функции
обратного вызова в процедурном программировании.
http://www.slideshare.net/IgorShkulipa 71
Пример. Интерфейс «Игра»
public interface IGame
{
void New();
void Start();
void Pause();
void Resume();
void Finish();
void Break();
void BreakAndFinish();
void BreakAndStart();
}
http://www.slideshare.net/IgorShkulipa 72
Реализация интерфейса
public class SomeGame : Igame {
void IGame.New() {
Console.WriteLine("New Game."); }
void IGame.Start() {
Console.WriteLine("Game Started."); }
void IGame.Pause() {
Console.WriteLine("Game Paused."); }
void IGame.Resume() {
Console.WriteLine("Game Resumed."); }
void IGame.Finish() {
Console.WriteLine("Game Finished."); }
void IGame.Break() {
Console.WriteLine("Game Breaked."); }
void IGame.BreakAndFinish() {
Console.WriteLine("Game Breaked.");
Console.WriteLine("Game Finished."); }
void IGame.BreakAndStart() {
Console.WriteLine("Game Breaked.");
Console.WriteLine("New Game.");
Console.WriteLine("Game Started."); }
}
http://www.slideshare.net/IgorShkulipa 73
Классы команд
public class Icommand {
public ICommand(IGame game) { Game = game; }
public virtual void ExecuteCommand() { }
public IGame Game { get; set; }
}
class NewCommand : Icommand {
public NewCommand(IGame game) : base(game) { }
public override void ExecuteCommand()
{
Console.WriteLine("Executing New Command...");
Game.New();
}
}
class StartCommand : Icommand {
public StartCommand(IGame game) : base(game) { }
public override void ExecuteCommand()
{
Console.WriteLine("Executing Start Command...");
Game.Start();
}
}
http://www.slideshare.net/IgorShkulipa 74
Классы команд
class PauseCommand : ICommand{
public PauseCommand(IGame game) : base(game) { }
public override void ExecuteCommand() {
Console.WriteLine("Executing Pause Command...");
Game.Pause();
}
}
class ResumeCommand : ICommand{
public ResumeCommand(IGame game) : base(game) { }
public override void ExecuteCommand() {
Console.WriteLine("Executing Resume Command...");
Game.Resume();
}
}
class FinishCommand : ICommand{
public FinishCommand(IGame game) : base(game) { }
public override void ExecuteCommand() {
Console.WriteLine("Executing Finish Command...");
Game.Finish();
}
}
http://www.slideshare.net/IgorShkulipa 75
Классы команд
class BreakCommand : ICommand{
public BreakCommand(IGame game) : base(game) { }
public override void ExecuteCommand() {
Console.WriteLine("Executing Break Command...");
Game.Break();
}
}
class BreakAndFinishCommand : ICommand{
public BreakAndFinishCommand(IGame game) : base(game) { }
public override void ExecuteCommand() {
Console.WriteLine("Executing Break And Finish Command...");
Game.BreakAndFinish();
}
}
class BreakAndStartCommand : ICommand{
public BreakAndStartCommand(IGame game) : base(game) { }
public override void ExecuteCommand() {
Console.WriteLine("Executing Break And Start Command...");
Game.BreakAndStart();
}
}
http://www.slideshare.net/IgorShkulipa 76
Использование команд
class Program
{
static void Main(string[] args)
{
IGame someGame = new SomeGame();
ICommand[] commands = new ICommand[10];
commands[0] = new NewCommand(someGame);
commands[1] = new StartCommand(someGame);
commands[2] = new BreakCommand(someGame);
commands[3] = new NewCommand(someGame);
commands[4] = new StartCommand(someGame);
commands[5] = new BreakAndStartCommand(someGame);
commands[6] = new PauseCommand(someGame);
commands[7] = new ResumeCommand(someGame);
commands[8] = new PauseCommand(someGame);
commands[9] = new BreakAndFinishCommand(someGame);
for (int i = 0; i < 10; i++)
{
commands[i].ExecuteCommand();
}
Console.ReadKey();
}
}
Результат:
Executing New Command...
New Game.
Executing Start Command...
Game Started.
Executing Break Command...
Game Breaked.
Executing New Command...
New Game.
Executing Start Command...
Game Started.
Executing Break And Start Command...
Game Breaked.
New Game.
Game Started.
Executing Pause Command...
Game Paused.
Executing Resume Command...
Game Resumed.
Executing Pause Command...
Game Paused.
Executing Break And Finish Command...
Game Breaked.
Game Finished.
http://www.slideshare.net/IgorShkulipa 77
Паттерн Iterator
Назначение паттерна Iterator
• Предоставляет способ последовательного доступа ко всем
элементам составного объекта, не раскрывая его внутреннего
представления.
• Абстракция в стандартных библиотеках C++ и Java, позволяющая
разделить классы коллекций и алгоритмов.
• Придает обходу коллекции "объектно-ориентированный статус".
• Полиморфный обход.
http://www.slideshare.net/IgorShkulipa 78
Интерфейсы
public interface IIterator
{
object Next();
object First();
bool Finished();
object Current();
}
public interface IIterCollection
{
IIterator GetIterator();
}
http://www.slideshare.net/IgorShkulipa 79
Реализация коллекции
public class IterCollection: IIterCollection
{
private ArrayList items = new ArrayList();
IIterator IIterCollection.GetIterator()
{
return new Iterator(this);
}
public object Get(int i)
{
return items[i];
}
public int GetCount()
{
return items.Count;
}
}
http://www.slideshare.net/IgorShkulipa 80
Реализация итератора
public class Iterator : IIterator
{
private IterCollection collection;
private int current;
public Iterator(IterCollection col)
{
collection = col;
current = 0;
}
object IIterator.First()
{
return collection.Get(0);
}
object IIterator.Current()
{
return collection.Get(current);
}
bool IIterator.Finished()
{
return (current >= collection.GetCount());
}
object IIterator.Next()
{
return collection.Get(current++);
}
}
http://www.slideshare.net/IgorShkulipa 81
Использование
class Program
{
static void Main(string[] args)
{
IIterCollection ic = new IterCollection(10);
IIterator iter = ic.GetIterator();
while (!iter.Finished())
{
Console.WriteLine(iter.Next());
}
Console.ReadKey();
}
}
0
7
5
2
9
9
5
0
5
9
http://www.slideshare.net/IgorShkulipa 82
Альтернативная реализация
public class SquareCollection : IEnumerable<int> {
private int[][] items;
public SquareCollection(int number) {
Random rand = new Random();
this.items = new int[number][];
for (int i = 0; i < number; i++) {
int[] item = new int[number];
for (int j = 0; j < number; j++) {
item[j] = rand.Next() % 10;
}
this.items[i] = item;
}
}
public IEnumerator<int> GetEnumerator() {
for (int i = 0; i < items.Length; i++) {
for (int j = items[i].Length - 1; j >= 0; j--) {
yield return items[i][j];
}
}
}
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
}
http://www.slideshare.net/IgorShkulipa 83
Использование
class Program
{
static void Main(string[] args)
{
SquareCollection sc = new SquareCollection(10);
foreach (var item in sc)
{
Console.WriteLine(item);
}
Console.ReadKey();
}
}
5
0
1
5
2
6
7
1
3
9
5
0
3
8
2
...
http://www.slideshare.net/IgorShkulipa 84
Паттерн Memento (Хранитель)
Назначение паттерна Memento:
• Не нарушая инкапсуляции, паттерн Memento получает и сохраняет
за пределами объекта его внутреннее состояние так, чтобы позже
можно было восстановить объект в таком же состоянии.
• Является средством для инкапсуляции "контрольных точек"
программы.
• Паттерн Memento придает операциям "Отмена" (undo) или "Откат"
(rollback) статус "полноценного объекта".
Паттерн проектирования Memento определяет трех различных
участников:
• Originator (хозяин) - объект, умеющий создавать хранителя, а
также знающий, как восстановить свое внутреннее состояние из
хранителя.
• Caretaker (смотритель) - объект, который знает, почему и когда
хозяин должен сохранять и восстанавливать себя.
• Memento (хранитель) - "ящик на замке", который пишется и
читается хозяином и за которым присматривает смотритель.
http://www.slideshare.net/IgorShkulipa 85
Класс Memento и интерфейс IOriginator
class Memento
{
public string Name { get; set; }
public string Surname { get; set; }
public string MiddleName { get; set; }
}
public interface IOriginator
{
object GetMemento();
void SetMemento(object memento);
}
http://www.slideshare.net/IgorShkulipa 86
Класс для состояние, которого надо запомнить
class FullNameClass: IOriginator
{
public string Name { get; set; }
public string Surname { get; set; }
public string MiddleName { get; set; }
public FullNameClass(string name, string surname, string middle) {
Name = name; Surname = surname; MiddleName = middle;
}
public void Print() {
Console.WriteLine("Name={0} Surname={1} Middle={2}", Name, Surname, MiddleName);
}
object IOriginator.GetMemento() {
return new Memento
{ Name = this.Name, Surname = this.Surname, MiddleName = this.MiddleName };
}
void IOriginator.SetMemento(object memento){
if (memento is Memento)
{
var mem = memento as Memento;
Name = mem.Name;
Surname = mem.Surname;
MiddleName = mem.MiddleName;
}
}
}
http://www.slideshare.net/IgorShkulipa 87
Класс «Смотритель»
public class Caretaker
{
private object memento;
public void SaveState(IOriginator originator)
{
memento = originator.GetMemento();
}
public void RestoreState(IOriginator originator)
{
originator.SetMemento(memento);
}
}
http://www.slideshare.net/IgorShkulipa 88
Использование
class Program
{
static void Main(string[] args)
{
FullNameClass fnc = new
FullNameClass("Ivan", "Ivanov", "Ivanovich");
Caretaker ct = new Caretaker();
fnc.Print();
ct.SaveState(fnc);
fnc = new FullNameClass("Petr", "Petrov", "Petrovich");
fnc.Print();
ct.RestoreState(fnc);
fnc.Print();
}
}
Name=Ivan Surname=Ivanov Middle=Ivanovich
Name=Petr Surname=Petrov Middle=Petrovich
Name=Ivan Surname=Ivanov Middle=Ivanovich
http://www.slideshare.net/IgorShkulipa 89
Паттерн «Стратегия»
Паттерн Стратегия (Strategy) предназначен для определения
семейства алгоритмов и инкапсуляции каждого из них и
обеспечения их взаимозаменяемости.
Переносит в отдельную иерархию классов все детали,
связанные с реализацией алгоритмов.
http://www.slideshare.net/IgorShkulipa 90
Пример
public abstract class IStrategy
{
public abstract void Use();
protected void WakeUp() { Console.WriteLine("Wake up."); }
protected void Shower() { Console.WriteLine("Take shower."); }
protected void Dress() { Console.WriteLine("Dress."); }
protected void GoToBusStop() { Console.WriteLine("Go to bus stop."); }
protected void Wait() { Console.WriteLine("Wait."); }
protected void Arrive() { Console.WriteLine("Arrive."); }
protected void DoWork() { Console.WriteLine("Do work."); }
protected void DoExercises() { Console.WriteLine("Do exercises."); }
protected void Walk() { Console.WriteLine("Walk."); }
protected void GoOut() { Console.WriteLine("Go out."); }
protected void GoToPark() { Console.WriteLine("Go to park."); }
}
http://www.slideshare.net/IgorShkulipa 91
Классы конкретных стратегий
class GoToWorkStrategy : Istrategy {
public override void Use()
{
WakeUp(); Shower(); Dress(); GoOut();
GoToBusStop(); Wait(); Arrive(); DoWork();
}
}
class GoWalkStrategy : Istrategy {
public override void Use()
{
GoOut(); GoToPark(); Walk();
}
}
class GoToGymStrategy : Istrategy {
public override void Use()
{
GoOut(); GoToBusStop(); Arrive(); DoExercises();
}
}
http://www.slideshare.net/IgorShkulipa 92
Клиент стратегий
public abstract class IStrategyClient
{
public abstract void UseStrategy();
public void SetStrategy(IStrategy st) { strategy = st; }
protected IStrategy strategy;
}
class StrategyClient1 : IStrategyClient
{
public StrategyClient1() { }
public override void UseStrategy()
{
strategy.Use();
}
}
http://www.slideshare.net/IgorShkulipa 93
Использование стратегий
class Program
{
static void Main(string[] args)
{
IStrategyClient stClient = new StrategyClient1();
stClient.SetStrategy(new GoToWorkStrategy());
stClient.UseStrategy();
Console.WriteLine();
stClient.SetStrategy(new GoToGymStrategy());
stClient.UseStrategy();
Console.WriteLine();
stClient.SetStrategy(new GoWalkStrategy());
stClient.UseStrategy();
Console.ReadKey();
}
}
Wake up.
Take shower.
Dress.
Go out.
Go to bus stop.
Wait.
Arrive.
Do work.
Go out.
Go to bus stop.
Arrive.
Do exercises.
Go out.
Go to park.
Walk.
http://www.slideshare.net/IgorShkulipa 94
Анонимные методы
Новый класс стратегий:
public delegate void StrategyDelegate();
public abstract class IStrategyClient
{
public abstract void UseStrategy();
public StrategyDelegate Strategy { get; set; }
}
class StrategyClient1 : IStrategyClient
{
public StrategyClient1() { }
public override void UseStrategy()
{
Strategy();
}
}
http://www.slideshare.net/IgorShkulipa 95
Использование анонимных методов
class Program
{
static void Main(string[] args)
{
IStrategyClient stClient = new StrategyClient1();
IStrategy goWork = new GoToWorkStrategy();
IStrategy goGym = new GoToGymStrategy();
IStrategy goWalk = new GoWalkStrategy();
stClient.Strategy = delegate {
Console.WriteLine("Anonymous Method:");
goWork.Use();
Console.WriteLine(); };
stClient.UseStrategy();
stClient.Strategy = delegate {
Console.WriteLine("Anonymous Method:");
goGym.Use(); Console.WriteLine(); };
stClient.UseStrategy();
stClient.Strategy = delegate {
Console.WriteLine("Anonymous Method:");
goWalk.Use(); Console.WriteLine(); };
stClient.UseStrategy();
Console.ReadKey();
}
}
Anonymous Method:
Wake up.
Take shower.
Dress.
Go out.
Go to bus stop.
Wait.
Arrive.
Do work.
Anonymous Method:
Go out.
Go to bus stop.
Arrive.
Do exercises.
Anonymous Method:
Go out.
Go to park.
Walk.
http://www.slideshare.net/IgorShkulipa 96
Шаблон проектирования «Visitor»
Паттерн Visitor определяет операцию, выполняемую на каждом
элементе из некоторой структуры без изменения классов этих
объектов.
• Паттерн Visitor определяет операцию, выполняемую на каждом
элементе из некоторой структуры. Позволяет, не изменяя классы
этих объектов, добавлять в них новые операции.
Применение расширяющих методов значительно упрощает реализацию
этого паттерна.
http://www.slideshare.net/IgorShkulipa 97
Классы «компонентов»
public class SomeClass1
{
public SomeClass1(int c) { SomeProperty1 = c; }
public int SomeProperty1 { get; set; }
}
public class SomeClass2
{
public SomeClass2(int c) { SomeProperty2 = c; }
public int SomeProperty2 { get; set; }
}
public class SomeClass3
{
public SomeClass3(int c) { SomeProperty3 = c; }
public int SomeProperty3 { get; set; }
}
http://www.slideshare.net/IgorShkulipa 98
Класс-посетитель
public static class Visitor
{
public static void Visit(this SomeClass1 sc1)
{
Console.WriteLine(sc1.SomeProperty1);
}
public static void Visit(this SomeClass2 sc2)
{
Console.WriteLine(sc2.SomeProperty2);
}
public static void Visit(this SomeClass3 sc3)
{
Console.WriteLine(sc3.SomeProperty3);
}
}
http://www.slideshare.net/IgorShkulipa 99
Использование
class Program
{
static void Main(string[] args)
{
SomeClass1 c1 = new SomeClass1(1);
SomeClass2 c2 = new SomeClass2(2);
SomeClass3 c3 = new SomeClass3(3);
c1.Visit(); c2.Visit(); c3.Visit();
Console.ReadKey();
}
}
1
2
3
http://www.slideshare.net/IgorShkulipa 100
Расширяющие методы
Расширяющие методы (методы расширения) позволяют "добавлять" методы в
существующие типы без создания нового производного типа, перекомпиляции или
иного изменения исходного типа.
Расширяющие методы являются особым видом статического метода, но они
вызываются, как если бы они были методами экземпляра в расширенном типе. Для
клиентского кода, написанного на языках C#, нет видимого различия между
вызовом метода расширения и вызовом методов, фактически определенных в типе.
public static class MyExtensions
{
public static int WordCount(this String str)
{
return str.Split(new char[] { ' ', '.', '?' },
StringSplitOptions.RemoveEmptyEntries).Length;
}
}
Методы расширения определяются как статические методы, но вызываются с
помощью синтаксиса обращения к методу экземпляра. Их первый параметр
определяет, с каким типом оперирует метод, и перед параметром идет
модификатор this. Методы расширения находятся в области действия, только если
пространство имен было явно импортировано в исходный код с помощью
директивы using.
http://www.slideshare.net/IgorShkulipa 101
Пример расширяющих методов
public static class ExtensionMethods
{
public static double Angle(this Complex compl)
{
if ((compl.Re == 0) && (compl.Im >= 0)) {
return Math.PI / 2;
}
if ((compl.Re == 0) && (compl.Im < 0)) {
return 3 * Math.PI / 2;
}
return Math.Atan(compl.Im / compl.Re);
}
}
class Program
{
static void Main(string[] args)
{
Complex c1 = new Complex(1,2);
Console.WriteLine(c1);
double angle = c1.Angle();
Console.WriteLine(angle);
Console.ReadKey();
}
}
http://www.slideshare.net/IgorShkulipa 102
Некоторые архитектурные паттерны
http://www.slideshare.net/IgorShkulipa 103
MVC
Шаблон проектирования
MVC разделяет работу
веб-приложения на три
отдельные
функциональные роли:
• модель данных
(model)
• пользовательский
интерфейс (view)
• управляющую
логику (controller)
Таким образом, изменения,
вносимые в один из
компонентов, оказывают
минимально возможное
воздействие на другие
компоненты.
http://www.slideshare.net/IgorShkulipa 104
MVP
• Модель (model)
представляет собой интерфейс,
определяющий данные для
отображения или участвующие в
пользовательском интерфейсе
иным образом
• Вид (view) - это интерфейс,
который отображает данные
(модель) и маршрутизирует
пользовательские команды (или
события) Presenter-у, чтобы тот
действовал над этими данными.
• Presenter действует над
моделью и видом. Он извлекает
данные из хранилища (модели), и
форматирует их для отображения
в Виде (view). Так же реализует
обработку событий вида.
http://www.slideshare.net/IgorShkulipa 105
MVC vs MVP
http://www.slideshare.net/IgorShkulipa 106
Архитектурный паттерн MVVM
• Модель (Model), так же, как в
классическом паттерне MVC, Модель
представляет собой фундаментальные
данные, необходимые для работы
приложения (классы, структуры).
• Вид/Представление (View) так
же, как в классическом паттерне MVC,
Вид — это графический интерфейс, то
есть окно, кнопки и.т.п.
• Модель вида (ViewModel, что
означает «Model of View») является с
одной стороны абстракцией Вида, а с
другой предоставляет обертку данных
из Модели, которые подлежат
связыванию. То есть она содержит
Модель, которая преобразована к
Виду, а так же содержит в себе
команды, которыми может
пользоваться Вид, чтобы влиять на
Модель.
http://www.slideshare.net/IgorShkulipa 107
MVVM

Contenu connexe

Tendances

Внедрение юзабилити практик в процесс разработки ПО в соответствии с СMMI - д...
Внедрение юзабилити практик в процесс разработки ПО в соответствии с СMMI - д...Внедрение юзабилити практик в процесс разработки ПО в соответствии с СMMI - д...
Внедрение юзабилити практик в процесс разработки ПО в соответствии с СMMI - д...Julia Kryuchkova
 
Внедрение Бизнес-Анализа, ИТ Бизнес-Аналитиков и UML
Внедрение Бизнес-Анализа, ИТ Бизнес-Аналитиков и UMLВнедрение Бизнес-Анализа, ИТ Бизнес-Аналитиков и UML
Внедрение Бизнес-Анализа, ИТ Бизнес-Аналитиков и UMLEdgar Khachatryan
 
Работа в команде, управление программными проектами
Работа в команде, управление программными проектамиРабота в команде, управление программными проектами
Работа в команде, управление программными проектамиUnguryan Vitaliy
 
REQ Labs 2014. Smart Business Modelling: A Key to Success in Enterprise Autom...
REQ Labs 2014. Smart Business Modelling: A Key to Success in Enterprise Autom...REQ Labs 2014. Smart Business Modelling: A Key to Success in Enterprise Autom...
REQ Labs 2014. Smart Business Modelling: A Key to Success in Enterprise Autom...Alex V. Petrov
 
Специфика работы бизнес-аналитика в зависимости от типов проектов и методологий
Специфика работы бизнес-аналитика в зависимости от типов проектов и методологийСпецифика работы бизнес-аналитика в зависимости от типов проектов и методологий
Специфика работы бизнес-аналитика в зависимости от типов проектов и методологийSQALab
 
STRATOPLAN. Efficient Object-Oriented Design and Structured Quality of Softwa...
STRATOPLAN. Efficient Object-Oriented Design and Structured Quality of Softwa...STRATOPLAN. Efficient Object-Oriented Design and Structured Quality of Softwa...
STRATOPLAN. Efficient Object-Oriented Design and Structured Quality of Softwa...Alex V. Petrov
 
Стандарт OMG Essence - в чем польза для аналитика?
Стандарт OMG Essence - в чем польза для аналитика?Стандарт OMG Essence - в чем польза для аналитика?
Стандарт OMG Essence - в чем польза для аналитика?Yury Kupriyanov
 
Clean architecture on Android
Clean architecture on AndroidClean architecture on Android
Clean architecture on AndroidGDG Odessa
 
ITGM #5. System Duality and Its Practical Effect on Business Analysis [1.0, RUS]
ITGM #5. System Duality and Its Practical Effect on Business Analysis [1.0, RUS]ITGM #5. System Duality and Its Practical Effect on Business Analysis [1.0, RUS]
ITGM #5. System Duality and Its Practical Effect on Business Analysis [1.0, RUS]Alex V. Petrov
 
Денис Бесков. Как обеспечивать полноту требований
Денис Бесков. Как обеспечивать полноту требованийДенис Бесков. Как обеспечивать полноту требований
Денис Бесков. Как обеспечивать полноту требованийDenis Beskov
 
HTP. Business Requirements Elicitation & Documentation [1.01, RUS]
HTP. Business Requirements Elicitation & Documentation [1.01, RUS]HTP. Business Requirements Elicitation & Documentation [1.01, RUS]
HTP. Business Requirements Elicitation & Documentation [1.01, RUS]Alex V. Petrov
 
метод организации репозитория исходного кода
метод организации репозитория исходного кодаметод организации репозитория исходного кода
метод организации репозитория исходного кодаSergii Shmarkatiuk
 
от каждого по потребностям, каждому — по Agile
от каждого по потребностям, каждому — по Agileот каждого по потребностям, каждому — по Agile
от каждого по потребностям, каждому — по AgileAlexey Deryushkin
 
UML2. Eleven Trivial Tips for BPMN Modellers [1.01, RUS]
UML2. Eleven Trivial Tips for BPMN Modellers [1.01, RUS]UML2. Eleven Trivial Tips for BPMN Modellers [1.01, RUS]
UML2. Eleven Trivial Tips for BPMN Modellers [1.01, RUS]Alex V. Petrov
 
А.Левенчук -- ISO 15288 и OMG Essence
А.Левенчук -- ISO 15288 и OMG EssenceА.Левенчук -- ISO 15288 и OMG Essence
А.Левенчук -- ISO 15288 и OMG EssenceAnatoly Levenchuk
 

Tendances (20)

SEMAT Agile Kitchen
SEMAT Agile KitchenSEMAT Agile Kitchen
SEMAT Agile Kitchen
 
Внедрение юзабилити практик в процесс разработки ПО в соответствии с СMMI - д...
Внедрение юзабилити практик в процесс разработки ПО в соответствии с СMMI - д...Внедрение юзабилити практик в процесс разработки ПО в соответствии с СMMI - д...
Внедрение юзабилити практик в процесс разработки ПО в соответствии с СMMI - д...
 
МиСПИСиТ (IDEF)
МиСПИСиТ (IDEF)МиСПИСиТ (IDEF)
МиСПИСиТ (IDEF)
 
Внедрение Бизнес-Анализа, ИТ Бизнес-Аналитиков и UML
Внедрение Бизнес-Анализа, ИТ Бизнес-Аналитиков и UMLВнедрение Бизнес-Анализа, ИТ Бизнес-Аналитиков и UML
Внедрение Бизнес-Анализа, ИТ Бизнес-Аналитиков и UML
 
Работа в команде, управление программными проектами
Работа в команде, управление программными проектамиРабота в команде, управление программными проектами
Работа в команде, управление программными проектами
 
Методоллогии Agile
Методоллогии AgileМетодоллогии Agile
Методоллогии Agile
 
REQ Labs 2014. Smart Business Modelling: A Key to Success in Enterprise Autom...
REQ Labs 2014. Smart Business Modelling: A Key to Success in Enterprise Autom...REQ Labs 2014. Smart Business Modelling: A Key to Success in Enterprise Autom...
REQ Labs 2014. Smart Business Modelling: A Key to Success in Enterprise Autom...
 
Специфика работы бизнес-аналитика в зависимости от типов проектов и методологий
Специфика работы бизнес-аналитика в зависимости от типов проектов и методологийСпецифика работы бизнес-аналитика в зависимости от типов проектов и методологий
Специфика работы бизнес-аналитика в зависимости от типов проектов и методологий
 
STRATOPLAN. Efficient Object-Oriented Design and Structured Quality of Softwa...
STRATOPLAN. Efficient Object-Oriented Design and Structured Quality of Softwa...STRATOPLAN. Efficient Object-Oriented Design and Structured Quality of Softwa...
STRATOPLAN. Efficient Object-Oriented Design and Structured Quality of Softwa...
 
Стандарт OMG Essence - в чем польза для аналитика?
Стандарт OMG Essence - в чем польза для аналитика?Стандарт OMG Essence - в чем польза для аналитика?
Стандарт OMG Essence - в чем польза для аналитика?
 
МиСПИСиТ (тестирование и отладка)
МиСПИСиТ (тестирование и отладка)МиСПИСиТ (тестирование и отладка)
МиСПИСиТ (тестирование и отладка)
 
Clean architecture on Android
Clean architecture on AndroidClean architecture on Android
Clean architecture on Android
 
ITGM #5. System Duality and Its Practical Effect on Business Analysis [1.0, RUS]
ITGM #5. System Duality and Its Practical Effect on Business Analysis [1.0, RUS]ITGM #5. System Duality and Its Practical Effect on Business Analysis [1.0, RUS]
ITGM #5. System Duality and Its Practical Effect on Business Analysis [1.0, RUS]
 
Денис Бесков. Как обеспечивать полноту требований
Денис Бесков. Как обеспечивать полноту требованийДенис Бесков. Как обеспечивать полноту требований
Денис Бесков. Как обеспечивать полноту требований
 
HTP. Business Requirements Elicitation & Documentation [1.01, RUS]
HTP. Business Requirements Elicitation & Documentation [1.01, RUS]HTP. Business Requirements Elicitation & Documentation [1.01, RUS]
HTP. Business Requirements Elicitation & Documentation [1.01, RUS]
 
метод организации репозитория исходного кода
метод организации репозитория исходного кодаметод организации репозитория исходного кода
метод организации репозитория исходного кода
 
от каждого по потребностям, каждому — по Agile
от каждого по потребностям, каждому — по Agileот каждого по потребностям, каждому — по Agile
от каждого по потребностям, каждому — по Agile
 
UML2. Eleven Trivial Tips for BPMN Modellers [1.01, RUS]
UML2. Eleven Trivial Tips for BPMN Modellers [1.01, RUS]UML2. Eleven Trivial Tips for BPMN Modellers [1.01, RUS]
UML2. Eleven Trivial Tips for BPMN Modellers [1.01, RUS]
 
А.Левенчук -- ISO 15288 и OMG Essence
А.Левенчук -- ISO 15288 и OMG EssenceА.Левенчук -- ISO 15288 и OMG Essence
А.Левенчук -- ISO 15288 и OMG Essence
 
МиСПИСиТ (общие принципы разработки)
МиСПИСиТ (общие принципы разработки)МиСПИСиТ (общие принципы разработки)
МиСПИСиТ (общие принципы разработки)
 

En vedette

C# Web. Занятие 07.
C# Web. Занятие 07.C# Web. Занятие 07.
C# Web. Занятие 07.Igor Shkulipa
 
C++ Базовый. Занятие 13.
C++ Базовый. Занятие 13.C++ Базовый. Занятие 13.
C++ Базовый. Занятие 13.Igor Shkulipa
 
Investors | How it works
Investors | How it worksInvestors | How it works
Investors | How it worksGREXdotIN
 
C# Desktop. Занятие 10.
C# Desktop. Занятие 10.C# Desktop. Занятие 10.
C# Desktop. Занятие 10.Igor Shkulipa
 
Bollywood Movie Poster
Bollywood Movie PosterBollywood Movie Poster
Bollywood Movie PosterAkash Hossain
 
C++ Базовый. Занятие 04.
C++ Базовый. Занятие 04.C++ Базовый. Занятие 04.
C++ Базовый. Занятие 04.Igor Shkulipa
 
JavaScript Базовый. Занятие 01.
JavaScript Базовый. Занятие 01.JavaScript Базовый. Занятие 01.
JavaScript Базовый. Занятие 01.Igor Shkulipa
 
σχέδιο προσέγγισης λογοτεχνικού κειμένου
σχέδιο προσέγγισης λογοτεχνικού κειμένουσχέδιο προσέγγισης λογοτεχνικού κειμένου
σχέδιο προσέγγισης λογοτεχνικού κειμένουMANOLIS MORAITIS
 
Capítulo iii correcion
Capítulo iii correcion Capítulo iii correcion
Capítulo iii correcion Ida Morán
 
C# Web. Занятие 01.
C# Web. Занятие 01.C# Web. Занятие 01.
C# Web. Занятие 01.Igor Shkulipa
 
16 FACTS ABOUT CHOCOLATE
16 FACTS ABOUT CHOCOLATE16 FACTS ABOUT CHOCOLATE
16 FACTS ABOUT CHOCOLATENisha Thinisha
 
Trabajo completo correcion
Trabajo completo correcionTrabajo completo correcion
Trabajo completo correcionIda Morán
 
Production diary 8
Production diary 8Production diary 8
Production diary 8Laila Jaleel
 
C++ Базовый. Занятие 08.
C++ Базовый. Занятие 08.C++ Базовый. Занятие 08.
C++ Базовый. Занятие 08.Igor Shkulipa
 
Company | How it works
Company | How it worksCompany | How it works
Company | How it worksGREXdotIN
 
Happily_Disconnected
Happily_DisconnectedHappily_Disconnected
Happily_DisconnectedAmber Perkins
 

En vedette (20)

Challenge 11
Challenge 11Challenge 11
Challenge 11
 
C# Web. Занятие 07.
C# Web. Занятие 07.C# Web. Занятие 07.
C# Web. Занятие 07.
 
C++ Базовый. Занятие 13.
C++ Базовый. Занятие 13.C++ Базовый. Занятие 13.
C++ Базовый. Занятие 13.
 
Investors | How it works
Investors | How it worksInvestors | How it works
Investors | How it works
 
C# Desktop. Занятие 10.
C# Desktop. Занятие 10.C# Desktop. Занятие 10.
C# Desktop. Занятие 10.
 
Bollywood Movie Poster
Bollywood Movie PosterBollywood Movie Poster
Bollywood Movie Poster
 
C++ Базовый. Занятие 04.
C++ Базовый. Занятие 04.C++ Базовый. Занятие 04.
C++ Базовый. Занятие 04.
 
JavaScript Базовый. Занятие 01.
JavaScript Базовый. Занятие 01.JavaScript Базовый. Занятие 01.
JavaScript Базовый. Занятие 01.
 
σχέδιο προσέγγισης λογοτεχνικού κειμένου
σχέδιο προσέγγισης λογοτεχνικού κειμένουσχέδιο προσέγγισης λογοτεχνικού κειμένου
σχέδιο προσέγγισης λογοτεχνικού κειμένου
 
Updated Colorado Resume
Updated Colorado Resume Updated Colorado Resume
Updated Colorado Resume
 
Capítulo iii correcion
Capítulo iii correcion Capítulo iii correcion
Capítulo iii correcion
 
Biotecnología
BiotecnologíaBiotecnología
Biotecnología
 
C# Web. Занятие 01.
C# Web. Занятие 01.C# Web. Занятие 01.
C# Web. Занятие 01.
 
16 FACTS ABOUT CHOCOLATE
16 FACTS ABOUT CHOCOLATE16 FACTS ABOUT CHOCOLATE
16 FACTS ABOUT CHOCOLATE
 
Trabajo completo correcion
Trabajo completo correcionTrabajo completo correcion
Trabajo completo correcion
 
Production diary 8
Production diary 8Production diary 8
Production diary 8
 
Pest & Fumi-(Shiva Resume)
Pest & Fumi-(Shiva Resume)Pest & Fumi-(Shiva Resume)
Pest & Fumi-(Shiva Resume)
 
C++ Базовый. Занятие 08.
C++ Базовый. Занятие 08.C++ Базовый. Занятие 08.
C++ Базовый. Занятие 08.
 
Company | How it works
Company | How it worksCompany | How it works
Company | How it works
 
Happily_Disconnected
Happily_DisconnectedHappily_Disconnected
Happily_Disconnected
 

Similaire à Общие темы. Тема 02.

Конспект лекций по курсу "Шаблоны разработки ПО"
Конспект лекций по курсу "Шаблоны разработки ПО"Конспект лекций по курсу "Шаблоны разработки ПО"
Конспект лекций по курсу "Шаблоны разработки ПО"Sergey Nemchinsky
 
C# Desktop. Занятие 01.
C# Desktop. Занятие 01.C# Desktop. Занятие 01.
C# Desktop. Занятие 01.Igor Shkulipa
 
Большие проекты, архитектура и фреймворки.
Большие проекты, архитектура и фреймворки.Большие проекты, архитектура и фреймворки.
Большие проекты, архитектура и фреймворки.EatDog
 
Евгений Кривошеев: Фундаментальные правила и принципы проектирования ПО
Евгений Кривошеев: Фундаментальные правила и принципы проектирования ПОЕвгений Кривошеев: Фундаментальные правила и принципы проектирования ПО
Евгений Кривошеев: Фундаментальные правила и принципы проектирования ПОLuxoft Education Center
 
Yuri Trukhin - Software developement best practices
Yuri Trukhin - Software developement best practicesYuri Trukhin - Software developement best practices
Yuri Trukhin - Software developement best practicesbeloslab
 
Автоматизация design patterns и компактный код вместе с PostSharp
Автоматизация design patterns и компактный код вместе с PostSharpАвтоматизация design patterns и компактный код вместе с PostSharp
Автоматизация design patterns и компактный код вместе с PostSharpGoSharp
 
Шаблоны разработки ПО. Часть 1. Введние
Шаблоны разработки ПО. Часть 1. ВведниеШаблоны разработки ПО. Часть 1. Введние
Шаблоны разработки ПО. Часть 1. ВведниеSergey Nemchinsky
 
Автоматизация design patterns и компактный код вместе с PostSharp
Автоматизация design patterns и компактный код вместе с PostSharpАвтоматизация design patterns и компактный код вместе с PostSharp
Автоматизация design patterns и компактный код вместе с PostSharpgeekfamilyrussia
 
C# Web. Занятие 04.
C# Web. Занятие 04.C# Web. Занятие 04.
C# Web. Занятие 04.Igor Shkulipa
 
Глава 2: Среда разработки NetBeans
Глава 2: Среда разработки NetBeansГлава 2: Среда разработки NetBeans
Глава 2: Среда разработки NetBeansmetaform
 
AOP and Design Patterns (GoF)
AOP and Design Patterns (GoF)AOP and Design Patterns (GoF)
AOP and Design Patterns (GoF)Andrey Gordienkov
 
Aspect Oriented Programming and Design Patterns
Aspect Oriented Programming and Design PatternsAspect Oriented Programming and Design Patterns
Aspect Oriented Programming and Design PatternsAndrey Gordienkov
 
C++ Базовый. Занятие 15.
C++ Базовый. Занятие 15.C++ Базовый. Занятие 15.
C++ Базовый. Занятие 15.Igor Shkulipa
 
шаблоны проектирования (42)
шаблоны проектирования (42)шаблоны проектирования (42)
шаблоны проектирования (42)romachka_pole
 
Классы и объекты в Java
Классы и объекты в JavaКлассы и объекты в Java
Классы и объекты в Javametaform
 

Similaire à Общие темы. Тема 02. (20)

Конспект лекций по курсу "Шаблоны разработки ПО"
Конспект лекций по курсу "Шаблоны разработки ПО"Конспект лекций по курсу "Шаблоны разработки ПО"
Конспект лекций по курсу "Шаблоны разработки ПО"
 
C# Desktop. Занятие 01.
C# Desktop. Занятие 01.C# Desktop. Занятие 01.
C# Desktop. Занятие 01.
 
Большие проекты, архитектура и фреймворки.
Большие проекты, архитектура и фреймворки.Большие проекты, архитектура и фреймворки.
Большие проекты, архитектура и фреймворки.
 
Design Rules And Principles
Design Rules And PrinciplesDesign Rules And Principles
Design Rules And Principles
 
Евгений Кривошеев: Фундаментальные правила и принципы проектирования ПО
Евгений Кривошеев: Фундаментальные правила и принципы проектирования ПОЕвгений Кривошеев: Фундаментальные правила и принципы проектирования ПО
Евгений Кривошеев: Фундаментальные правила и принципы проектирования ПО
 
Tdd php
Tdd phpTdd php
Tdd php
 
Netpeak Talks #3: Масштабируемое приложение на PHP
Netpeak Talks #3: Масштабируемое приложение на PHPNetpeak Talks #3: Масштабируемое приложение на PHP
Netpeak Talks #3: Масштабируемое приложение на PHP
 
Refactoring
RefactoringRefactoring
Refactoring
 
Yuri Trukhin - Software developement best practices
Yuri Trukhin - Software developement best practicesYuri Trukhin - Software developement best practices
Yuri Trukhin - Software developement best practices
 
Автоматизация design patterns и компактный код вместе с PostSharp
Автоматизация design patterns и компактный код вместе с PostSharpАвтоматизация design patterns и компактный код вместе с PostSharp
Автоматизация design patterns и компактный код вместе с PostSharp
 
Шаблоны разработки ПО. Часть 1. Введние
Шаблоны разработки ПО. Часть 1. ВведниеШаблоны разработки ПО. Часть 1. Введние
Шаблоны разработки ПО. Часть 1. Введние
 
Автоматизация design patterns и компактный код вместе с PostSharp
Автоматизация design patterns и компактный код вместе с PostSharpАвтоматизация design patterns и компактный код вместе с PostSharp
Автоматизация design patterns и компактный код вместе с PostSharp
 
C# Web. Занятие 04.
C# Web. Занятие 04.C# Web. Занятие 04.
C# Web. Занятие 04.
 
A2
A2A2
A2
 
Глава 2: Среда разработки NetBeans
Глава 2: Среда разработки NetBeansГлава 2: Среда разработки NetBeans
Глава 2: Среда разработки NetBeans
 
AOP and Design Patterns (GoF)
AOP and Design Patterns (GoF)AOP and Design Patterns (GoF)
AOP and Design Patterns (GoF)
 
Aspect Oriented Programming and Design Patterns
Aspect Oriented Programming and Design PatternsAspect Oriented Programming and Design Patterns
Aspect Oriented Programming and Design Patterns
 
C++ Базовый. Занятие 15.
C++ Базовый. Занятие 15.C++ Базовый. Занятие 15.
C++ Базовый. Занятие 15.
 
шаблоны проектирования (42)
шаблоны проектирования (42)шаблоны проектирования (42)
шаблоны проектирования (42)
 
Классы и объекты в Java
Классы и объекты в JavaКлассы и объекты в Java
Классы и объекты в Java
 

Plus de Igor Shkulipa

JavaScript Базовый. Занятие 06.
JavaScript Базовый. Занятие 06.JavaScript Базовый. Занятие 06.
JavaScript Базовый. Занятие 06.Igor Shkulipa
 
JavaScript Базовый. Занятие 11.
JavaScript Базовый. Занятие 11.JavaScript Базовый. Занятие 11.
JavaScript Базовый. Занятие 11.Igor Shkulipa
 
JavaScript Базовый. Занятие 09.
JavaScript Базовый. Занятие 09.JavaScript Базовый. Занятие 09.
JavaScript Базовый. Занятие 09.Igor Shkulipa
 
JavaScript Базовый. Занятие 10.
JavaScript Базовый. Занятие 10.JavaScript Базовый. Занятие 10.
JavaScript Базовый. Занятие 10.Igor Shkulipa
 
JavaScript Базовый. Занятие 05.
JavaScript Базовый. Занятие 05.JavaScript Базовый. Занятие 05.
JavaScript Базовый. Занятие 05.Igor Shkulipa
 
JavaScript Базовый. Занятие 08.
JavaScript Базовый. Занятие 08.JavaScript Базовый. Занятие 08.
JavaScript Базовый. Занятие 08.Igor Shkulipa
 
JavaScript Базовый. Занятие 07.
JavaScript Базовый. Занятие 07.JavaScript Базовый. Занятие 07.
JavaScript Базовый. Занятие 07.Igor Shkulipa
 
JavaScript Базовый. Занятие 04.
JavaScript Базовый. Занятие 04.JavaScript Базовый. Занятие 04.
JavaScript Базовый. Занятие 04.Igor Shkulipa
 
JavaScript Базовый. Занятие 03.
JavaScript Базовый. Занятие 03.JavaScript Базовый. Занятие 03.
JavaScript Базовый. Занятие 03.Igor Shkulipa
 
JavaScript Базовый. Занятие 02.
JavaScript Базовый. Занятие 02.JavaScript Базовый. Занятие 02.
JavaScript Базовый. Занятие 02.Igor Shkulipa
 
C# Web. Занятие 09.
C# Web. Занятие 09.C# Web. Занятие 09.
C# Web. Занятие 09.Igor Shkulipa
 
C# Web. Занятие 08.
C# Web. Занятие 08.C# Web. Занятие 08.
C# Web. Занятие 08.Igor Shkulipa
 
C# Web. Занятие 12.
C# Web. Занятие 12.C# Web. Занятие 12.
C# Web. Занятие 12.Igor Shkulipa
 
C# Web. Занятие 14.
C# Web. Занятие 14.C# Web. Занятие 14.
C# Web. Занятие 14.Igor Shkulipa
 
C# Web. Занятие 15.
C# Web. Занятие 15.C# Web. Занятие 15.
C# Web. Занятие 15.Igor Shkulipa
 
C# Web. Занятие 13.
C# Web. Занятие 13.C# Web. Занятие 13.
C# Web. Занятие 13.Igor Shkulipa
 
C# Web. Занятие 11.
C# Web. Занятие 11.C# Web. Занятие 11.
C# Web. Занятие 11.Igor Shkulipa
 
C# Web. Занятие 10.
C# Web. Занятие 10.C# Web. Занятие 10.
C# Web. Занятие 10.Igor Shkulipa
 
C# Web. Занятие 05.
C# Web. Занятие 05.C# Web. Занятие 05.
C# Web. Занятие 05.Igor Shkulipa
 
C# Web. Занятие 03.
C# Web. Занятие 03.C# Web. Занятие 03.
C# Web. Занятие 03.Igor Shkulipa
 

Plus de Igor Shkulipa (20)

JavaScript Базовый. Занятие 06.
JavaScript Базовый. Занятие 06.JavaScript Базовый. Занятие 06.
JavaScript Базовый. Занятие 06.
 
JavaScript Базовый. Занятие 11.
JavaScript Базовый. Занятие 11.JavaScript Базовый. Занятие 11.
JavaScript Базовый. Занятие 11.
 
JavaScript Базовый. Занятие 09.
JavaScript Базовый. Занятие 09.JavaScript Базовый. Занятие 09.
JavaScript Базовый. Занятие 09.
 
JavaScript Базовый. Занятие 10.
JavaScript Базовый. Занятие 10.JavaScript Базовый. Занятие 10.
JavaScript Базовый. Занятие 10.
 
JavaScript Базовый. Занятие 05.
JavaScript Базовый. Занятие 05.JavaScript Базовый. Занятие 05.
JavaScript Базовый. Занятие 05.
 
JavaScript Базовый. Занятие 08.
JavaScript Базовый. Занятие 08.JavaScript Базовый. Занятие 08.
JavaScript Базовый. Занятие 08.
 
JavaScript Базовый. Занятие 07.
JavaScript Базовый. Занятие 07.JavaScript Базовый. Занятие 07.
JavaScript Базовый. Занятие 07.
 
JavaScript Базовый. Занятие 04.
JavaScript Базовый. Занятие 04.JavaScript Базовый. Занятие 04.
JavaScript Базовый. Занятие 04.
 
JavaScript Базовый. Занятие 03.
JavaScript Базовый. Занятие 03.JavaScript Базовый. Занятие 03.
JavaScript Базовый. Занятие 03.
 
JavaScript Базовый. Занятие 02.
JavaScript Базовый. Занятие 02.JavaScript Базовый. Занятие 02.
JavaScript Базовый. Занятие 02.
 
C# Web. Занятие 09.
C# Web. Занятие 09.C# Web. Занятие 09.
C# Web. Занятие 09.
 
C# Web. Занятие 08.
C# Web. Занятие 08.C# Web. Занятие 08.
C# Web. Занятие 08.
 
C# Web. Занятие 12.
C# Web. Занятие 12.C# Web. Занятие 12.
C# Web. Занятие 12.
 
C# Web. Занятие 14.
C# Web. Занятие 14.C# Web. Занятие 14.
C# Web. Занятие 14.
 
C# Web. Занятие 15.
C# Web. Занятие 15.C# Web. Занятие 15.
C# Web. Занятие 15.
 
C# Web. Занятие 13.
C# Web. Занятие 13.C# Web. Занятие 13.
C# Web. Занятие 13.
 
C# Web. Занятие 11.
C# Web. Занятие 11.C# Web. Занятие 11.
C# Web. Занятие 11.
 
C# Web. Занятие 10.
C# Web. Занятие 10.C# Web. Занятие 10.
C# Web. Занятие 10.
 
C# Web. Занятие 05.
C# Web. Занятие 05.C# Web. Занятие 05.
C# Web. Занятие 05.
 
C# Web. Занятие 03.
C# Web. Занятие 03.C# Web. Занятие 03.
C# Web. Занятие 03.
 

Общие темы. Тема 02.

  • 1. Темы лекции: SOLID. Паттерны проектирования Игорь Шкулипа, к.т.н.
  • 3. http://www.slideshare.net/IgorShkulipa 3 SOLID. Принципы проектирования классов SOLID – это акроним названий пяти основных принципов проектирования классов, сформулированных Робертом Мартином: •Single responsibility (принцип одной ответственности), •Open for extension and closed for modification (принцип открытости/закрытости, или открытость для расширения и закрытость для модификации), •Liskov substitution (принцип подстановки Лисков), •Interface segregation (принцип разделения интерфейса), •Dependency inversion (принцип инверсии зависимостей).
  • 4. http://www.slideshare.net/IgorShkulipa 4 Single Responsibility Принцип единственной ответственности (Single Responsibility Principle) часто определяют так: у объекта должна быть только одна причина для изменения; чем больше файл или класс, тем труднее достичь этой цели. Этот принцип говорит о том, что по-хорошему каждый класс должен решать только одну задачу. Это совсем не значит, что в классе должен быть всего один метод. Это означает, что методы класса должны быть связаны одной общей целью.
  • 5. http://www.slideshare.net/IgorShkulipa 5 Single Responsibility class Persone { public string Name { get; set; } public string Surname { get; set; } public string Middle { get; set; } public void LoadFromDatabase() { } public void SaveToDatabase() { } public void PrintToPrinter() { } } class Persone { public string Name { get; set; } public string Surname { get; set; } public string Middle { get; set; } } class PersoneDatabase { public Persone LoadFromDatabase() { } public void SaveToDatabase(Persone p) { } } class PersonePrinter { public void PrintToPrinter(Persone p) { } }
  • 6. http://www.slideshare.net/IgorShkulipa 6 Open for Extension and Closed for Modification Объекты проектирования (классы, функции, модули и т.д.) должны быть открыты для расширения, но закрыты для модификации. Этот принцип говорит о том, что классы нужно проектировать так, чтобы впоследствии иметь возможность изменять поведение класса, не изменяя его код.
  • 7. http://www.slideshare.net/IgorShkulipa 7 Open for Extension and Closed for Modification class PersonePrinter { public void PrintToPrinter(Persone p) { } } class PersonePrinter { public void PrintToPrinter(Persone p) { } public void PrintToPrinterShortForm(Persone p) { } public void PrintToPrinterDetailedForm(Persone p) { } } interface IPrintForm { List<string> Formats { get; set; } } class PrintFormGeneral : IPrintForm {} class PrintFormShort : IPrintForm { } class PrintFormDetailed : IPrintForm { } class PersonePrinter { public void PrintToPrinter(Persone p, IPrintForm f) { } }
  • 8. http://www.slideshare.net/IgorShkulipa 8 Liskov Substitution Функции, которые используют ссылки на базовые классы, должны иметь возможность использовать объекты производных классов, не зная об этом.
  • 9. http://www.slideshare.net/IgorShkulipa 9 Liskov Substitution class PersonePrinter { public void PrintToPrinter(Persone p, IPrintForm f) { //... var shortForm = f as PrintFormShort; if (shortForm != null) { ... } //... var detailedForm = f as PrintFormDetailed; if (detailedForm != null) { ... } //... } } class PersonePrinter { public void PrintToPrinter(Persone p, IPrintForm f) { //... f.FormatReport(p); //... } }
  • 10. http://www.slideshare.net/IgorShkulipa 10 Interface Segregation Принцип изоляции/разделения интерфейса говорит о том, что клиент не должен вынужденно зависеть от элементов интерфейса, которые он не использует.
  • 11. http://www.slideshare.net/IgorShkulipa 11 Interface Segregation interface IEmployee { void UseComputer(); void Develop(); void Test(); } class SoftDeveloper : IEmployee { public void UseComputer() { } public void Develop() { } public void Test() {/* How??? */} } class SoftTester : IEmployee { public void UseComputer() { } public void Develop() {/* How??? */} public void Test() { } } interface IEmployee { void UseComputer(); } interface IDeveloper { void Develop(); } interface ITester { void Test(); } class SoftDeveloper : IEmployee, IDeveloper { public void UseComputer() { } public void Develop() { } } class SoftTester : IEmployee, ITester { public void UseComputer() { } public void Test() { } }
  • 12. http://www.slideshare.net/IgorShkulipa 12 Dependency Inversion • Модули верхних уровней не должны зависеть от модулей нижних уровней. • Оба типа модулей должны зависеть от абстракций. • Абстракции не должны зависеть от деталей. • Детали должны зависеть от абстракций.
  • 13. http://www.slideshare.net/IgorShkulipa 13 Dependency Inversion class SoftDeveloper { public void Develop() { } } class Manager { private readonly SoftDeveloper dev = new SoftDeveloper(); public void Manage() { dev.Develop(); } } interface IDeveloper { void Develop(); } class SoftDeveloper: IDeveloper { public void Develop() { } } class Manager { private IDeveloper dev; public Manager(IDeveloper developer) { dev = developer; } public void Manage() { dev.Develop(); } }
  • 15. http://www.slideshare.net/IgorShkulipa 15 Паттерны (шаблоны проектирования) Паттерн описывает задачу, которая снова и снова возникает в работе, а так же принцип ее решения, причем таким образом, что это решение можно потом использовать много раз, ничего не изобретая заново. В общем случае паттерн состоит из четырех основных элементов: Имя. Присваивание паттернам имен позволяет проектировать на более высоком уровне абстракции. С помощью имен паттернов можно вести общение с коллегами. Назначение паттернам имен упрощает общение в профессиональной среде. Задача - это описание того, когда следует применять паттерн. Необходимо сформулировать задачу и ее контекст. Может описываться конкретная проблема проектирования, например способ представления алгоритмов в виде объектов. Так же задача может включать перечень условий, при выполнении которых имеет смысл применять данный паттерн. Решение представляет собой описание элементов дизайна, отношений между ними, функций каждого элемента. Конкретный дизайн или реализация не имеются ввиду, поскольку паттерн – это шаблон, применимый в самых разных ситуациях. Результаты - это следствия применения паттерна и разного рода компромиссы. Хотя при описании проектных решений о последствиях часто не упоминают, знать о них необходимо, чтобы можно было выбрать между различными вариантами и оценить преимущества и недостатки данного паттерна.
  • 16. http://www.slideshare.net/IgorShkulipa 16 Паттерны (шаблоны проектирования) Паттерн описывает задачу, которая снова и снова возникает в работе, а так же принцип ее решения, причем таким образом, что это решение можно потом использовать много раз, ничего не изобретая заново. В общем случае паттерн состоит из четырех основных элементов: Имя. Присваивание паттернам имен позволяет проектировать на более высоком уровне абстракции. С помощью имен паттернов можно вести общение с коллегами. Назначение паттернам имен упрощает общение в профессиональной среде. Задача - это описание того, когда следует применять паттерн. Необходимо сформулировать задачу и ее контекст. Может описываться конкретная проблема проектирования, например способ представления алгоритмов в виде объектов. Так же задача может включать перечень условий, при выполнении которых имеет смысл применять данный паттерн. Решение представляет собой описание элементов дизайна, отношений между ними, функций каждого элемента. Конкретный дизайн или реализация не имеются ввиду, поскольку паттерн – это шаблон, применимый в самых разных ситуациях. Результаты - это следствия применения паттерна и разного рода компромиссы. Хотя при описании проектных решений о последствиях часто не упоминают, знать о них необходимо, чтобы можно было выбрать между различными вариантами и оценить преимущества и недостатки данного паттерна.
  • 17. http://www.slideshare.net/IgorShkulipa 17 Классификация паттернов Паттерны проектирования программных систем делятся на следующие категории: Архитектурные паттерны. Описывают структурную схему программной системы в целом. В данной схеме указываются отдельные функциональные составляющие системы, называемые подсистемами, а также взаимоотношения между ними. Паттерны проектирования. описывают схемы детализации программных подсистем и отношений между ними, при этом они не влияют на структуру программной системы в целом и сохраняют независимость от реализации языка программирования. Идиомы - низкоуровневые паттерны, имеют дело с вопросами реализации какой-либо проблемы с учетом особенностей данного языка программирования.
  • 18. http://www.slideshare.net/IgorShkulipa 18 Паттерны проектирования Паттерны проектирования делятся на следующие категории: Порождающие - шаблоны проектирования, которые абстрагируют процесс создания объектов. Они позволяют сделать систему независимой от способа создания, композиции и представления объектов. Структурные - шаблоны проектирования, в которых рассматривается вопрос о том, как из классов и объектов образуются более крупные структуры. Поведенческие - шаблоны проектирования, определяющие алгоритмы и способы реализации взаимодействия различных объектов и классов.
  • 19. http://www.slideshare.net/IgorShkulipa 19 Порождающие паттерны • Singleton (Одиночка) - контролирует создание единственного экземпляра некоторого класса и предоставляет доступ к нему. • Factory Method (Фабричный метод) - В его классическом варианте вводится полиморфный класс Factory, в котором определяется интерфейс фабричного метода, а ответственность за создание объектов конкретных классов переносится на производные от Factory классы, в которых этот метод переопределяется. • Abstract Factory (Абстрактная фабрика) - использует несколько фабричных методов и предназначен для создания целого семейства или группы взаимосвязанных объектов. • Builder (Строитель) - определяет процесс поэтапного конструирования сложного объекта, в результате которого могут получаться разные представления этого объекта. • Prototype (Прототип) - создает новые объекты с помощью прототипов. Прототип - некоторый объект, умеющий создавать по запросу копию самого себя. • Object Pool (Пул объектов) - используется в случае, когда создание объекта требует больших затрат или может быть создано только ограниченное количество объектов некоторого класса.
  • 20. http://www.slideshare.net/IgorShkulipa 20 Шаблон проектирования Singleton public class Singleton { public static Singleton Instance { get { if (instance == null) instance = new Singleton(); return instance; } } public void Method1() { Console.WriteLine("Singleton.Method1"); } public void Method2() { Console.WriteLine("Singleton.Method2"); } private Singleton() { } private static Singleton instance; } class Program { static void Main(string[] args) { Singleton.Instance.Method1(); Singleton.Instance.Method2(); } }
  • 21. http://www.slideshare.net/IgorShkulipa 21 Применение Singleton Применяется, когда нужен только один экземпляр класса. Например для хранения глобальной конфигурации системы, для ведения логов, связи с базой данных и т.д. Основное преимущество перед глобальными переменными в том, что экземпляр класса создается не при инициализации программы, а по первому требованию.
  • 22. http://www.slideshare.net/IgorShkulipa 22 Factory Method Паттерн Factory Method может быть полезным в решении следующих задач: 1. Система должна оставаться расширяемой путем добавления объектов новых типов. Непосредственное использование оператора new является нежелательным, так как в этом случае код создания объектов с указанием конкретных типов может получиться разбросанным по всему приложению. Тогда такие операции как добавление в систему объектов новых типов или замена объектов одного типа на другой будут затруднительными. Паттерн Factory Method позволяет системе оставаться независимой как от самого процесса порождения объектов, так и от их типов. 2. Заранее известно, когда нужно создавать объект, но неизвестен его тип.
  • 23. http://www.slideshare.net/IgorShkulipa 23 Описание паттерна Factory Method Для того, чтобы система оставалась независимой от различных типов объектов, паттерн Factory Method использует механизм полиморфизма - классы всех конечных типов наследуются от одного абстрактного базового класса, предназначенного для полиморфного использования. В этом базовом классе определяется единый интерфейс, через который пользователь будет оперировать объектами конечных типов. Для обеспечения относительно простого добавления в систему новых типов паттерн Factory Method локализует создание объектов конкретных типов в специальном классе-фабрике. Методы этого класса, посредством которых создаются объекты конкретных классов, называются фабричными. Существуют две разновидности паттерна Factory Method: Обобщенный конструктор, когда в том же самом полиморфном базовом классе, от которого наследуются производные классы всех создаваемых в системе типов, определяется статический фабричный метод. В качестве параметра в этот метод должен передаваться идентификатор типа создаваемого объекта. Классический вариант фабричного метода, когда интерфейс фабричных методов объявляется в независимом классе-фабрике, а их реализация определяется конкретными подклассами этого класса.
  • 24. http://www.slideshare.net/IgorShkulipa 24 Классическая реализация Factory Method. Классы- результаты фабрики public abstract class BaseClass { public abstract string GetName(); } public class DerivedClass1 : BaseClass { public override string GetName() { return "Derived Class 1"; } } public class DerivedClass2 : BaseClass { public override string GetName() { return "Derived Class 2"; } }
  • 25. http://www.slideshare.net/IgorShkulipa 25 Классическая реализация Factory Method. Классы фабрик public abstract class Factory { public abstract BaseClass FactoryMethod(); } class Factory1 : Factory { public override BaseClass FactoryMethod() { return new DerivedClass1(); } } class Factory2 : Factory { public override BaseClass FactoryMethod() { return new DerivedClass2(); } }
  • 26. http://www.slideshare.net/IgorShkulipa 26 Классическая реализация Factory Method. Использование class Program { static void Main(string[] args) { Factory1 fact1 = new Factory1(); Factory2 fact2 = new Factory2(); Factory[] factories = { fact1, fact2 }; for (int i = 0; i < factories.Length; i++) { BaseClass bc = factories[i].FactoryMethod(); Console.WriteLine( "Type={0}, Object={1}", bc.GetType().ToString(), bc.GetName()); } Console.ReadKey(); } } Type=HelloWorld.DerivedClass1, Object=Derived Class 1 Type=HelloWorld.DerivedClass2, Object=Derived Class 2
  • 27. http://www.slideshare.net/IgorShkulipa 27 Преимущества и недостатки Преимущества паттерна Factory Method: –Создает объекты разных типов, позволяя системе оставаться независимой как от самого процесса создания, так и от типов создаваемых объектов. Недостатки паттерна Factory Method: –В случае классического варианта паттерна даже для порождения единственного объекта необходимо создавать соответствующую фабрику
  • 28. http://www.slideshare.net/IgorShkulipa 28 Abstract Factory Паттерн Abstract Factory стоит использовать, когда: –Система должна оставаться независимой как от процесса создания новых объектов, так и от типов порождаемых объектов. Непосредственное использование оператора new в коде приложения нежелательно. –Необходимо создавать группы или семейства взаимосвязанных объектов, исключая возможность одновременного использования объектов из разных семейств в одном контексте.
  • 29. http://www.slideshare.net/IgorShkulipa 29 Классы для 1-й фабрики public abstract class BaseClass1 { public abstract string GetName(); } public class DerivedClass11 : BaseClass1 { public override string GetName() { return "Derived Class 11"; } } public class DerivedClass21 : BaseClass1 { public override string GetName() { return "Derived Class 21"; } }
  • 30. http://www.slideshare.net/IgorShkulipa 30 Классы для 2-й фабрики public abstract class BaseClass2 { public abstract string GetName(); } public class DerivedClass12 : BaseClass2 { public override string GetName() { return "Derived Class 12"; } } public class DerivedClass22 : BaseClass2 { public override string GetName() { return "Derived Class 22"; } }
  • 31. http://www.slideshare.net/IgorShkulipa 31 Классы фабрик public abstract class AbstractFactory { public abstract BaseClass1 FactoryMethod1(); public abstract BaseClass2 FactoryMethod2(); } class AbstractFactory1 : AbstractFactory { public override BaseClass1 FactoryMethod1() { return new DerivedClass11(); } public override BaseClass2 FactoryMethod2() { return new DerivedClass12(); } } class AbstractFactory2 : AbstractFactory { public override BaseClass1 FactoryMethod1() { return new DerivedClass21(); } public override BaseClass2 FactoryMethod2() { return new DerivedClass22(); } }
  • 32. http://www.slideshare.net/IgorShkulipa 32 Использование class Program { static void UseAbstractFactory(AbstractFactory af) { BaseClass1 bc1 = af.FactoryMethod1(); BaseClass2 bc2 = af.FactoryMethod2(); Console.WriteLine(bc1.GetName()); Console.WriteLine(bc2.GetName()); } static void Main(string[] args) { AbstractFactory af1 = new AbstractFactory1(); AbstractFactory af2 = new AbstractFactory2(); UseAbstractFactory(af1); UseAbstractFactory(af2); Console.ReadKey(); } } Derived Class 11 Derived Class 12 Derived Class 21 Derived Class 22
  • 33. http://www.slideshare.net/IgorShkulipa 33 Паттерн «Прототип» Использует для создания новых объектов копию самого себя. Паттерн Prototype (прототип) можно использовать в следующих случаях: –Система должна оставаться независимой как от процесса создания новых объектов, так и от типов порождаемых объектов. Непосредственное использование оператора new в коде приложения считается нежелательным. –Необходимо создавать объекты, точные классы которых становятся известными уже на стадии выполнения программы.
  • 34. http://www.slideshare.net/IgorShkulipa 34 Интерфейс ICloneable Поддерживает копирование, при котором создается новый экземпляр класса с тем же значением, что и у существующего экземпляра. Метод Clone() создает новый объект, являющийся копией текущего экземпляра. Метод MemberwiseClone для создания неполной копии создает новый объект, а затем копирует в него нестатические поля текущего объекта. Если поле относится к типу значения, выполняется побитовое копирование полей. Если поле относится к ссылочному типу, копируются ссылки, а не объекты, на которые они указывают; следовательно, ссылки в исходном объекте и его клоне указывают на один и тот же объект.
  • 35. http://www.slideshare.net/IgorShkulipa 35 Пример class DeepStructure { public int A { get; set; } public int B { get; set; } } class CloneClass { public int X { get; set; } public int Y { get; set; } public DeepStructure ds; public CloneClass() { ds = new DeepStructure(); } public override string ToString() { return X.ToString() + " " + Y.ToString() + " " + ds.A.ToString() + " " + ds.B.ToString() + " " + ds.GetHashCode(); } } class ShallowCloneClass : CloneClass, ICloneable { public object Clone() { return (ShallowCloneClass)this.MemberwiseClone(); } } class DeepCloneClass : CloneClass, ICloneable { public object Clone() { DeepCloneClass result = new DeepCloneClass(); result.X = this.X; result.Y = this.Y; result.ds = new DeepStructure(); result.ds.A = this.ds.A; result.ds.B = this.ds.B; return result; ; } }
  • 36. http://www.slideshare.net/IgorShkulipa 36 Использование 3 class Program { static void Main(string[] args) { ShallowCloneClass sc1 = new ShallowCloneClass(); sc1.X = 1; sc1.Y = 2; sc1.ds.A = 3; sc1.ds.B = 4; ShallowCloneClass sc2 = (ShallowCloneClass)sc1.Clone(); Console.WriteLine(sc1.ToString()); Console.WriteLine(sc2.ToString()); DeepCloneClass dc1 = new DeepCloneClass(); dc1.X = 1; dc1.Y = 2; dc1.ds.A = 3; dc1.ds.B = 4; DeepCloneClass dc2 = (DeepCloneClass)dc1.Clone(); Console.WriteLine(dc1.ToString()); Console.WriteLine(dc2.ToString()); Console.ReadKey(); } } 1 2 3 4 27226607 1 2 3 4 27226607 1 2 3 4 42549079 1 2 3 4 66790640
  • 37. http://www.slideshare.net/IgorShkulipa 37 Паттерн Builder Паттерн Builder может помочь в решении следующих задач: –В системе могут существовать сложные объекты, создание которых за одну операцию затруднительно или невозможно. Требуется поэтапное построение объектов с контролем результатов выполнения каждого этапа. –Данные должны иметь несколько представлений. Например, если есть некоторый исходный документ в формате RTF (Rich Text Format), в общем случае содержащий текст, графические изображения и служебную информацию о форматировании (размер и тип шрифтов, отступы и др.). Если этот документ в формате RTF преобразовать в другие форматы (например, Microsoft Word или простой ASCII-текст), то полученные документы и будут представлениями исходных данных.
  • 38. http://www.slideshare.net/IgorShkulipa 38 Описание паттерна Builder Паттерн Builder отделяет алгоритм поэтапного конструирования сложного объекта от его внешнего представления так, что с помощью одного и того же алгоритма можно получать разные представления этого объекта. Для этого паттерн Builder определяет алгоритм поэтапного создания продукта в специальном классе Director (распорядитель), а ответственность за координацию процесса сборки отдельных частей продукта возлагает на иерархию классов Builder. В этой иерархии базовый класс Builder объявляет интерфейс для построения отдельных частей продукта, а соответствующие подклассы конкретных строителей их реализуют подходящим образом, например, создают или получают нужные ресурсы, сохраняют промежуточные результаты, контролируют результаты выполнения операций.
  • 39. http://www.slideshare.net/IgorShkulipa 39 Реализация паттерна Builder. Класс Computer class Computer { public string Name { get; set; } public string CPU { get; set; } public string RAM { get; set; } public string HDD { get; set; } public string VGA { get; set; } public void Print() { Console.Write( "{0}: {1}/{2}/{3}/{4}n", Name, CPU, RAM, HDD, VGA); } }
  • 40. http://www.slideshare.net/IgorShkulipa 40 Классы-строители interface ICompBuilder { Computer Build(); } class GameCompBuilder : ICompBuilder { private Computer computer; public GameCompBuilder() { computer = new Computer(); } Computer ICompBuilder.Build() { computer.Name = "Game Computer"; computer.CPU = "Core i7 3.0 GHz"; computer.RAM = "8 Gb"; computer.HDD = "1 Tb"; computer.VGA = "GeForce GTX 560"; return computer; } } class OfficeCompBuilder : ICompBuilder { private Computer computer; public OfficeCompBuilder() { computer = new Computer(); } Computer ICompBuilder.Build() { computer.Name = "Office Computer"; computer.CPU = "Core i3 3.0 GHz"; computer.RAM = "2 Gb"; computer.HDD = "500 Gb"; computer.VGA = "Intel GMA 4000"; return computer; } }
  • 41. http://www.slideshare.net/IgorShkulipa 41 Класс-директор class Director { private ICompBuilder builder; public Director() { } public void SetBuilder(ICompBuilder builder) { this.builder = builder; } public Computer GetComp() { return builder.Build(); } }
  • 42. http://www.slideshare.net/IgorShkulipa 42 Использование строителей class Program { static void Main(string[] args) { Director director = new Director(); //Building Game Computer director.SetBuilder(new GameCompBuilder()); Computer comp = director.GetComp(); comp.Print(); //Building Office Computer director.SetBuilder(new OfficeCompBuilder()); comp = director.GetComp(); comp.Print(); Console.ReadKey(); } } Game Computer: Core i7 3.2 GHz/16 Gb/1 Tb/GeForce GTX 960 Office Computer: Core i3 3.0 GHz/2 Gb/500 Gb/Intel GMA 5000
  • 43. http://www.slideshare.net/IgorShkulipa 43 StringBuilder Предоставляет изменяемую строку символов. [SerializableAttribute] [ComVisibleAttribute(true)] public sealed class StringBuilder : ISerializable Операция объединения объекта String всегда создает новый объект из существующей строки и новых данных. Объект StringBuilder поддерживает буфер для размещения и конкатенации новых данных. Новые данные добавляются в имеющийся буфер только в том случае, если в нем имеется достаточное свободное пространство для их размещения, в противном случае выделяется новый буфер достаточного размера, данные из оригинального буфера копируются в другой буфер, и новые данные добавляются уже в новый буфер.
  • 44. http://www.slideshare.net/IgorShkulipa 44 Пример class Program { static void Main(string[] args) { string strText1 = "Hello" + "," + " " + "World" + "!"; string strText2 = ""; StringBuilder strBuilder = new StringBuilder(strText2); strBuilder.Append("Hello"); strBuilder.Append(","); strBuilder.Append(" "); strBuilder.Append("World"); strBuilder.Append("!"); strText2 = strBuilder.ToString(); Console.WriteLine(strText1); Console.WriteLine(strText2); Console.ReadKey(); } } Hello, World! Hello, World!
  • 45. http://www.slideshare.net/IgorShkulipa 45 Object Pool Применение паттерна Object Pool может значительно повысить производительность системы; его использование наиболее эффективно в ситуациях, когда создание экземпляров некоторого класса требует больших затрат, объекты в системе создаются часто, но число создаваемых объектов в единицу времени ограничено. Пулы объектов (известны также как пулы ресурсов) используются для управления кэшированием объектов. Клиент, имеющий доступ к пулу объектов может избежать создания новых объектов, просто запрашивая в пуле уже созданный экземпляр. Пул объектов может быть растущим, когда при отсутствии свободных создаются новые объекты или c ограничением количества создаваемых объектов.
  • 46. http://www.slideshare.net/IgorShkulipa 46 Реализация Object Pool на основе Singleton. Классы объектов abstract class IObject { protected string Text; public virtual void Print() { Console.WriteLine("The Object is: {0}", Text); } } class Object1 : IObject { public Object1() { Text = "Object 1"; } } class Object2 : IObject { public Object2() { Text = "Object 2"; } } class Object3 : IObject { public Object3() { Text = "Object 3"; } } class Object4 : IObject { public Object4() { Text = "Object 4"; } }
  • 47. http://www.slideshare.net/IgorShkulipa 47 Object Pool class ObjectPool { public static ObjectPool GetInstance(int size) { if (instance == null) instance = new ObjectPool(size); return instance; } public IObject GetObject() { for (int i = 0; i < poolSize; i++) { if (!busyObjects[i]) { busyObjects[i] = true; return objectPool[i]; } } return null; } public void ReleaseObject(IObject obj) { for (int i = 0; i < poolSize; i++) { if (objectPool[i] == obj) { busyObjects[i] = false; } } }...
  • 48. http://www.slideshare.net/IgorShkulipa 48 Object Pool private ObjectPool(int size) { poolSize = size; objectPool = new IObject[poolSize]; busyObjects = new bool[poolSize]; Random rand = new Random(1000); for (int i = 0; i < poolSize; i++) { int iObjNumber = rand.Next()%4; switch (iObjNumber) { case 0: objectPool[i] = new Object1(); busyObjects[i] = false; break; case 1: objectPool[i] = new Object2(); busyObjects[i] = false; break; case 2: objectPool[i] = new Object3(); busyObjects[i] = false; break; case 3: objectPool[i] = new Object4(); busyObjects[i] = false; break; } busyObjects[i] = false; } } private IObject[] objectPool; private int poolSize; private bool[] busyObjects; private static ObjectPool instance; }
  • 49. http://www.slideshare.net/IgorShkulipa 49 Использование Object Pool class Program { static void Main(string[] args) { ObjectPool op = ObjectPool.GetInstance(5); IObject object1 = op.GetObject(); if (object1 != null) object1.Print(); else Console.WriteLine("The Object is: NULL"); IObject object2 = op.GetObject(); if (object2 != null) object2.Print(); else Console.WriteLine("The Object is: NULL"); IObject object3 = op.GetObject(); if (object3 != null) object3.Print(); else Console.WriteLine("The Object is: NULL"); IObject object4 = op.GetObject(); if (object4 != null) object4.Print(); else Console.WriteLine("The Object is: NULL"); IObject object5 = op.GetObject(); if (object5 != null) object5.Print(); else Console.WriteLine("The Object is: NULL"); IObject object6 = op.GetObject(); if (object6 != null) object6.Print(); else Console.WriteLine("The Object is: NULL"); IObject object7 = op.GetObject(); if (object7 != null) object7.Print(); else Console.WriteLine("The Object is: NULL"); op.ReleaseObject(object2); IObject object8 = op.GetObject(); if (object8 != null) object8.Print(); else Console.WriteLine("The Object is: NULL"); Console.ReadKey(); } }
  • 50. http://www.slideshare.net/IgorShkulipa 50 Результат The Object is: Object 2 The Object is: Object 4 The Object is: Object 3 The Object is: Object 1 The Object is: Object 2 The Object is: NULL The Object is: NULL The Object is: Object 4
  • 51. http://www.slideshare.net/IgorShkulipa 51 Структурные шаблоны проектирования –Adapter представляет собой программную обертку над уже существующими классами и предназначен для преобразования их интерфейсов к виду, пригодному для последующего использования в новом программном проекте. –Bridge отделяет абстракцию от реализации так, что то и другое можно изменять независимо. –Composite группирует схожие объекты в древовидные структуры. Рассматривает единообразно простые и сложные объекты. –Decorator используется для расширения функциональности объектов. Являясь гибкой альтернативой порождению классов, паттерн Decorator динамически добавляет объекту новые обязанности. –Facade предоставляет высокоуровневый унифицированный интерфейс к набору интерфейсов некоторой подсистемы, что облегчает ее использование. –Flyweight использует разделение для эффективной поддержки множества объектов. –Proxy замещает другой объект для контроля доступа к нему.
  • 52. http://www.slideshare.net/IgorShkulipa 52 Адаптер Паттерн Adapter, представляет собой программную обертку над существующими классами, преобразуя их интерфейсы к виду, пригодному для последующего использования. Пусть класс, интерфейс которого нужно адаптировать к нужному виду, имеет имя Adaptee. Для решения задачи преобразования его интерфейса паттерн Adapter вводит следующую иерархию классов: –Виртуальный базовый класс Target. Здесь объявляется пользовательский интерфейс подходящего вида. Только этот интерфейс доступен для пользователя. –Производный класс Adapter, реализующий интерфейс Target. В этом классе также имеется указатель или ссылка на экземпляр Adaptee. Паттерн Adapter использует этот указатель для перенаправления клиентских вызовов в Adaptee. Так как интерфейсы Adaptee и Target несовместимы между собой, то эти вызовы обычно требуют преобразования.
  • 53. http://www.slideshare.net/IgorShkulipa 53 Пример. Преобразование строки в структуру class InputStringFullName { public string Text { get; set; } public InputStringFullName() { Text = ""; } public void Input() { Console.Write ("Input Full Name (Surname Name MiddleName): "); Text = Console.ReadLine(); } }
  • 54. http://www.slideshare.net/IgorShkulipa 54 Класс структуры class FullName { public string Name { get; set; } public string Surname { get; set; } public string Middle { get; set; } public FullName(string surname, string name, string middle) { Name = name; Surname = surname; Middle = middle; } public void Print() { Console.WriteLine(Name); Console.WriteLine(Middle); Console.WriteLine(Surname); } }
  • 55. http://www.slideshare.net/IgorShkulipa 55 Класс-адаптер class FullNameAdapter : InputStringFullName { public FullNameAdapter(InputStringFullName stringFullName) { Text = stringFullName.Text; } public FullName GetFullName() { int iFirstSpace = Text.IndexOf(' '); string strSurname = Text.Substring(0, iFirstSpace); int iSecondSpace = Text.Substring(iFirstSpace + 1).IndexOf(' ') + iFirstSpace + 1; string strName = Text.Substring(iFirstSpace, iSecondSpace - iFirstSpace); string strMiddle = Text.Substring(iSecondSpace); return new FullName(strSurname, strName, strMiddle); } }
  • 56. http://www.slideshare.net/IgorShkulipa 56 Использование адаптера class Program { static void Main(string[] args) { InputStringFullName isfn = new InputStringFullName(); isfn.Input(); FullNameAdapter fna = new FullNameAdapter(isfn); FullName fn = fna.GetFullName(); fn.Print(); Console.ReadKey(); } } Результат: Input Full Name (Surname Name MiddleName): Ivanov Ivan Ivanovich Ivan Ivanovich Ivanov
  • 57. http://www.slideshare.net/IgorShkulipa 57 Паттерн проектирования «Мост» Используется для того, чтобы разделять абстракцию и реализацию так, чтобы они могли изменяться независимо.
  • 58. http://www.slideshare.net/IgorShkulipa 58 Реализация. Классы реализаторов с общим интерфейсом public interface Iimplementor { void Operation(); } class Implementor1 : Iimplementor { void IImplementor.Operation() { Console.WriteLine("Implementor 1"); } } class Implementor2 : Iimplementor { void IImplementor.Operation() { Console.WriteLine("Implementor 2"); } }
  • 59. http://www.slideshare.net/IgorShkulipa 59 Класс-абстракция class Abstraction { protected IImplementor implementor; public Abstraction() { } public void SetImplementor(IImplementor implementor) { this.implementor = implementor; } public void Operation() { implementor.Operation(); } }
  • 60. http://www.slideshare.net/IgorShkulipa 60 Использование моста class Program { static void Main(string[] args) { Abstraction abstr = new Abstraction(); abstr.SetImplementor(new Implementor1()); abstr.Operation(); abstr.SetImplementor(new Implementor2()); abstr.Operation(); Console.ReadKey(); } } Результат: Implementor 1 Implementor 2
  • 61. http://www.slideshare.net/IgorShkulipa 61 Шаблоны поведения Паттерн Chain of Responsibility позволяет обработать запрос нескольким объектам-получателям. Получатели связываются в цепочку, и запрос передается по цепочке, пока не будет обработан каким-то объектом. Паттерн Chain of Responsibility позволяет также избежать жесткой зависимости между отправителем запроса и его получателями. Паттерн Command преобразовывает запрос на выполнение действия в отдельный объект-команду. Это придает системе гибкость: позволяет осуществлять динамическую замену команд, использовать сложные составные команды, осуществлять отмену операций. Паттерн Iterator предоставляет механизм обхода элементов составных объектов (коллекций) не раскрывая их внутреннего представления. Паттерн Interpreter предназначен для решения повторяющихся задач, которые можно описать некоторым языком. Для этого паттерн Interpreter описывает решаемую задачу в виде предложений этого языка, а затем интерпретирует их. Паттерн Mediator инкапсулирует взаимодействие совокупности объектов в отдельный объект-посредник. Уменьшает степень связанности взаимодействующих объектов - им не нужно хранить ссылки друг на друга.
  • 62. http://www.slideshare.net/IgorShkulipa 62 Шаблоны поведения Паттерн Memento получает и сохраняет за пределами объекта его внутреннее состояние так, чтобы позже можно было восстановить объект в таком же состоянии. Паттерн Observer определяет зависимость "один-ко-многим" между объектами так, что при изменении состояния одного объекта все зависящие от него объекты уведомляются и обновляются автоматически. Паттерн State позволяет объекту изменять свое поведение в зависимости от внутреннего состояния. Создается впечатление, что объект изменил свой класс. Паттерн State является объектно- ориентированной реализацией конечного автомата. Если поведение системы настраивается согласно одному из некоторого множества алгоритму, то применение паттерна Strategy переносит семейство алгоритмов в отдельную иерархию классов, что позволяет заменять один алгоритм другим в ходе выполнения программы. Кроме того, такую систему проще расширять и поддерживать. Паттерн Template Method определяет основу алгоритма и позволяет подклассам изменить некоторые шаги этого алгоритма без изменения его общей структуры. Паттерн Visitor определяет операцию, выполняемую на каждом элементе из некоторой структуры без изменения классов этих объектов.
  • 63. http://www.slideshare.net/IgorShkulipa 63 Паттерн Chain of Responsibility Паттерн Chain of Responsibility позволяет избежать жесткой зависимости отправителя запроса от его получателя, при этом запрос может быть обработан несколькими объектами. Объекты-получатели связываются в цепочку. Запрос передается по этой цепочке, пока не будет обработан. Вводит конвейерную обработку для запроса с множеством возможных обработчиков. Объектно-ориентированный связанный список с рекурсивным обходом.
  • 64. http://www.slideshare.net/IgorShkulipa 64 Общая схема паттерна Клиент Обработчик 1 Обработчик 2 Обработчик 3 Обработчик ... Обработчик n
  • 65. http://www.slideshare.net/IgorShkulipa 65 Реализация цепочки. Классы событий public abstract class IEvent{ public string EventType { get; set; } } class Event1 : IEvent { public Event1() { EventType = "Event1"; } } class Event2 : IEvent { public Event2() { EventType = "Event2"; } } class Event3 : IEvent { public Event3() { EventType = "Event3"; } } class Event4 : IEvent { public Event4() { EventType = "Event4"; } } class Event5 : IEvent { public Event5() { EventType = "Event5"; } } class Event6 : IEvent { public Event6() { EventType = "Event6"; } }
  • 66. http://www.slideshare.net/IgorShkulipa 66 Базовый класс-обработчик public abstract class BaseHandler { public BaseHandler() { Next = null; } public virtual void Handle(IEvent ev) { if (PrivateEvent.EventType == ev.EventType) { Console.WriteLine("{0} successfully handled", PrivateEvent.EventType); } else { Console.WriteLine("Sending event to next Handler..."); if (Next != null) Next.Handle(ev); else Console.WriteLine("Unknown event. Can't handle."); } } protected void SetNextHandler(BaseHandler newHandler) { Next = newHandler; } protected BaseHandler Next { get; set; } protected IEvent PrivateEvent { get; set; } }
  • 67. http://www.slideshare.net/IgorShkulipa 67 Классы-обработчики class Handler5 : BaseHandler { public Handler5() { PrivateEvent = new Event5(); Next = null; } } class Handler4 : BaseHandler { public Handler4() { PrivateEvent = new Event4(); Next = new Handler5(); } } class Handler3 : BaseHandler { public Handler3() { PrivateEvent = new Event3(); Next = new Handler4(); } } class Handler2 : BaseHandler { public Handler2() { PrivateEvent = new Event2(); Next = new Handler3(); } } class Handler1 : BaseHandler { public Handler1() { PrivateEvent = new Event1(); Next = new Handler2(); } }
  • 68. http://www.slideshare.net/IgorShkulipa 68 Класс тестового приложения public class ChainApplication { public ChainApplication() { eventHandler = new Handler1(); Rand = new Random(); } public void Run(int EventCount) { for (int i = 0; i < EventCount; i++) { HandleEvent(GenerateRandomEvent()); } } private void HandleEvent(IEvent ev) { eventHandler.Handle(ev); } private IEvent GenerateRandomEvent() { IEvent result; switch (Rand.Next(1,6)) { case 0: result = new Event1(); break; case 1: result = new Event2(); break; case 2: result = new Event3(); break; case 3: result = new Event4(); break; case 4: result = new Event5(); break; default: result = new Event6(); break; } Console.WriteLine("Generated event: {0}", result.EventType); return result; } private BaseHandler eventHandler; private Random Rand; }
  • 69. http://www.slideshare.net/IgorShkulipa 69 Результат цепочки ответственностей class Program { static void Main(string[] args) { ChainApplication app = new ChainApplication(); app.Run(3); Console.ReadKey(); } } Результат: Generated event: Event4 Sending event to next Handler... Sending event to next Handler... Sending event to next Handler... Event4 successfully handled Generated event: Event6 Sending event to next Handler... Sending event to next Handler... Sending event to next Handler... Sending event to next Handler... Sending event to next Handler... Unknown event. Can't handle. Generated event: Event5 Sending event to next Handler... Sending event to next Handler... Sending event to next Handler... Sending event to next Handler... Event5 successfully handled
  • 70. http://www.slideshare.net/IgorShkulipa 70 Команда Паттерн Command преобразовывает запрос на выполнение действия в отдельный объект-команду. Такая инкапсуляция позволяет передавать эти действия другим функциям и объектам в качестве параметра, приказывая им выполнить запрошенную операцию. Команда – это объект, поэтому над ней допустимы любые операции, что и над объектом. Команда используется, если: –Система управляется событиями. При появлении такого события (запроса) необходимо выполнить определенную последовательность действий. –Необходимо параметризировать объекты выполняемым действием, ставить запросы в очередь или поддерживать операции отмены и повтора действий. –Нужен объектно-ориентированный аналог функции обратного вызова в процедурном программировании.
  • 71. http://www.slideshare.net/IgorShkulipa 71 Пример. Интерфейс «Игра» public interface IGame { void New(); void Start(); void Pause(); void Resume(); void Finish(); void Break(); void BreakAndFinish(); void BreakAndStart(); }
  • 72. http://www.slideshare.net/IgorShkulipa 72 Реализация интерфейса public class SomeGame : Igame { void IGame.New() { Console.WriteLine("New Game."); } void IGame.Start() { Console.WriteLine("Game Started."); } void IGame.Pause() { Console.WriteLine("Game Paused."); } void IGame.Resume() { Console.WriteLine("Game Resumed."); } void IGame.Finish() { Console.WriteLine("Game Finished."); } void IGame.Break() { Console.WriteLine("Game Breaked."); } void IGame.BreakAndFinish() { Console.WriteLine("Game Breaked."); Console.WriteLine("Game Finished."); } void IGame.BreakAndStart() { Console.WriteLine("Game Breaked."); Console.WriteLine("New Game."); Console.WriteLine("Game Started."); } }
  • 73. http://www.slideshare.net/IgorShkulipa 73 Классы команд public class Icommand { public ICommand(IGame game) { Game = game; } public virtual void ExecuteCommand() { } public IGame Game { get; set; } } class NewCommand : Icommand { public NewCommand(IGame game) : base(game) { } public override void ExecuteCommand() { Console.WriteLine("Executing New Command..."); Game.New(); } } class StartCommand : Icommand { public StartCommand(IGame game) : base(game) { } public override void ExecuteCommand() { Console.WriteLine("Executing Start Command..."); Game.Start(); } }
  • 74. http://www.slideshare.net/IgorShkulipa 74 Классы команд class PauseCommand : ICommand{ public PauseCommand(IGame game) : base(game) { } public override void ExecuteCommand() { Console.WriteLine("Executing Pause Command..."); Game.Pause(); } } class ResumeCommand : ICommand{ public ResumeCommand(IGame game) : base(game) { } public override void ExecuteCommand() { Console.WriteLine("Executing Resume Command..."); Game.Resume(); } } class FinishCommand : ICommand{ public FinishCommand(IGame game) : base(game) { } public override void ExecuteCommand() { Console.WriteLine("Executing Finish Command..."); Game.Finish(); } }
  • 75. http://www.slideshare.net/IgorShkulipa 75 Классы команд class BreakCommand : ICommand{ public BreakCommand(IGame game) : base(game) { } public override void ExecuteCommand() { Console.WriteLine("Executing Break Command..."); Game.Break(); } } class BreakAndFinishCommand : ICommand{ public BreakAndFinishCommand(IGame game) : base(game) { } public override void ExecuteCommand() { Console.WriteLine("Executing Break And Finish Command..."); Game.BreakAndFinish(); } } class BreakAndStartCommand : ICommand{ public BreakAndStartCommand(IGame game) : base(game) { } public override void ExecuteCommand() { Console.WriteLine("Executing Break And Start Command..."); Game.BreakAndStart(); } }
  • 76. http://www.slideshare.net/IgorShkulipa 76 Использование команд class Program { static void Main(string[] args) { IGame someGame = new SomeGame(); ICommand[] commands = new ICommand[10]; commands[0] = new NewCommand(someGame); commands[1] = new StartCommand(someGame); commands[2] = new BreakCommand(someGame); commands[3] = new NewCommand(someGame); commands[4] = new StartCommand(someGame); commands[5] = new BreakAndStartCommand(someGame); commands[6] = new PauseCommand(someGame); commands[7] = new ResumeCommand(someGame); commands[8] = new PauseCommand(someGame); commands[9] = new BreakAndFinishCommand(someGame); for (int i = 0; i < 10; i++) { commands[i].ExecuteCommand(); } Console.ReadKey(); } } Результат: Executing New Command... New Game. Executing Start Command... Game Started. Executing Break Command... Game Breaked. Executing New Command... New Game. Executing Start Command... Game Started. Executing Break And Start Command... Game Breaked. New Game. Game Started. Executing Pause Command... Game Paused. Executing Resume Command... Game Resumed. Executing Pause Command... Game Paused. Executing Break And Finish Command... Game Breaked. Game Finished.
  • 77. http://www.slideshare.net/IgorShkulipa 77 Паттерн Iterator Назначение паттерна Iterator • Предоставляет способ последовательного доступа ко всем элементам составного объекта, не раскрывая его внутреннего представления. • Абстракция в стандартных библиотеках C++ и Java, позволяющая разделить классы коллекций и алгоритмов. • Придает обходу коллекции "объектно-ориентированный статус". • Полиморфный обход.
  • 78. http://www.slideshare.net/IgorShkulipa 78 Интерфейсы public interface IIterator { object Next(); object First(); bool Finished(); object Current(); } public interface IIterCollection { IIterator GetIterator(); }
  • 79. http://www.slideshare.net/IgorShkulipa 79 Реализация коллекции public class IterCollection: IIterCollection { private ArrayList items = new ArrayList(); IIterator IIterCollection.GetIterator() { return new Iterator(this); } public object Get(int i) { return items[i]; } public int GetCount() { return items.Count; } }
  • 80. http://www.slideshare.net/IgorShkulipa 80 Реализация итератора public class Iterator : IIterator { private IterCollection collection; private int current; public Iterator(IterCollection col) { collection = col; current = 0; } object IIterator.First() { return collection.Get(0); } object IIterator.Current() { return collection.Get(current); } bool IIterator.Finished() { return (current >= collection.GetCount()); } object IIterator.Next() { return collection.Get(current++); } }
  • 81. http://www.slideshare.net/IgorShkulipa 81 Использование class Program { static void Main(string[] args) { IIterCollection ic = new IterCollection(10); IIterator iter = ic.GetIterator(); while (!iter.Finished()) { Console.WriteLine(iter.Next()); } Console.ReadKey(); } } 0 7 5 2 9 9 5 0 5 9
  • 82. http://www.slideshare.net/IgorShkulipa 82 Альтернативная реализация public class SquareCollection : IEnumerable<int> { private int[][] items; public SquareCollection(int number) { Random rand = new Random(); this.items = new int[number][]; for (int i = 0; i < number; i++) { int[] item = new int[number]; for (int j = 0; j < number; j++) { item[j] = rand.Next() % 10; } this.items[i] = item; } } public IEnumerator<int> GetEnumerator() { for (int i = 0; i < items.Length; i++) { for (int j = items[i].Length - 1; j >= 0; j--) { yield return items[i][j]; } } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } }
  • 83. http://www.slideshare.net/IgorShkulipa 83 Использование class Program { static void Main(string[] args) { SquareCollection sc = new SquareCollection(10); foreach (var item in sc) { Console.WriteLine(item); } Console.ReadKey(); } } 5 0 1 5 2 6 7 1 3 9 5 0 3 8 2 ...
  • 84. http://www.slideshare.net/IgorShkulipa 84 Паттерн Memento (Хранитель) Назначение паттерна Memento: • Не нарушая инкапсуляции, паттерн Memento получает и сохраняет за пределами объекта его внутреннее состояние так, чтобы позже можно было восстановить объект в таком же состоянии. • Является средством для инкапсуляции "контрольных точек" программы. • Паттерн Memento придает операциям "Отмена" (undo) или "Откат" (rollback) статус "полноценного объекта". Паттерн проектирования Memento определяет трех различных участников: • Originator (хозяин) - объект, умеющий создавать хранителя, а также знающий, как восстановить свое внутреннее состояние из хранителя. • Caretaker (смотритель) - объект, который знает, почему и когда хозяин должен сохранять и восстанавливать себя. • Memento (хранитель) - "ящик на замке", который пишется и читается хозяином и за которым присматривает смотритель.
  • 85. http://www.slideshare.net/IgorShkulipa 85 Класс Memento и интерфейс IOriginator class Memento { public string Name { get; set; } public string Surname { get; set; } public string MiddleName { get; set; } } public interface IOriginator { object GetMemento(); void SetMemento(object memento); }
  • 86. http://www.slideshare.net/IgorShkulipa 86 Класс для состояние, которого надо запомнить class FullNameClass: IOriginator { public string Name { get; set; } public string Surname { get; set; } public string MiddleName { get; set; } public FullNameClass(string name, string surname, string middle) { Name = name; Surname = surname; MiddleName = middle; } public void Print() { Console.WriteLine("Name={0} Surname={1} Middle={2}", Name, Surname, MiddleName); } object IOriginator.GetMemento() { return new Memento { Name = this.Name, Surname = this.Surname, MiddleName = this.MiddleName }; } void IOriginator.SetMemento(object memento){ if (memento is Memento) { var mem = memento as Memento; Name = mem.Name; Surname = mem.Surname; MiddleName = mem.MiddleName; } } }
  • 87. http://www.slideshare.net/IgorShkulipa 87 Класс «Смотритель» public class Caretaker { private object memento; public void SaveState(IOriginator originator) { memento = originator.GetMemento(); } public void RestoreState(IOriginator originator) { originator.SetMemento(memento); } }
  • 88. http://www.slideshare.net/IgorShkulipa 88 Использование class Program { static void Main(string[] args) { FullNameClass fnc = new FullNameClass("Ivan", "Ivanov", "Ivanovich"); Caretaker ct = new Caretaker(); fnc.Print(); ct.SaveState(fnc); fnc = new FullNameClass("Petr", "Petrov", "Petrovich"); fnc.Print(); ct.RestoreState(fnc); fnc.Print(); } } Name=Ivan Surname=Ivanov Middle=Ivanovich Name=Petr Surname=Petrov Middle=Petrovich Name=Ivan Surname=Ivanov Middle=Ivanovich
  • 89. http://www.slideshare.net/IgorShkulipa 89 Паттерн «Стратегия» Паттерн Стратегия (Strategy) предназначен для определения семейства алгоритмов и инкапсуляции каждого из них и обеспечения их взаимозаменяемости. Переносит в отдельную иерархию классов все детали, связанные с реализацией алгоритмов.
  • 90. http://www.slideshare.net/IgorShkulipa 90 Пример public abstract class IStrategy { public abstract void Use(); protected void WakeUp() { Console.WriteLine("Wake up."); } protected void Shower() { Console.WriteLine("Take shower."); } protected void Dress() { Console.WriteLine("Dress."); } protected void GoToBusStop() { Console.WriteLine("Go to bus stop."); } protected void Wait() { Console.WriteLine("Wait."); } protected void Arrive() { Console.WriteLine("Arrive."); } protected void DoWork() { Console.WriteLine("Do work."); } protected void DoExercises() { Console.WriteLine("Do exercises."); } protected void Walk() { Console.WriteLine("Walk."); } protected void GoOut() { Console.WriteLine("Go out."); } protected void GoToPark() { Console.WriteLine("Go to park."); } }
  • 91. http://www.slideshare.net/IgorShkulipa 91 Классы конкретных стратегий class GoToWorkStrategy : Istrategy { public override void Use() { WakeUp(); Shower(); Dress(); GoOut(); GoToBusStop(); Wait(); Arrive(); DoWork(); } } class GoWalkStrategy : Istrategy { public override void Use() { GoOut(); GoToPark(); Walk(); } } class GoToGymStrategy : Istrategy { public override void Use() { GoOut(); GoToBusStop(); Arrive(); DoExercises(); } }
  • 92. http://www.slideshare.net/IgorShkulipa 92 Клиент стратегий public abstract class IStrategyClient { public abstract void UseStrategy(); public void SetStrategy(IStrategy st) { strategy = st; } protected IStrategy strategy; } class StrategyClient1 : IStrategyClient { public StrategyClient1() { } public override void UseStrategy() { strategy.Use(); } }
  • 93. http://www.slideshare.net/IgorShkulipa 93 Использование стратегий class Program { static void Main(string[] args) { IStrategyClient stClient = new StrategyClient1(); stClient.SetStrategy(new GoToWorkStrategy()); stClient.UseStrategy(); Console.WriteLine(); stClient.SetStrategy(new GoToGymStrategy()); stClient.UseStrategy(); Console.WriteLine(); stClient.SetStrategy(new GoWalkStrategy()); stClient.UseStrategy(); Console.ReadKey(); } } Wake up. Take shower. Dress. Go out. Go to bus stop. Wait. Arrive. Do work. Go out. Go to bus stop. Arrive. Do exercises. Go out. Go to park. Walk.
  • 94. http://www.slideshare.net/IgorShkulipa 94 Анонимные методы Новый класс стратегий: public delegate void StrategyDelegate(); public abstract class IStrategyClient { public abstract void UseStrategy(); public StrategyDelegate Strategy { get; set; } } class StrategyClient1 : IStrategyClient { public StrategyClient1() { } public override void UseStrategy() { Strategy(); } }
  • 95. http://www.slideshare.net/IgorShkulipa 95 Использование анонимных методов class Program { static void Main(string[] args) { IStrategyClient stClient = new StrategyClient1(); IStrategy goWork = new GoToWorkStrategy(); IStrategy goGym = new GoToGymStrategy(); IStrategy goWalk = new GoWalkStrategy(); stClient.Strategy = delegate { Console.WriteLine("Anonymous Method:"); goWork.Use(); Console.WriteLine(); }; stClient.UseStrategy(); stClient.Strategy = delegate { Console.WriteLine("Anonymous Method:"); goGym.Use(); Console.WriteLine(); }; stClient.UseStrategy(); stClient.Strategy = delegate { Console.WriteLine("Anonymous Method:"); goWalk.Use(); Console.WriteLine(); }; stClient.UseStrategy(); Console.ReadKey(); } } Anonymous Method: Wake up. Take shower. Dress. Go out. Go to bus stop. Wait. Arrive. Do work. Anonymous Method: Go out. Go to bus stop. Arrive. Do exercises. Anonymous Method: Go out. Go to park. Walk.
  • 96. http://www.slideshare.net/IgorShkulipa 96 Шаблон проектирования «Visitor» Паттерн Visitor определяет операцию, выполняемую на каждом элементе из некоторой структуры без изменения классов этих объектов. • Паттерн Visitor определяет операцию, выполняемую на каждом элементе из некоторой структуры. Позволяет, не изменяя классы этих объектов, добавлять в них новые операции. Применение расширяющих методов значительно упрощает реализацию этого паттерна.
  • 97. http://www.slideshare.net/IgorShkulipa 97 Классы «компонентов» public class SomeClass1 { public SomeClass1(int c) { SomeProperty1 = c; } public int SomeProperty1 { get; set; } } public class SomeClass2 { public SomeClass2(int c) { SomeProperty2 = c; } public int SomeProperty2 { get; set; } } public class SomeClass3 { public SomeClass3(int c) { SomeProperty3 = c; } public int SomeProperty3 { get; set; } }
  • 98. http://www.slideshare.net/IgorShkulipa 98 Класс-посетитель public static class Visitor { public static void Visit(this SomeClass1 sc1) { Console.WriteLine(sc1.SomeProperty1); } public static void Visit(this SomeClass2 sc2) { Console.WriteLine(sc2.SomeProperty2); } public static void Visit(this SomeClass3 sc3) { Console.WriteLine(sc3.SomeProperty3); } }
  • 99. http://www.slideshare.net/IgorShkulipa 99 Использование class Program { static void Main(string[] args) { SomeClass1 c1 = new SomeClass1(1); SomeClass2 c2 = new SomeClass2(2); SomeClass3 c3 = new SomeClass3(3); c1.Visit(); c2.Visit(); c3.Visit(); Console.ReadKey(); } } 1 2 3
  • 100. http://www.slideshare.net/IgorShkulipa 100 Расширяющие методы Расширяющие методы (методы расширения) позволяют "добавлять" методы в существующие типы без создания нового производного типа, перекомпиляции или иного изменения исходного типа. Расширяющие методы являются особым видом статического метода, но они вызываются, как если бы они были методами экземпляра в расширенном типе. Для клиентского кода, написанного на языках C#, нет видимого различия между вызовом метода расширения и вызовом методов, фактически определенных в типе. public static class MyExtensions { public static int WordCount(this String str) { return str.Split(new char[] { ' ', '.', '?' }, StringSplitOptions.RemoveEmptyEntries).Length; } } Методы расширения определяются как статические методы, но вызываются с помощью синтаксиса обращения к методу экземпляра. Их первый параметр определяет, с каким типом оперирует метод, и перед параметром идет модификатор this. Методы расширения находятся в области действия, только если пространство имен было явно импортировано в исходный код с помощью директивы using.
  • 101. http://www.slideshare.net/IgorShkulipa 101 Пример расширяющих методов public static class ExtensionMethods { public static double Angle(this Complex compl) { if ((compl.Re == 0) && (compl.Im >= 0)) { return Math.PI / 2; } if ((compl.Re == 0) && (compl.Im < 0)) { return 3 * Math.PI / 2; } return Math.Atan(compl.Im / compl.Re); } } class Program { static void Main(string[] args) { Complex c1 = new Complex(1,2); Console.WriteLine(c1); double angle = c1.Angle(); Console.WriteLine(angle); Console.ReadKey(); } }
  • 103. http://www.slideshare.net/IgorShkulipa 103 MVC Шаблон проектирования MVC разделяет работу веб-приложения на три отдельные функциональные роли: • модель данных (model) • пользовательский интерфейс (view) • управляющую логику (controller) Таким образом, изменения, вносимые в один из компонентов, оказывают минимально возможное воздействие на другие компоненты.
  • 104. http://www.slideshare.net/IgorShkulipa 104 MVP • Модель (model) представляет собой интерфейс, определяющий данные для отображения или участвующие в пользовательском интерфейсе иным образом • Вид (view) - это интерфейс, который отображает данные (модель) и маршрутизирует пользовательские команды (или события) Presenter-у, чтобы тот действовал над этими данными. • Presenter действует над моделью и видом. Он извлекает данные из хранилища (модели), и форматирует их для отображения в Виде (view). Так же реализует обработку событий вида.
  • 106. http://www.slideshare.net/IgorShkulipa 106 Архитектурный паттерн MVVM • Модель (Model), так же, как в классическом паттерне MVC, Модель представляет собой фундаментальные данные, необходимые для работы приложения (классы, структуры). • Вид/Представление (View) так же, как в классическом паттерне MVC, Вид — это графический интерфейс, то есть окно, кнопки и.т.п. • Модель вида (ViewModel, что означает «Model of View») является с одной стороны абстракцией Вида, а с другой предоставляет обертку данных из Модели, которые подлежат связыванию. То есть она содержит Модель, которая преобразована к Виду, а так же содержит в себе команды, которыми может пользоваться Вид, чтобы влиять на Модель.