Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 4f48659

Browse files
2 parents 21a989b + 495215e commit 4f48659

File tree

1 file changed

+117
-2
lines changed

1 file changed

+117
-2
lines changed

‎README.md‎

Lines changed: 117 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
2. [Одиночка (Singleton)](#Одиночка)
1616
3. [Строитель (Builder)](#Строитель)
1717
4. [Прототип (Prototype)](#Прототип)
18+
5. [Фабричный метод (Factory Method)](#Фабричный-метод)
1819
2. [Структурные паттерны](#Структурные-паттерны)
1920
1. [Адаптер (Adapter)](#Адаптер)
2021
2. [Декоратор (Decorator)](#Декоратор)
@@ -265,7 +266,7 @@ public class SectionDatabase
265266

266267
return Database;
267268
}
268-
}
269+
}
269270
```
270271
:white_check_mark: __Преимущества паттерна Singleton__: класс гарантированно имеет только один экземпляр и не более, у нас есть точка доступа к единственному экземпляру (в нашем случае это метод Initialize) <br>
271272
:x: __Недостатки__: нарушение принципа единой ответственности (Single Responsibility Principle), требуется особая обработка в многопоточной среде.
@@ -467,7 +468,120 @@ public class Director
467468
:x: __Недостатки__: жесткая связка конкретного Builder и продукта, который он создает.
468469
___
469470
### Прототип
470-
__Прототип (Prototype)__ - это такой паттерн, который используется ​для создания новых объектов с помощью клонирования существующих.
471+
__Прототип (Prototype)__ - это такой паттерн, который используется ​для создания новых объектов с помощью клонирования существующих. Для того, чтобы определение паттерна было более понятно, приведу конкретный пример.<br>
472+
Предположим, что у нас есть биржа фриланса, где есть заказчики и исполнители.<br>
473+
:one: Для начала создадим абстрактный класс User - пользователь биржи фриланса. У пользователя будут идентификатор, ФИО и абстрактный метод Clone. Это означает, что мы обязательно должны реализовать его в классе-наследнике.
474+
```C#
475+
/// <summary>
476+
/// Пользователь
477+
/// </summary>
478+
public abstract class User
479+
{
480+
/// <summary>
481+
/// Идентификатор.
482+
/// </summary>
483+
public int Id { get; set; }
484+
485+
/// <summary>
486+
/// Имя.
487+
/// </summary>
488+
public string FirstName { get; set; }
489+
490+
/// <summary>
491+
/// Фамилия.
492+
/// </summary>
493+
public string LastName { get; set; }
494+
495+
/// <summary>
496+
/// Отчество.
497+
/// </summary>
498+
public string Patronymic { get; set; }
499+
500+
/// <summary>
501+
/// Клонирование пользователя.
502+
/// </summary>
503+
/// <returns>Нового пользователя.</returns>
504+
public abstract User Clone();
505+
506+
/// <summary>
507+
/// Строковое представления объекта пользователя.
508+
/// </summary>
509+
/// <returns>Данные пользователя в виде строки.</returns>
510+
public override string ToString() => $"Идентификатор - {Id} Имя - {FirstName} Фамилия - {LastName} Отчество - {Patronymic}";
511+
}
512+
```
513+
:two: Теперь реализуем класс-наследник исполнителя: в него не будем добавлять дополнительные свойства. Реализация метода Clone будет выглядеть так:
514+
```C#
515+
/// <summary>
516+
/// Исполнитель.
517+
/// </summary>
518+
public class Executor : User
519+
{
520+
/// <summary>
521+
/// Клонирование пользователя.
522+
/// </summary>
523+
/// <returns>Нового пользователя.</returns>
524+
public override User Clone() => (Executor)MemberwiseClone();
525+
526+
/// <summary>
527+
/// Строковое представления объекта исполнителя.
528+
/// </summary>
529+
/// <returns>Данные исполнителя в виде строки.</returns>
530+
public override string ToString() => $"Данные исполнителя: {base.ToString()}";
531+
}
532+
```
533+
> В данном случае мы можем выполнить неполное (поверхностное) копирование. Это подходит тогда, когда у нас все поля Executor являются значимыми типами (исключение: string).
534+
535+
Теперь рассмотрим второй класс-наследник: Customer.
536+
```C#
537+
/// <summary>
538+
/// Заказчик
539+
/// </summary>
540+
public class Customer : User
541+
{
542+
/// <summary>
543+
/// Паспорт.
544+
/// </summary>
545+
public Passport Passport { get; set; }
546+
547+
/// <summary>
548+
/// Создание пользователя.
549+
/// </summary>
550+
public Customer()
551+
{
552+
Passport = new Passport();
553+
}
554+
555+
/// <summary>
556+
/// Клонирование пользователя.
557+
/// </summary>
558+
/// <returns>Нового пользователя.</returns>
559+
public override User Clone()
560+
{
561+
var customer = (Customer)MemberwiseClone();
562+
customer.Passport = new Passport();
563+
customer.Passport.Series = Passport.Series;
564+
customer.Passport.Number = Passport.Number;
565+
customer.Passport.ReceiptPlace = Passport.ReceiptPlace;
566+
567+
return customer;
568+
}
569+
570+
/// <summary>
571+
/// Строковое представления объекта заказчика.
572+
/// </summary>
573+
/// <returns>Данные заказчика в виде строки.</returns>
574+
public override string ToString() => $"Данные заказчика: {base.ToString()} {Passport}";
575+
}
576+
```
577+
> Здесь у нас уже присутствует класс Passport - это ссылочный тип, соответсвенно, мы не можем использовать неполное копирование. Если мы будем использовать неполное копирование, то у нас будет два заказчика ссылаться на один и тот же объект паспортных данных. Поэтому нам придется создать новый объект паспорта и вручную его проинициализировать.
578+
579+
Также, чтобы убедиться в том, что у нас создаются два абсолютно разных объекта, которые не ссылаются на одни и те же поля, рекомендую запустить тесты в проекте PrototypeTests, где происходит данная проверка.<br><br>
580+
:white_check_mark: __Преимущества паттерна Prototype__: клонирование объектов без привязки к конкретным классам, сокращение кода инициализации экземплятор классов<br>
581+
:x: __Недостатки__: Проблемы с клонированием составных объектов, то есть, тех объектов, которые внутри содержат другие объекты.
582+
___
583+
### Фабричный метод
584+
__Фабричный метод (Factory Method)__ -
471585
## Структурные паттерны
472586
__Структурные паттерны__ (Structural) - цель их применения заключается в том, что благодаря им вы можете совмещать и сочетать сущности вместе.
473587
___
@@ -999,6 +1113,7 @@ public class User : IObserver<Message>
9991113
Console.WriteLine($"Полученное уведомление: {Environment.NewLine}{value}{Environment.NewLine}" +
10001114
$"Логин получателя: {_login}");
10011115
}
1116+
}
10021117
```
10031118
:three: Теперь создадим класс нашего корпоративного портала, реализующий интерфейс IObservable (наблюдаемый объект). В качестве параметра также выступает тип данных Message - тип сообщения для подписчиков.
10041119
```C#

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /