1.0
Main
This commit is contained in:
commit
3a28caed27
63
.gitattributes
vendored
Normal file
63
.gitattributes
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
###############################################################################
|
||||
# Set default behavior to automatically normalize line endings.
|
||||
###############################################################################
|
||||
* text=auto
|
||||
|
||||
###############################################################################
|
||||
# Set default behavior for command prompt diff.
|
||||
#
|
||||
# This is need for earlier builds of msysgit that does not have it on by
|
||||
# default for csharp files.
|
||||
# Note: This is only used by command line
|
||||
###############################################################################
|
||||
#*.cs diff=csharp
|
||||
|
||||
###############################################################################
|
||||
# Set the merge driver for project and solution files
|
||||
#
|
||||
# Merging from the command prompt will add diff markers to the files if there
|
||||
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||
# the diff markers are never inserted). Diff markers may cause the following
|
||||
# file extensions to fail to load in VS. An alternative would be to treat
|
||||
# these files as binary and thus will always conflict and require user
|
||||
# intervention with every merge. To do so, just uncomment the entries below
|
||||
###############################################################################
|
||||
#*.sln merge=binary
|
||||
#*.csproj merge=binary
|
||||
#*.vbproj merge=binary
|
||||
#*.vcxproj merge=binary
|
||||
#*.vcproj merge=binary
|
||||
#*.dbproj merge=binary
|
||||
#*.fsproj merge=binary
|
||||
#*.lsproj merge=binary
|
||||
#*.wixproj merge=binary
|
||||
#*.modelproj merge=binary
|
||||
#*.sqlproj merge=binary
|
||||
#*.wwaproj merge=binary
|
||||
|
||||
###############################################################################
|
||||
# behavior for image files
|
||||
#
|
||||
# image files are treated as binary by default.
|
||||
###############################################################################
|
||||
#*.jpg binary
|
||||
#*.png binary
|
||||
#*.gif binary
|
||||
|
||||
###############################################################################
|
||||
# diff behavior for common document formats
|
||||
#
|
||||
# Convert binary document formats to text before diffing them. This feature
|
||||
# is only available from the command line. Turn it on by uncommenting the
|
||||
# entries below.
|
||||
###############################################################################
|
||||
#*.doc diff=astextplain
|
||||
#*.DOC diff=astextplain
|
||||
#*.docx diff=astextplain
|
||||
#*.DOCX diff=astextplain
|
||||
#*.dot diff=astextplain
|
||||
#*.DOT diff=astextplain
|
||||
#*.pdf diff=astextplain
|
||||
#*.PDF diff=astextplain
|
||||
#*.rtf diff=astextplain
|
||||
#*.RTF diff=astextplain
|
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
.vs
|
||||
Patterns/bin
|
||||
Patterns/obj
|
121
LICENSE
Normal file
121
LICENSE
Normal file
@ -0,0 +1,121 @@
|
||||
Creative Commons Legal Code
|
||||
|
||||
CC0 1.0 Universal
|
||||
|
||||
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
|
||||
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
|
||||
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
|
||||
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
|
||||
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
|
||||
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
|
||||
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
|
||||
HEREUNDER.
|
||||
|
||||
Statement of Purpose
|
||||
|
||||
The laws of most jurisdictions throughout the world automatically confer
|
||||
exclusive Copyright and Related Rights (defined below) upon the creator
|
||||
and subsequent owner(s) (each and all, an "owner") of an original work of
|
||||
authorship and/or a database (each, a "Work").
|
||||
|
||||
Certain owners wish to permanently relinquish those rights to a Work for
|
||||
the purpose of contributing to a commons of creative, cultural and
|
||||
scientific works ("Commons") that the public can reliably and without fear
|
||||
of later claims of infringement build upon, modify, incorporate in other
|
||||
works, reuse and redistribute as freely as possible in any form whatsoever
|
||||
and for any purposes, including without limitation commercial purposes.
|
||||
These owners may contribute to the Commons to promote the ideal of a free
|
||||
culture and the further production of creative, cultural and scientific
|
||||
works, or to gain reputation or greater distribution for their Work in
|
||||
part through the use and efforts of others.
|
||||
|
||||
For these and/or other purposes and motivations, and without any
|
||||
expectation of additional consideration or compensation, the person
|
||||
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
|
||||
is an owner of Copyright and Related Rights in the Work, voluntarily
|
||||
elects to apply CC0 to the Work and publicly distribute the Work under its
|
||||
terms, with knowledge of his or her Copyright and Related Rights in the
|
||||
Work and the meaning and intended legal effect of CC0 on those rights.
|
||||
|
||||
1. Copyright and Related Rights. A Work made available under CC0 may be
|
||||
protected by copyright and related or neighboring rights ("Copyright and
|
||||
Related Rights"). Copyright and Related Rights include, but are not
|
||||
limited to, the following:
|
||||
|
||||
i. the right to reproduce, adapt, distribute, perform, display,
|
||||
communicate, and translate a Work;
|
||||
ii. moral rights retained by the original author(s) and/or performer(s);
|
||||
iii. publicity and privacy rights pertaining to a person's image or
|
||||
likeness depicted in a Work;
|
||||
iv. rights protecting against unfair competition in regards to a Work,
|
||||
subject to the limitations in paragraph 4(a), below;
|
||||
v. rights protecting the extraction, dissemination, use and reuse of data
|
||||
in a Work;
|
||||
vi. database rights (such as those arising under Directive 96/9/EC of the
|
||||
European Parliament and of the Council of 11 March 1996 on the legal
|
||||
protection of databases, and under any national implementation
|
||||
thereof, including any amended or successor version of such
|
||||
directive); and
|
||||
vii. other similar, equivalent or corresponding rights throughout the
|
||||
world based on applicable law or treaty, and any national
|
||||
implementations thereof.
|
||||
|
||||
2. Waiver. To the greatest extent permitted by, but not in contravention
|
||||
of, applicable law, Affirmer hereby overtly, fully, permanently,
|
||||
irrevocably and unconditionally waives, abandons, and surrenders all of
|
||||
Affirmer's Copyright and Related Rights and associated claims and causes
|
||||
of action, whether now known or unknown (including existing as well as
|
||||
future claims and causes of action), in the Work (i) in all territories
|
||||
worldwide, (ii) for the maximum duration provided by applicable law or
|
||||
treaty (including future time extensions), (iii) in any current or future
|
||||
medium and for any number of copies, and (iv) for any purpose whatsoever,
|
||||
including without limitation commercial, advertising or promotional
|
||||
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
|
||||
member of the public at large and to the detriment of Affirmer's heirs and
|
||||
successors, fully intending that such Waiver shall not be subject to
|
||||
revocation, rescission, cancellation, termination, or any other legal or
|
||||
equitable action to disrupt the quiet enjoyment of the Work by the public
|
||||
as contemplated by Affirmer's express Statement of Purpose.
|
||||
|
||||
3. Public License Fallback. Should any part of the Waiver for any reason
|
||||
be judged legally invalid or ineffective under applicable law, then the
|
||||
Waiver shall be preserved to the maximum extent permitted taking into
|
||||
account Affirmer's express Statement of Purpose. In addition, to the
|
||||
extent the Waiver is so judged Affirmer hereby grants to each affected
|
||||
person a royalty-free, non transferable, non sublicensable, non exclusive,
|
||||
irrevocable and unconditional license to exercise Affirmer's Copyright and
|
||||
Related Rights in the Work (i) in all territories worldwide, (ii) for the
|
||||
maximum duration provided by applicable law or treaty (including future
|
||||
time extensions), (iii) in any current or future medium and for any number
|
||||
of copies, and (iv) for any purpose whatsoever, including without
|
||||
limitation commercial, advertising or promotional purposes (the
|
||||
"License"). The License shall be deemed effective as of the date CC0 was
|
||||
applied by Affirmer to the Work. Should any part of the License for any
|
||||
reason be judged legally invalid or ineffective under applicable law, such
|
||||
partial invalidity or ineffectiveness shall not invalidate the remainder
|
||||
of the License, and in such case Affirmer hereby affirms that he or she
|
||||
will not (i) exercise any of his or her remaining Copyright and Related
|
||||
Rights in the Work or (ii) assert any associated claims and causes of
|
||||
action with respect to the Work, in either case contrary to Affirmer's
|
||||
express Statement of Purpose.
|
||||
|
||||
4. Limitations and Disclaimers.
|
||||
|
||||
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
||||
surrendered, licensed or otherwise affected by this document.
|
||||
b. Affirmer offers the Work as-is and makes no representations or
|
||||
warranties of any kind concerning the Work, express, implied,
|
||||
statutory or otherwise, including without limitation warranties of
|
||||
title, merchantability, fitness for a particular purpose, non
|
||||
infringement, or the absence of latent or other defects, accuracy, or
|
||||
the present or absence of errors, whether or not discoverable, all to
|
||||
the greatest extent permissible under applicable law.
|
||||
c. Affirmer disclaims responsibility for clearing rights of other persons
|
||||
that may apply to the Work or any use thereof, including without
|
||||
limitation any person's Copyright and Related Rights in the Work.
|
||||
Further, Affirmer disclaims responsibility for obtaining any necessary
|
||||
consents, permissions or other rights required for any use of the
|
||||
Work.
|
||||
d. Affirmer understands and acknowledges that Creative Commons is not a
|
||||
party to this document and has no duty or obligation with respect to
|
||||
this CC0 or use of the Work.
|
11
Patterns/1_Принцип единственной обязанности/1_Принцип единственной обязанности.csproj
Normal file
11
Patterns/1_Принцип единственной обязанности/1_Принцип единственной обязанности.csproj
Normal file
@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<RootNamespace>_1_Принцип_единственной_обязанности</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
71
Patterns/1_Принцип единственной обязанности/Program.cs
Normal file
71
Patterns/1_Принцип единственной обязанности/Program.cs
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Глава 17: Принцип единственной обязанности (SOLID SRP)
|
||||
*
|
||||
* - инкапсуляция сущности с целью организации архитектуры
|
||||
* приложения, которую будет легко поддерживать и расширять в
|
||||
* течении всего промежутка эксплуатации
|
||||
*
|
||||
* Автор: Роберт Мартин (Дядя Боб)
|
||||
*
|
||||
* Принципы:
|
||||
* 1. Single responsibility - принцип единственной ответственности
|
||||
* 2. Open-closed - принцип открытости/закрытости
|
||||
* 3. Liskov substitution - принцип подстановки Барбары Лисков (самый сложный)
|
||||
* 4. Interface Segregation - принцип разделения интерфейса
|
||||
* 5. Dependency inversion - принцип инверсии зависисмостей
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Принцип единственной ответственности (англ. single-responsibility principle, SPR) -
|
||||
* принцип ООП, обозначающий, что каждый объект должен иметь одну ответственность и эта
|
||||
* ответственность должна быть полностью инкапсулирована в класс.
|
||||
* Все его поведения должны быть направлены исключительно на обеспечение этой отвественности.
|
||||
*/
|
||||
/// <summary>
|
||||
/// К примеру: Разработать класс который будет работать с изображениями
|
||||
/// </summary>
|
||||
abstract class Attach
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
class Image : Attach
|
||||
{
|
||||
private int width;
|
||||
private int height;
|
||||
public int Width => width;
|
||||
public int Height => height;
|
||||
private Image(int width, int height) { }
|
||||
//Добавление других методов предполагающих иной функционал не рационально
|
||||
//Следуем принципу - декомпозировать - делать максимально минимальные классы под свою ответственность
|
||||
public static Image CreateImage(int width, int height) { return new Image(width, height); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// EMail сервис
|
||||
/// Если отваливается модуль отправки Email
|
||||
/// мы чиним только его, нам не требуется разбирать класс Image
|
||||
/// </summary>
|
||||
class EmailService
|
||||
{
|
||||
private string email;
|
||||
private string text;
|
||||
private string subject;
|
||||
private Attach[] attach;
|
||||
public EmailService(string email,
|
||||
string text = "",
|
||||
string subject = "",
|
||||
params Attach[] args)
|
||||
{ }
|
||||
public void SendTo(string email, string text, string subject) { }
|
||||
}
|
||||
|
||||
|
||||
class Program
|
||||
{
|
||||
public static void Main(string[] argv)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<RootNamespace>_2_Принцип_открытости__закрытости</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
55
Patterns/2_Принцип открытости, закрытости/Program.cs
Normal file
55
Patterns/2_Принцип открытости, закрытости/Program.cs
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Глава 18: Принцип открытости/закрытости (SOLID SRP)
|
||||
*
|
||||
* Автор: Роберт Мартин (Дядя Боб)
|
||||
*
|
||||
* Постулаты:
|
||||
* - если какая-то сущность описана, то она уже
|
||||
* полностью закрыта для каких либо изменений;
|
||||
* - сущность открыта для модификаций;
|
||||
*
|
||||
* Принципы:
|
||||
* 1. Single responsibility - принцип единственной ответственности
|
||||
* 2. Open-closed - принцип открытости/закрытости
|
||||
* 3. Liskov substitution - принцип подстановки Барбары Лисков (самый сложный)
|
||||
* 4. Interface Segregation - принцип разделения интерфейса
|
||||
* 5. Dependency inversion - принцип инверсии зависисмостей
|
||||
*/
|
||||
public abstract class Attach
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class Image : Attach
|
||||
{
|
||||
private int width;
|
||||
private int height;
|
||||
public int Width => width;
|
||||
public int Height => height;
|
||||
private Image(int width, int height) { }
|
||||
private Image(int width, int height, ISave save) { }
|
||||
public static Image CreateImage(int width, int height) { return new Image(width, height); }
|
||||
public static Image CreateImage(int width, int height, ISave save) { return new Image(width, height, save); }
|
||||
public void SaveToFile(string path) { }
|
||||
}
|
||||
|
||||
public interface ISave
|
||||
{
|
||||
ISave SaveTo(string path);
|
||||
}
|
||||
|
||||
public class SaveToBmp : ISave
|
||||
{
|
||||
public ISave SaveTo(string path)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] argv)
|
||||
{
|
||||
Image.CreateImage(100, 100, new SaveToBmp().SaveTo(""));
|
||||
}
|
||||
}
|
11
Patterns/3_Принцип подстановки Барбары Лисков/3_Принцип подстановки Барбары Лисков.csproj
Normal file
11
Patterns/3_Принцип подстановки Барбары Лисков/3_Принцип подстановки Барбары Лисков.csproj
Normal file
@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<RootNamespace>_3_Принцип_подстановки_Барбары_Лисков</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
127
Patterns/3_Принцип подстановки Барбары Лисков/Program.cs
Normal file
127
Patterns/3_Принцип подстановки Барбары Лисков/Program.cs
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Глава 19: Принцип подстановки Барбары Лисков (SOLID SRP)
|
||||
*
|
||||
* Автор: Роберт Мартин (Дядя Боб)
|
||||
*
|
||||
* Сам принцип:
|
||||
* - Пусть Q(x) является свойством, верным относительно объектов x некоторого
|
||||
* типа T. Тогда Q(y) также должно быть верным для объектов y типа S, где S является подтипом T.
|
||||
*
|
||||
* или
|
||||
*
|
||||
* - Функции, которые используют базовый тип, должны иметь возможность использовать подтипы базового типа, не зная об этом.
|
||||
* Поведение классов-наследников не должно противоречить поведению, заданному базовым классом
|
||||
*
|
||||
* Принципы:
|
||||
* 1. Single responsibility - принцип единственной ответственности
|
||||
* 2. Open-closed - принцип открытости/закрытости
|
||||
* 3. Liskov substitution - принцип подстановки Барбары Лисков (самый сложный)
|
||||
* 4. Interface Segregation - принцип разделения интерфейса
|
||||
* 5. Dependency inversion - принцип инверсии зависисмостей
|
||||
*/
|
||||
|
||||
public class Coordinates
|
||||
{
|
||||
public int Longtitude { get; set; }
|
||||
public int Latitude { get; set; }
|
||||
public override string ToString()
|
||||
{
|
||||
return $"Широта: {Longtitude} Долгота: {Latitude}";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Шаблон летающей птицы
|
||||
/// </summary>
|
||||
public class Bird
|
||||
{
|
||||
protected Random rand;
|
||||
public Coordinates Position { get; set; }
|
||||
protected int speed, spacing;
|
||||
public int Spacing { get => spacing; }
|
||||
|
||||
public Bird()
|
||||
{
|
||||
Position = new Coordinates();
|
||||
rand = new Random();
|
||||
}
|
||||
|
||||
protected void Mark(int x, int y) { }
|
||||
|
||||
/// <summary>
|
||||
/// Полёт птицы
|
||||
/// </summary>
|
||||
private void Fly()
|
||||
{
|
||||
speed = 1;
|
||||
switch (rand.Next(2))
|
||||
{
|
||||
case 0: Position.Latitude += speed; break;
|
||||
default: Position.Longtitude += speed; break;
|
||||
}
|
||||
spacing++;
|
||||
Console.SetCursorPosition(Position.Latitude, Position.Longtitude);
|
||||
Console.WriteLine("B");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Движение птицы
|
||||
/// </summary>
|
||||
public virtual void Move()
|
||||
{
|
||||
Fly();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Шаблон бегущей птицы
|
||||
/// </summary>
|
||||
public class Kiwi : Bird
|
||||
{
|
||||
private void Run()
|
||||
{
|
||||
speed = 1;
|
||||
switch (rand.Next(2, 6))
|
||||
{
|
||||
case 3: Position.Latitude += speed; break;
|
||||
default: Position.Longtitude += speed; break;
|
||||
}
|
||||
spacing++;
|
||||
Console.SetCursorPosition(Position.Latitude, Position.Longtitude);
|
||||
Console.WriteLine("K");
|
||||
}
|
||||
|
||||
public override void Move()
|
||||
{
|
||||
Run();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Шаблон отображеня движения
|
||||
/// </summary>
|
||||
class CalculatingDistance
|
||||
{
|
||||
private int time;
|
||||
public CalculatingDistance(int time) { this.time = time; }
|
||||
public void Calculate(Bird bird)
|
||||
{
|
||||
for (int i = 0; i < time; i++)
|
||||
{
|
||||
bird.Move();
|
||||
}
|
||||
Console.Title = ($"\n\n\nРасстояние: {bird.Spacing} {bird.Position}");
|
||||
}
|
||||
}
|
||||
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] argv)
|
||||
{
|
||||
var bird = new Bird();
|
||||
new CalculatingDistance(10).Calculate(bird);
|
||||
var kiwi = new Kiwi();
|
||||
new CalculatingDistance(10).Calculate(kiwi);
|
||||
Console.ReadLine();
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<RootNamespace>_4_Принцип_разделения_интерфейсов</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
48
Patterns/4_Принцип разделения интерфейсов/Program.cs
Normal file
48
Patterns/4_Принцип разделения интерфейсов/Program.cs
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Глава 20: Принцип разделения интерфейсов (SOLID SRP)
|
||||
*
|
||||
* Автор: Роберт Мартин (Дядя Боб)
|
||||
*
|
||||
* Сам принцип:
|
||||
* - клиенты не должны зависеть от методов которые они не используют
|
||||
*
|
||||
* или
|
||||
*
|
||||
* - если какая-то сущность заявляет о своем функционале, то он должен работать
|
||||
*
|
||||
* или
|
||||
*
|
||||
* - от реализации исбыточных интерфейсов следует отказаться в пользу специфичных
|
||||
*
|
||||
* Принципы:
|
||||
* 1. Single responsibility - принцип единственной ответственности
|
||||
* 2. Open-closed - принцип открытости/закрытости
|
||||
* 3. Liskov substitution - принцип подстановки Барбары Лисков (самый сложный)
|
||||
* 4. Interface Segregation - принцип разделения интерфейса
|
||||
* 5. Dependency inversion - принцип инверсии зависисмостей
|
||||
*/
|
||||
public abstract class Car
|
||||
{
|
||||
public string Model { get; set; }
|
||||
public string Brand { get; set; }
|
||||
|
||||
public Car(string model, string name)
|
||||
{
|
||||
Model = model;
|
||||
Brand = name;
|
||||
}
|
||||
}
|
||||
|
||||
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
//!!! вместо огромного набора функций в одном интерфейсе !!!
|
||||
//!!! в случае если при наследовании от него множество функций не реализуется !!!
|
||||
//!!! нужно перейти в сторону множественного наследования интерфейсов под каждую из функций !!!
|
||||
//!!! или под каждый набор функций !!!
|
||||
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] argv)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<RootNamespace>_5_Принцип_инверсии_зависимостей</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
107
Patterns/5_Принцип инверсии зависимостей/Program.cs
Normal file
107
Patterns/5_Принцип инверсии зависимостей/Program.cs
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Глава 21: Принцип инверсии зависимостей (SOLID SRP)
|
||||
*
|
||||
* Автор: Роберт Мартин (Дядя Боб)
|
||||
*
|
||||
* Сам принцип:
|
||||
*
|
||||
* - Модули верхних уровней не должны зависеть от модулей нижних уровней
|
||||
* (Оба типа должны зависеть от абстракций)
|
||||
*
|
||||
* - Абстракции не должны зависеть от деталей
|
||||
* (Детали должны зависеть от абстракций)
|
||||
*
|
||||
* Принципы:
|
||||
* 1. Single responsibility - принцип единственной ответственности
|
||||
* 2. Open-closed - принцип открытости/закрытости
|
||||
* 3. Liskov substitution - принцип подстановки Барбары Лисков (самый сложный)
|
||||
* 4. Interface Segregation - принцип разделения интерфейса
|
||||
* 5. Dependency inversion - принцип инверсии зависисмостей
|
||||
*/
|
||||
public class Person
|
||||
{
|
||||
public string FirstName { get; set; }
|
||||
public string LastName { get; set; }
|
||||
public int Age { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Поведение поиска в хранилищах информации
|
||||
/// </summary>
|
||||
public interface IFindStorage
|
||||
{
|
||||
List<Person> FindAll(Predicate<Person> predicate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Шаблон списка пользователей
|
||||
/// </summary>
|
||||
public class ListStorage : IFindStorage
|
||||
{
|
||||
private List<Person> storage;
|
||||
public ListStorage()
|
||||
{
|
||||
storage = new List<Person>();
|
||||
}
|
||||
|
||||
public List<Person> GetPersons() => storage;
|
||||
|
||||
public void Add(Person p) => storage.Add(p);
|
||||
|
||||
public List<Person> FindAll(Predicate<Person> predicate)
|
||||
{
|
||||
return storage.Where(e => predicate(e)).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Шаблон словаря пользователей
|
||||
/// </summary>
|
||||
public class DictionaryStorage : IFindStorage
|
||||
{
|
||||
private Dictionary<string, Person> storage;
|
||||
public DictionaryStorage()
|
||||
{
|
||||
storage = new Dictionary<string, Person>();
|
||||
}
|
||||
|
||||
public Dictionary<string, Person> GetPersons() => storage;
|
||||
|
||||
public void Add(string key, Person p) => storage.Add(key, p);
|
||||
|
||||
public List<Person> FindAll(Predicate<Person> predicate)
|
||||
{
|
||||
return storage.Where(e => predicate(e.Value)).Select(e => e.Value).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Щаблон поисковика
|
||||
/// </summary>
|
||||
public class SearchByAge
|
||||
{
|
||||
IFindStorage storage;
|
||||
public SearchByAge(IFindStorage storage) => this.storage = storage;
|
||||
public void Search()
|
||||
{
|
||||
foreach (var p in storage.FindAll(e => e.Age > 45))
|
||||
{
|
||||
Console.WriteLine($"{p.FirstName} {p.Age}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] argv)
|
||||
{
|
||||
Console.WriteLine("DictionaryStorage: ");
|
||||
var storageDict = new DictionaryStorage();
|
||||
storageDict.Add("1", new Person() { Age = 90 });
|
||||
new SearchByAge(storageDict).Search();
|
||||
Console.WriteLine("ListStorage: ");
|
||||
var storageList = new ListStorage();
|
||||
storageList.Add(new Person() { Age = 43 });
|
||||
new SearchByAge(storageList).Search();
|
||||
}
|
||||
}
|
10
Patterns/AbstractFactory/AbstractFactory.csproj
Normal file
10
Patterns/AbstractFactory/AbstractFactory.csproj
Normal file
@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
148
Patterns/AbstractFactory/Program.cs
Normal file
148
Patterns/AbstractFactory/Program.cs
Normal file
@ -0,0 +1,148 @@
|
||||
/* Абстрактная фабрика
|
||||
Предоставляет интерфейс для создания
|
||||
групп связанных или зависимых объектов,
|
||||
не указывая их конкретный класс
|
||||
*/
|
||||
class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
#region Пример №1 - базовое
|
||||
var soldier = new Hero(new SoldierFactory());
|
||||
soldier.Run();
|
||||
soldier.Hit();
|
||||
|
||||
var elf = new Hero(new ElfFactory());
|
||||
elf.Run();
|
||||
elf.Hit();
|
||||
|
||||
Console.ReadKey();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Оружие базовая логика
|
||||
/// </summary>
|
||||
abstract class Weapon
|
||||
{
|
||||
public abstract void Hit();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Движение базовая логика
|
||||
/// </summary>
|
||||
abstract class Movement
|
||||
{
|
||||
public abstract void Move();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Огнестрел
|
||||
/// </summary>
|
||||
class Gun : Weapon
|
||||
{
|
||||
public override void Hit()
|
||||
{
|
||||
Console.WriteLine("Hit Gun");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Арбалет
|
||||
/// </summary>
|
||||
class Arbalet : Weapon
|
||||
{
|
||||
public override void Hit()
|
||||
{
|
||||
Console.WriteLine("Hit Arbalet");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Герой летает
|
||||
/// </summary>
|
||||
class Fly : Movement
|
||||
{
|
||||
public override void Move()
|
||||
{
|
||||
Console.WriteLine("Hero Fly");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Герой бежит
|
||||
/// </summary>
|
||||
class Run : Movement
|
||||
{
|
||||
public override void Move()
|
||||
{
|
||||
Console.WriteLine("Hero Run");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Супергерой
|
||||
/// </summary>
|
||||
class Hero
|
||||
{
|
||||
private Weapon Weapon { get; set; }
|
||||
private Movement Movement { get; set; }
|
||||
|
||||
public Hero(HeroFactory factory)
|
||||
{
|
||||
Weapon = factory.CreateWeapon();
|
||||
Movement = factory.CreateMovement();
|
||||
}
|
||||
|
||||
public void Run()
|
||||
{
|
||||
Movement.Move();
|
||||
}
|
||||
|
||||
public void Hit()
|
||||
{
|
||||
Weapon.Hit();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Абстракция фабрика героев
|
||||
/// </summary>
|
||||
abstract class HeroFactory
|
||||
{
|
||||
public abstract Weapon CreateWeapon();
|
||||
public abstract Movement CreateMovement();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Эльфы
|
||||
/// </summary>
|
||||
class ElfFactory : HeroFactory
|
||||
{
|
||||
public override Movement CreateMovement()
|
||||
{
|
||||
return new Fly();
|
||||
}
|
||||
|
||||
public override Weapon CreateWeapon()
|
||||
{
|
||||
return new Arbalet();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Солдаты
|
||||
/// </summary>
|
||||
class SoldierFactory : HeroFactory
|
||||
{
|
||||
public override Movement CreateMovement()
|
||||
{
|
||||
return new Run();
|
||||
}
|
||||
|
||||
public override Weapon CreateWeapon()
|
||||
{
|
||||
return new Gun();
|
||||
}
|
||||
}
|
10
Patterns/Adapter/Adapter.csproj
Normal file
10
Patterns/Adapter/Adapter.csproj
Normal file
@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
78
Patterns/Adapter/Program.cs
Normal file
78
Patterns/Adapter/Program.cs
Normal file
@ -0,0 +1,78 @@
|
||||
/* Адаптер
|
||||
Конвенртирует интерфейс класса в другой интерфейс,
|
||||
ожидаемый клиентом. Позволяет классам
|
||||
с разными интерфейсами работать вместе.
|
||||
*/
|
||||
class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
#region Пример №1 - базовое
|
||||
var man = new Driver();
|
||||
var car = new Auto(); //машина она едет также как мотоцикл, всё отлично
|
||||
var camelTransport = //но мы хотим добраться на пешем транспорте (на верблюде)
|
||||
new CamelToTransport(new Camel());
|
||||
|
||||
man.Travel(camelTransport);
|
||||
man.Travel(car);
|
||||
|
||||
Console.ReadKey();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
interface ITransport
|
||||
{
|
||||
void Drive();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Шаблон автомобиля
|
||||
/// </summary>
|
||||
class Auto : ITransport
|
||||
{
|
||||
public void Drive()
|
||||
{
|
||||
Console.WriteLine(GetType().Name + " Move");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Шаблон верблюда
|
||||
/// </summary>
|
||||
class Camel
|
||||
{
|
||||
public void Move()
|
||||
{
|
||||
Console.WriteLine(GetType().Name + " Move");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Шаблон движения верблюда
|
||||
/// </summary>
|
||||
class CamelToTransport : ITransport
|
||||
{
|
||||
Camel camel;
|
||||
|
||||
public CamelToTransport(Camel camel)
|
||||
{
|
||||
this.camel = camel;
|
||||
}
|
||||
|
||||
public void Drive()
|
||||
{
|
||||
camel.Move();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Шаблон путешественника
|
||||
/// </summary>
|
||||
class Driver
|
||||
{
|
||||
public void Travel(ITransport transport)
|
||||
{
|
||||
transport.Drive();
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="2.2.10" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="2.2.10" />
|
||||
<PackageReference Include="coverlet.collector" Version="3.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
6
Patterns/Base.UserLibrary.Tests/TestData.xml
Normal file
6
Patterns/Base.UserLibrary.Tests/TestData.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<UserDetails>
|
||||
<User userId="Ivan" email="aspkx@mail.ru" />
|
||||
<User userId="Nikolay" email="aspkx@mail.ru" />
|
||||
<User userId="Oleg" email="aspkx@mail.ru" />
|
||||
</UserDetails>
|
31
Patterns/Base.UserLibrary.Tests/UnitTest1.cs
Normal file
31
Patterns/Base.UserLibrary.Tests/UnitTest1.cs
Normal file
@ -0,0 +1,31 @@
|
||||
namespace Base.UserLibrary.Tests
|
||||
{
|
||||
[TestClass]
|
||||
public class UnitTest1
|
||||
{
|
||||
private TestContext testContextInstance;
|
||||
public TestContext TestContextInstance
|
||||
{
|
||||
get { return testContextInstance; }
|
||||
set { testContextInstance = value; }
|
||||
}
|
||||
private UserManagerMsTest manager = new UserManagerMsTest();
|
||||
|
||||
/// <summary>
|
||||
/// DataSource - îïðåäåëåíèå èñòî÷íèêà äàííûõ
|
||||
/// 1 ïàðàìåòð - èìÿ ïðîâàéäåðà
|
||||
/// 2 ïàðàìåòð - ñòðîêà ïîäêëþ÷åíèÿ èëè ïóòü ê ôàéëó
|
||||
/// 3 ïàðàìåòð - èìÿ òàáëèöû èëè ýëåìåíòà XML
|
||||
/// 4 ïàðàìåòð - êàê ïðîèñõîäèò äîñòóï ê çàïèñÿì èç èñòî÷íèêà äàííûõ
|
||||
/// </summary>
|
||||
[DataSource("Microsoft.VisualStudio.TestTools.DataSource.XML",
|
||||
"TestData.xml",
|
||||
"User",
|
||||
DataAccessMethod.Sequential)]
|
||||
[TestMethod]
|
||||
public void AddDataTest()
|
||||
{
|
||||
string userId = Convert.ToString(TestContextInstance.DataRow["Row1"]);
|
||||
}
|
||||
}
|
||||
}
|
1
Patterns/Base.UserLibrary.Tests/Usings.cs
Normal file
1
Patterns/Base.UserLibrary.Tests/Usings.cs
Normal file
@ -0,0 +1 @@
|
||||
global using Microsoft.VisualStudio.TestTools.UnitTesting;
|
28
Patterns/Base.cs
Normal file
28
Patterns/Base.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using System;
|
||||
|
||||
public class Base
|
||||
|
||||
|
||||
//абстрактный класс
|
||||
abstract class AbstrTest
|
||||
{
|
||||
void Move()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//реализация по умолчанию
|
||||
public virtual void Resize()
|
||||
{
|
||||
|
||||
}
|
||||
void Declare();
|
||||
}
|
||||
|
||||
public class Class_Main : AbstrTest
|
||||
{
|
||||
public Class_Main()
|
||||
{
|
||||
Declare();
|
||||
}
|
||||
}
|
26
Patterns/Base/AssertMsTest.cs
Normal file
26
Patterns/Base/AssertMsTest.cs
Normal file
@ -0,0 +1,26 @@
|
||||
namespace Base;
|
||||
|
||||
public class AssertMsTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Получить квадратный корень
|
||||
/// </summary>
|
||||
/// <param name="value">Значение</param>
|
||||
/// <returns>double</returns>
|
||||
public static double GetSqrt(double value)
|
||||
{
|
||||
return Math.Sqrt(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получить приветствие
|
||||
/// </summary>
|
||||
/// <param name="name">Имя</param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ArgumentNullException">пустое имя</exception>
|
||||
public string SayHello(string name)
|
||||
{
|
||||
if (name == null) throw new ArgumentNullException("Parameter name can not be null");
|
||||
return "Hi! " + name;
|
||||
}
|
||||
}
|
14
Patterns/Base/BaseInfo.csproj
Normal file
14
Patterns/Base/BaseInfo.csproj
Normal file
@ -0,0 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
17
Patterns/Base/Extension.cs
Normal file
17
Patterns/Base/Extension.cs
Normal file
@ -0,0 +1,17 @@
|
||||
namespace Base
|
||||
{
|
||||
/// <summary>
|
||||
/// Тестовый класс статических реализаций
|
||||
/// </summary>
|
||||
internal static class Extension
|
||||
{
|
||||
/// <summary>
|
||||
/// Тестовый статический метод
|
||||
/// </summary>
|
||||
/// <param name="classMain">Представитель определённого поведения</param>
|
||||
public static void ResizeExt(this IInterTest classMain)
|
||||
{
|
||||
Console.WriteLine("Resize Class Extension");
|
||||
}
|
||||
}
|
||||
}
|
410
Patterns/Base/Program.cs
Normal file
410
Patterns/Base/Program.cs
Normal file
@ -0,0 +1,410 @@
|
||||
using Newtonsoft.Json;
|
||||
using static Base.Records;
|
||||
|
||||
namespace Base;
|
||||
|
||||
/// <summary>
|
||||
/// Важно: ссылочные типы лежат в куче, значимые - ссылка в куче, значение в стеке
|
||||
/// ***
|
||||
/// Шаблон, по которому определяется форма объекта
|
||||
/// Определение:
|
||||
/// Класс - это ссылочный тип данных, шаблон по которому определяется объект, информацию о себе хранит в куче.
|
||||
/// </summary>
|
||||
class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
var person = new Person() //реализация record сборки разборки
|
||||
{
|
||||
Id = 1,
|
||||
Name = "john"
|
||||
};
|
||||
Console.WriteLine(person.ToString());
|
||||
var job = new Job()
|
||||
{
|
||||
Ida = 786897980,
|
||||
Names = "Address"
|
||||
};
|
||||
Console.WriteLine(job.ToString());
|
||||
var gl = new GlobalInfo();
|
||||
person.Deconstruct(out gl.Name, out gl.Id);
|
||||
job.Deconstruct(out gl.Names, out gl.Ida);
|
||||
Console.WriteLine($"{gl.Name}/{gl.Names}/{gl.Id}/{gl.Ida}");
|
||||
|
||||
IInterTest interTest = new ClassMain();
|
||||
interTest.ResizeExt(); //методы static
|
||||
interTest.Relocate(); //метод объявлен и реализован в самом интерфейсе
|
||||
var Records = new Records(1, "rec1"); //экзмепляр Records (аналог class)
|
||||
var (NameS, idS) = Records; //можно разложить record на переменные
|
||||
var RecNew = Records with { Name = "rec2" };//можно инициализировать другой класс на основе данных первого
|
||||
Console.WriteLine($"{NameS} {idS}");
|
||||
var (NameS2, idS2) = RecNew; //можно разложить record на переменные
|
||||
Console.WriteLine($"{NameS2} {idS2}");
|
||||
Console.WriteLine(Records == RecNew); //можно сравнить record обычными операторами сравнения
|
||||
Console.WriteLine();
|
||||
Console.WriteLine(RecNew); //можно напечать JSON представление содержимого record по умолчанию
|
||||
Console.WriteLine(Records); //можно напечать JSON представление содержимого record по умолчанию
|
||||
var json = JsonConvert.SerializeObject(Records, Formatting.Indented);
|
||||
Console.WriteLine(json);
|
||||
var otherSideRecord = JsonConvert.DeserializeObject<Records>(json);
|
||||
Console.WriteLine(otherSideRecord);
|
||||
Records = Records with { Id = 10 };
|
||||
Console.WriteLine(Records);
|
||||
Console.ReadKey();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Абстракция которая отвечает за контракт взаимодействия для различных типов
|
||||
/// Определение:
|
||||
/// Интерфейс - это ссылочный тип данных, представляющий контракт взаимодействия (поведение).
|
||||
/// Этот контракт гласит о том что должен содержать class или struct.
|
||||
/// Формирует общий признак для разнородных объектов
|
||||
/// </summary>
|
||||
public interface IInterTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Декларация - метод без реализации по умолчанию
|
||||
/// </summary>
|
||||
/// <param name="build"></param>
|
||||
void Build(int build = 0);
|
||||
/// <summary>
|
||||
/// После C# 8.0 можно указывать реализацию метода в интерфейсе
|
||||
/// </summary>
|
||||
void Relocate()
|
||||
{
|
||||
Console.WriteLine("-> IInterTest: Relocate");
|
||||
}
|
||||
/// <summary>
|
||||
/// Cигнатура - операция без реализации - абстрактный метод
|
||||
/// </summary>
|
||||
abstract void Reload();
|
||||
/// <summary>
|
||||
/// Делегат - ссылочный тип
|
||||
/// </summary>
|
||||
delegate void Destiny();
|
||||
/// <summary>
|
||||
/// Cвойство - ссылочный тип
|
||||
/// </summary>
|
||||
string Name { get; set; }
|
||||
/// <summary>
|
||||
/// Cвойство - ссылочный тип
|
||||
/// </summary>
|
||||
object ID { get; set; }
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Абстрактный класс
|
||||
/// Определение:
|
||||
/// Абстрактный класс - это ссылочный тип данных, для описания общности сущностей, которые не имеют конкретного воплощения
|
||||
/// </summary>
|
||||
public abstract class AbstrTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Поле
|
||||
/// </summary>
|
||||
public int key = 100;
|
||||
/// <summary>
|
||||
/// Свойство
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Конструктор без параметров
|
||||
/// </summary>
|
||||
public AbstrTest()
|
||||
{
|
||||
key = 110;
|
||||
Name = "Fire";
|
||||
Console.WriteLine($"->AbstrTest {Name} {key}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Конструктор с параметрами
|
||||
/// </summary>
|
||||
/// <param name="key">ключ</param>
|
||||
public AbstrTest(int key)
|
||||
{
|
||||
this.key = key;
|
||||
Name = "Fire";
|
||||
Console.WriteLine($"->AbstrTest {Name} {key}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Метод - это фиксированная операция с реализацией по умолчанию
|
||||
/// </summary>
|
||||
public void Move()
|
||||
{
|
||||
Console.WriteLine("Move Abstr");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Виртуальный метод - операция с реализацией по умолчанию
|
||||
/// </summary>
|
||||
public virtual void Resize()
|
||||
{
|
||||
Console.WriteLine("Resize Abstr");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Абстрактный метод - сигнатура - операция без реализации
|
||||
/// </summary>
|
||||
public abstract void Open();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Определение:
|
||||
/// Структура - это значимый тип данных, ссылка на структуру хранится в куче, значение в стеке
|
||||
/// Тот же класс, меняется тип данных
|
||||
/// </summary>
|
||||
public struct TestStruct : IInterTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Свойство имени
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
/// <summary>
|
||||
/// Свойство идентификатора
|
||||
/// </summary>
|
||||
public object ID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Конструктор без параметров
|
||||
/// </summary>
|
||||
public TestStruct()
|
||||
{
|
||||
Name = "Base";
|
||||
ID = (object)0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Метод с реализацией с параметрами
|
||||
/// </summary>
|
||||
/// <param name="build">#</param>
|
||||
public void Build(int build = 0)
|
||||
{
|
||||
Console.WriteLine($"Build TestStruct {build}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Метод с реализацией без параметров
|
||||
/// </summary>
|
||||
public void Reload()
|
||||
{
|
||||
Console.WriteLine("Reload TestStruct");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Реализация поведения класса
|
||||
/// </summary>
|
||||
public class ClassMain : AbstrTest, IInterTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Свойство
|
||||
/// </summary>
|
||||
public int countBuild { get; set; }
|
||||
/// <summary>
|
||||
/// Свойство от интерфейса
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
/// <summary>
|
||||
/// Свойство от интерфейса
|
||||
/// </summary>
|
||||
public object ID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Конструтор + реализация поведения конструктора абстрактного класса
|
||||
/// </summary>
|
||||
public ClassMain() : base (0)
|
||||
{
|
||||
TestStruct testStruct = new TestStruct();
|
||||
Console.WriteLine($"TestStruct: {testStruct.Name}, {testStruct.ID}");
|
||||
Name = "Base";
|
||||
ID = (object)0;
|
||||
Move();
|
||||
Build();
|
||||
Reload();
|
||||
Resize();
|
||||
Open();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Конструтор c параметрами + реализация поведения конструктора абстрактного класса
|
||||
/// </summary>
|
||||
/// <param name="build">#</param>
|
||||
/// <param name="name">#</param>
|
||||
/// <param name="id">#</param>
|
||||
public ClassMain(int build, string name, object id) : base(build)
|
||||
{
|
||||
countBuild = build;
|
||||
Name = name;
|
||||
ID = id;
|
||||
Move();
|
||||
Build(build);
|
||||
Reload();
|
||||
Resize();
|
||||
Open();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Виртуальный метод
|
||||
/// </summary>
|
||||
public virtual void GG()
|
||||
{
|
||||
Console.WriteLine("GG Virtual Method Class");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Метод с параметрами
|
||||
/// </summary>
|
||||
/// <param name="build">#</param>
|
||||
public void Build(int build = 0)
|
||||
{
|
||||
Console.WriteLine($"Build Interface Class {build}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Метод без параметров обязательный к реализации от интерфейса
|
||||
/// </summary>
|
||||
public void Reload()
|
||||
{
|
||||
Console.WriteLine("Reload Interface Abstract Method Class");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Реализация virtual метода абстрактного класса
|
||||
/// </summary>
|
||||
public override void Resize()
|
||||
{
|
||||
base.Resize();
|
||||
countBuild--;
|
||||
Console.WriteLine("Resize Class");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Переопределение сигнатуры абстрактного класса
|
||||
/// </summary>
|
||||
public override void Open()
|
||||
{
|
||||
Console.WriteLine("Open Abstract Method Class");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Реализация деструктора класса
|
||||
/// </summary>
|
||||
~ClassMain()
|
||||
{
|
||||
Console.WriteLine("###Destroy ClassMain");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Реализация наследования (3 принцип ООП)
|
||||
/// Определение:
|
||||
/// Наследование - это возможность создания новых абстракций на основе существующих.
|
||||
/// Наследование является ключевой функцией объектно-ориентированных языков программирования.
|
||||
/// Оно позволяет определить базовый класс для определенных функций (доступа к данным или действий),
|
||||
/// а затем создавать производные классы, которые наследуют или переопределяют функции базового класса.
|
||||
/// </summary>
|
||||
public class Nasled : ClassMain
|
||||
{
|
||||
/// <summary>
|
||||
/// Необязательное перепределение виртуального метода главного класса
|
||||
/// </summary>
|
||||
public override void GG()
|
||||
{
|
||||
base.GG();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Определение:
|
||||
/// Records - это ссылочный тип, некая модификация возможностей классов
|
||||
/// Ключевая особенность - может представлять неизменяемый тип данных (immutable)
|
||||
/// Также имеет особенность в виде встроенного JSON представления при выводе в строку
|
||||
/// Имеет возможность управлять своим деконструктором
|
||||
/// </summary>
|
||||
public record class Records
|
||||
{
|
||||
/// <summary>
|
||||
/// Свойство идентификатора
|
||||
/// </summary>
|
||||
public int Id { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Свойство имени
|
||||
/// </summary>
|
||||
public string Name { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Конструктор с параметрами
|
||||
/// </summary>
|
||||
/// <param name="id">идентификатор</param>
|
||||
/// <param name="name">имя</param>
|
||||
public Records(int id, string name)
|
||||
{
|
||||
Id = id;
|
||||
Name = name;
|
||||
Console.WriteLine("Construct");
|
||||
}
|
||||
|
||||
public class GlobalInfo
|
||||
{
|
||||
public int Id;
|
||||
public string Name;
|
||||
public int Ida;
|
||||
public string Names;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Деконструктор
|
||||
/// </summary>
|
||||
/// <param name="name">имя</param>
|
||||
/// <param name="id">идентификатор</param>
|
||||
public void Deconstruct(out string name, out int id)
|
||||
{
|
||||
name = Name;
|
||||
id = Id;
|
||||
Console.WriteLine("Destruct");
|
||||
}
|
||||
}
|
||||
|
||||
public record class Person
|
||||
{
|
||||
public int Id { get; init; }
|
||||
public string Name { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Деконструктор
|
||||
/// </summary>
|
||||
/// <param name="name">имя</param>
|
||||
/// <param name="id">идентификатор</param>
|
||||
public void Deconstruct(out string name, out int id)
|
||||
{
|
||||
name = Name;
|
||||
id = Id;
|
||||
Console.WriteLine("Destruct Person");
|
||||
}
|
||||
}
|
||||
|
||||
public record class Job
|
||||
{
|
||||
public int Ida { get; init; }
|
||||
public string Names { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Деконструктор
|
||||
/// </summary>
|
||||
/// <param name="name">имя</param>
|
||||
/// <param name="id">идентификатор</param>
|
||||
public void Deconstruct(out string name, out int id)
|
||||
{
|
||||
name = Names;
|
||||
id = Ida;
|
||||
Console.WriteLine("Destruct Job");
|
||||
}
|
||||
}
|
31
Patterns/BaseTests/000_TestsMain.cs
Normal file
31
Patterns/BaseTests/000_TestsMain.cs
Normal file
@ -0,0 +1,31 @@
|
||||
using Base;
|
||||
|
||||
namespace BaseTests;
|
||||
|
||||
/// <summary>
|
||||
/// Модульный тест
|
||||
/// Конфигурирование:
|
||||
/// Чтобы добавить возможность вызывать методы какого-либо проекта
|
||||
/// Нажимаем правой кнопкой на зависимости в данном проекте
|
||||
/// Выбираем пункт - добавить ссылку на проект
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public class TestsMain
|
||||
{
|
||||
/// <summary>
|
||||
/// Реализация тестового метода модульного теста
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestMethod1()
|
||||
{
|
||||
// arrange
|
||||
int expected = 3;
|
||||
|
||||
// act
|
||||
var classMain = new ClassMain(4, "Unit", 10);
|
||||
int actual = classMain.countBuild;
|
||||
|
||||
// assert
|
||||
Assert.AreEqual(expected, actual, 0.001, "BuildCount not correctly"); //сравниваем полученное значение с требуемым
|
||||
}
|
||||
}
|
38
Patterns/BaseTests/001_TestInitAndCleanUp.cs
Normal file
38
Patterns/BaseTests/001_TestInitAndCleanUp.cs
Normal file
@ -0,0 +1,38 @@
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Base.Tests;
|
||||
|
||||
[TestClass]
|
||||
public class TestInitAndCleanUp
|
||||
{
|
||||
private ClassMain main;
|
||||
private string Name;
|
||||
|
||||
/// <summary>
|
||||
/// Запускается перед каждым тестируемым методом
|
||||
/// </summary>
|
||||
[TestInitialize]
|
||||
public void TestInitialize()
|
||||
{
|
||||
Debug.WriteLine("Test Initialize");
|
||||
main = new ClassMain();
|
||||
main.Name = "Nikolay";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Запускается после каждого завершения тестирования метода
|
||||
/// </summary>
|
||||
[TestCleanup]
|
||||
public void MainCleanUp()
|
||||
{
|
||||
Debug.WriteLine("Test CleanUp");
|
||||
Name = string.Empty;
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AddName()
|
||||
{
|
||||
Name = "Nikolay";
|
||||
Assert.AreEqual(Name, main.Name);
|
||||
}
|
||||
}
|
41
Patterns/BaseTests/002_ClassInitAndCleanUp.cs
Normal file
41
Patterns/BaseTests/002_ClassInitAndCleanUp.cs
Normal file
@ -0,0 +1,41 @@
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Base.Tests;
|
||||
|
||||
[TestClass]
|
||||
public class ClassInitAndCleanUp
|
||||
{
|
||||
private static ClassMain main;
|
||||
|
||||
/// <summary>
|
||||
/// Запускается один раз перед тем как запустится один Unit Test
|
||||
/// Метод должен быть открытым, статическим и принимать параметр типа контекста
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
[ClassInitialize]
|
||||
public static void ClassInitialize(TestContext context)
|
||||
{
|
||||
main = new ClassMain();
|
||||
main.Name = "Test";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Запускается после последнего тестируемого метода
|
||||
/// Метод должен быть открытым, статическим и возвращать void
|
||||
/// </summary>
|
||||
[ClassCleanup]
|
||||
public static void MainCleanUp()
|
||||
{
|
||||
Debug.WriteLine("Test CleanUp");
|
||||
main.Name = string.Empty;
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AddName()
|
||||
{
|
||||
var Name = "Test";
|
||||
Assert.AreEqual(Name, main.Name);
|
||||
}
|
||||
}
|
26
Patterns/BaseTests/003_AssemblyInit.cs
Normal file
26
Patterns/BaseTests/003_AssemblyInit.cs
Normal file
@ -0,0 +1,26 @@
|
||||
namespace Base.Tests;
|
||||
|
||||
[TestClass]
|
||||
public class AssemblyInit
|
||||
{
|
||||
/// <summary>
|
||||
/// Код выполняется один раз на всю сборку
|
||||
/// Используется во всех Unit тестах во всех тестовых вкладках
|
||||
/// </summary>
|
||||
/// <param name="testContext"></param>
|
||||
[AssemblyInitialize]
|
||||
public static void TestMethodInit(TestContext testContext)
|
||||
{
|
||||
Console.WriteLine("Test AssemblyInitialize: " + testContext.TestName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Код выполняется один раз на всю сборку
|
||||
/// Используется во всех Unit тестах во всех тестовых вкладках
|
||||
/// </summary>
|
||||
[AssemblyCleanup]
|
||||
public static void TestMethodGlobalCleanUp()
|
||||
{
|
||||
Console.WriteLine("Test AssemblyCleanup");
|
||||
}
|
||||
}
|
65
Patterns/BaseTests/004_AssertMethods.cs
Normal file
65
Patterns/BaseTests/004_AssertMethods.cs
Normal file
@ -0,0 +1,65 @@
|
||||
namespace Base.Tests;
|
||||
|
||||
[TestClass]
|
||||
public class AssertMethods
|
||||
{
|
||||
[TestMethod]
|
||||
public void IsSqrtTest()
|
||||
{
|
||||
// arrange
|
||||
const double input = 4;
|
||||
const double expected = 2;
|
||||
|
||||
// act
|
||||
var actual = AssertMsTest.GetSqrt(input);
|
||||
|
||||
// assert - сравнивает два значения
|
||||
Assert.AreEqual(expected, actual, $"Sqrt of {input} should have been {expected}");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DeltaTest()
|
||||
{
|
||||
const double expected = 3.1;
|
||||
const double delta = 0.07;
|
||||
|
||||
// 3.1622776601683795
|
||||
// 0.062..
|
||||
double actual = AssertMsTest.GetSqrt(10);
|
||||
|
||||
// Проверка значений на равенство с учётом прогрешлоости delta
|
||||
Assert.AreEqual(expected, actual, delta, $"Sqrt of {actual} should have been {expected}");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void StringAreEqualTest()
|
||||
{
|
||||
// arrange
|
||||
const string expected = "hello";
|
||||
const string input = "HELLO";
|
||||
|
||||
// act and assert
|
||||
// третий параметр игнорирование регистра
|
||||
Assert.AreEqual(expected, input, true);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void StringAreSameTest()
|
||||
{
|
||||
string a = "Hello";
|
||||
string b = "Hello";
|
||||
|
||||
// проверка равенства ссылок
|
||||
Assert.AreSame(a, b);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void IntegerAreSameTest()
|
||||
{
|
||||
int a = 10;
|
||||
int b = 10;
|
||||
|
||||
// проверка равенства ссылок
|
||||
Assert.AreSame(a, b);
|
||||
}
|
||||
}
|
65
Patterns/BaseTests/005_CollectionAssertMethods.cs
Normal file
65
Patterns/BaseTests/005_CollectionAssertMethods.cs
Normal file
@ -0,0 +1,65 @@
|
||||
namespace Base.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// Проверяет результат работы с коллекциями
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public class CollectionAssertMethods
|
||||
{
|
||||
public static List<string> employees;
|
||||
|
||||
[ClassInitialize]
|
||||
public static void InitializeCurrentTest(TestContext context)
|
||||
{
|
||||
employees = new List<string>();
|
||||
|
||||
employees.Add("Nikolay");
|
||||
employees.Add("Oleg");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Проверка значений коллекции на наличие в ней
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void AllItemAreNotNullTest()
|
||||
{
|
||||
CollectionAssert.AllItemsAreNotNull(employees, "Not null failed");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Проверка значения коллекции на уникальность
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void AllItemsAreUniqueTest()
|
||||
{
|
||||
CollectionAssert.AllItemsAreUnique(employees, "Uniqueness failed");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Проверяет каждый элемент списка на равенство с входящим списком
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void AreEqualTest()
|
||||
{
|
||||
var currList = new List<string>();
|
||||
|
||||
currList.Add("Nikolay");
|
||||
currList.Add("Oleg");
|
||||
|
||||
CollectionAssert.AreEqual(currList, employees);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Проверяем наличии одного List в другом
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void SubsetTest()
|
||||
{
|
||||
var subsetList = new List<string>();
|
||||
|
||||
subsetList.Add(employees[1]);
|
||||
//subsetList.Add("Mig"); //ошибка так как этот элемент не входит в employees
|
||||
|
||||
CollectionAssert.IsSubsetOf(subsetList, employees, "not elements subsetList to employees");
|
||||
}
|
||||
}
|
44
Patterns/BaseTests/006_StringAssetMethods.cs
Normal file
44
Patterns/BaseTests/006_StringAssetMethods.cs
Normal file
@ -0,0 +1,44 @@
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Base.Tests;
|
||||
|
||||
[TestClass]
|
||||
public class StringAssetMethods
|
||||
{
|
||||
/// <summary>
|
||||
/// Проверка подстроки в строке
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void StringContainsTest()
|
||||
{
|
||||
StringAssert.Contains("Assert samples", "sam");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ПРоверка с использованием регулярного выражения
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void StringMathesTest()
|
||||
{
|
||||
// проверяет наличие трёх цифр подряд
|
||||
StringAssert.Matches("123", new Regex(@"\d{3}"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Проверка начала строки на соответствие условию
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void StringStartsWithTest()
|
||||
{
|
||||
StringAssert.StartsWith("Hello London", "H");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Проверка конца строки на соответствие условию
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void StringEndWithTest()
|
||||
{
|
||||
StringAssert.EndsWith("Hello Moscow", "w");
|
||||
}
|
||||
}
|
27
Patterns/BaseTests/007_ExpectingExceptions.cs
Normal file
27
Patterns/BaseTests/007_ExpectingExceptions.cs
Normal file
@ -0,0 +1,27 @@
|
||||
namespace Base.Tests;
|
||||
|
||||
[TestClass]
|
||||
public class ExpectingExceptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Проверка метода на возврат исключения
|
||||
/// </summary>
|
||||
[ExpectedException(typeof(ArgumentNullException), "Exception was not throw")]
|
||||
[TestMethod]
|
||||
public void AssertMsTestExceptionTest()
|
||||
{
|
||||
var ms = new AssertMsTest();
|
||||
ms.SayHello(null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AssertMsTestReturnTest()
|
||||
{
|
||||
var name = "Hi! Nikolay";
|
||||
|
||||
var ms = new AssertMsTest();
|
||||
var actual = ms.SayHello("Nikolay");
|
||||
|
||||
Assert.AreEqual(name, actual, $"name: {name} act: {actual}");
|
||||
}
|
||||
}
|
22
Patterns/BaseTests/Base.Tests.csproj
Normal file
22
Patterns/BaseTests/Base.Tests.csproj
Normal file
@ -0,0 +1,22 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="2.2.8" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="2.2.8" />
|
||||
<PackageReference Include="coverlet.collector" Version="3.1.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Base\BaseInfo.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
1
Patterns/BaseTests/Usings.cs
Normal file
1
Patterns/BaseTests/Usings.cs
Normal file
@ -0,0 +1 @@
|
||||
global using Microsoft.VisualStudio.TestTools.UnitTesting;
|
10
Patterns/Bridge/Bridge.csproj
Normal file
10
Patterns/Bridge/Bridge.csproj
Normal file
@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
96
Patterns/Bridge/Program.cs
Normal file
96
Patterns/Bridge/Program.cs
Normal file
@ -0,0 +1,96 @@
|
||||
/* Мост
|
||||
Разделяет абстракцию и реализацию так,
|
||||
чтобы они могли изменяться независимо друг от друга
|
||||
*/
|
||||
class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
#region Пример №1 - базовое
|
||||
var programmer_1 = new FreelancerProgger(new CPPLang());
|
||||
programmer_1.DoWork();
|
||||
programmer_1.EarnMoney();
|
||||
var programmer_2 = new FreelancerProgger(new CSharpLang());
|
||||
programmer_2.DoWork();
|
||||
programmer_2.EarnMoney();
|
||||
Console.ReadKey();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Поведение языка
|
||||
/// </summary>
|
||||
interface ILanguage
|
||||
{
|
||||
void Build();
|
||||
void Execute();
|
||||
}
|
||||
|
||||
class CPPLang : ILanguage
|
||||
{
|
||||
public void Build()
|
||||
{
|
||||
Console.WriteLine("C++ compile");
|
||||
}
|
||||
|
||||
public void Execute()
|
||||
{
|
||||
Console.WriteLine("C++ Start");
|
||||
}
|
||||
}
|
||||
|
||||
class CSharpLang : ILanguage
|
||||
{
|
||||
public void Build()
|
||||
{
|
||||
Console.WriteLine("C# compile");
|
||||
}
|
||||
|
||||
public void Execute()
|
||||
{
|
||||
Console.WriteLine("C# Start");
|
||||
}
|
||||
}
|
||||
|
||||
abstract class Programmer
|
||||
{
|
||||
protected ILanguage language;
|
||||
public ILanguage Language
|
||||
{
|
||||
set { language = value; }
|
||||
}
|
||||
|
||||
public Programmer(ILanguage language)
|
||||
{
|
||||
Language = language;
|
||||
}
|
||||
|
||||
public virtual void DoWork()
|
||||
{
|
||||
language.Build();
|
||||
language.Execute();
|
||||
}
|
||||
|
||||
public abstract void EarnMoney();
|
||||
}
|
||||
|
||||
class FreelancerProgger : Programmer
|
||||
{
|
||||
public FreelancerProgger(ILanguage language) : base(language) { }
|
||||
|
||||
public override void EarnMoney()
|
||||
{
|
||||
Console.WriteLine("Получаем оплату за заказ");
|
||||
}
|
||||
}
|
||||
|
||||
class CorporateProgger : Programmer
|
||||
{
|
||||
public CorporateProgger(ILanguage language) : base(language) { }
|
||||
|
||||
public override void EarnMoney()
|
||||
{
|
||||
Console.WriteLine("Получаем оплату в конце месяца");
|
||||
}
|
||||
}
|
10
Patterns/Builder/Builder.csproj
Normal file
10
Patterns/Builder/Builder.csproj
Normal file
@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
120
Patterns/Builder/Program.cs
Normal file
120
Patterns/Builder/Program.cs
Normal file
@ -0,0 +1,120 @@
|
||||
/* Строитель
|
||||
Разделяет создание сложного объекта
|
||||
и его инициализацию так, что одинаковый
|
||||
процесс построения может может создавать
|
||||
объекты с разным состоянием
|
||||
*/
|
||||
class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
#region Пример №1 - базовое
|
||||
var rx = new Baker();
|
||||
var bread = rx.Bake(new RBuilderBread());
|
||||
|
||||
Console.WriteLine(bread.ToString());
|
||||
Console.ReadKey();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Мука
|
||||
/// </summary>
|
||||
class Floor
|
||||
{
|
||||
/// <summary>
|
||||
/// Сорт муки
|
||||
/// </summary>
|
||||
public string Sort { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Соль
|
||||
/// </summary>
|
||||
class Salt
|
||||
{
|
||||
/// <summary>
|
||||
/// Масса
|
||||
/// </summary>
|
||||
public double Mass { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Пищевые добавки
|
||||
/// </summary>
|
||||
class Additives
|
||||
{
|
||||
/// <summary>
|
||||
/// Список пищевых добавок
|
||||
/// </summary>
|
||||
public string[] Names { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Xлеб
|
||||
/// </summary>
|
||||
class Bread
|
||||
{
|
||||
public Floor Floor { get; set; }
|
||||
public Salt Salt { get; set; }
|
||||
public Additives Additives { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"[F: {Floor.Sort}]---[S: {Salt.Mass}]---[A: {Additives.Names[0]}]";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Строитель хлеба
|
||||
/// </summary>
|
||||
abstract class BreadBuilder
|
||||
{
|
||||
public Bread Bread { get; set; }
|
||||
public void CreateBread()
|
||||
{
|
||||
Bread = new Bread();
|
||||
}
|
||||
|
||||
public abstract void SetFloor();
|
||||
public abstract void SetSalt();
|
||||
public abstract void SetAdditives();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Пекарь
|
||||
/// </summary>
|
||||
class Baker
|
||||
{
|
||||
public Bread Bake(BreadBuilder breadBuilder)
|
||||
{
|
||||
breadBuilder.CreateBread();
|
||||
breadBuilder.SetFloor();
|
||||
breadBuilder.SetSalt();
|
||||
breadBuilder.SetAdditives();
|
||||
return breadBuilder.Bread;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Для ржаного хлеба строитель
|
||||
/// </summary>
|
||||
class RBuilderBread : BreadBuilder
|
||||
{
|
||||
public override void SetAdditives()
|
||||
{
|
||||
Bread.Additives = new Additives() { Names = new[] { "E222", "E297" } };
|
||||
}
|
||||
|
||||
public override void SetFloor()
|
||||
{
|
||||
Bread.Floor = new Floor() { Sort = "R class" };
|
||||
}
|
||||
|
||||
public override void SetSalt()
|
||||
{
|
||||
Bread.Salt = new Salt() { Mass = 3.44 };
|
||||
}
|
||||
}
|
10
Patterns/ChainOfResponsibility/ChainOfResponsibility.csproj
Normal file
10
Patterns/ChainOfResponsibility/ChainOfResponsibility.csproj
Normal file
@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
165
Patterns/ChainOfResponsibility/Program.cs
Normal file
165
Patterns/ChainOfResponsibility/Program.cs
Normal file
@ -0,0 +1,165 @@
|
||||
/* Цепочка обязанностей
|
||||
Избегает связывание отправителя запроса
|
||||
с его получателем, давая возможность обработать
|
||||
запрос более чем одному объекту. Связывает
|
||||
объекты-получатели и передаёт запрос по цепочке
|
||||
пока объект не обработает его.
|
||||
*/
|
||||
class Program
|
||||
{
|
||||
public static void GiveCommand(IWorker worker, string command)
|
||||
{
|
||||
var str = worker.Execute(command);
|
||||
if(string.IsNullOrEmpty(str)) Console.WriteLine(command + " - никто не выполнил команду");
|
||||
else Console.WriteLine(str);
|
||||
}
|
||||
|
||||
static void Main()
|
||||
{
|
||||
#region Пример №1 - базовое
|
||||
Handler h1 = new ConcreateHandler1();
|
||||
Handler h2 = new ConcreateHandler2();
|
||||
h1.Successor = h2;
|
||||
h1.HandleRequest(2); //От первого до второго объекта обработка
|
||||
Console.WriteLine("Please press Enter...");
|
||||
Console.ReadKey();
|
||||
#endregion
|
||||
#region Пример №2 - этапы строительства дома
|
||||
var designer = new Designer();
|
||||
var programmer = new Programmer();
|
||||
var finishworker = new FinishWorker();
|
||||
designer.SetNetWorker(finishworker).SetNetWorker(programmer);
|
||||
|
||||
GiveCommand(designer, "Спроектировать веранду");
|
||||
GiveCommand(designer, "Сделать машину времени");
|
||||
GiveCommand(designer, "Уволить работников");
|
||||
GiveCommand(designer, "Курить");
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Передатчик
|
||||
/// </summary>
|
||||
abstract class Handler
|
||||
{
|
||||
public Handler Successor { get; set; }
|
||||
public abstract void HandleRequest(int condition);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Обработчик запроса №1
|
||||
/// </summary>
|
||||
class ConcreateHandler1 : Handler
|
||||
{
|
||||
/// <summary>
|
||||
/// Обработка запроса
|
||||
/// </summary>
|
||||
/// <param name="condition">состояние</param>
|
||||
public override void HandleRequest(int condition)
|
||||
{
|
||||
Console.WriteLine("1");
|
||||
if(condition == 1) return; //завершаем выполнение
|
||||
else if(Successor != null)
|
||||
Successor.HandleRequest(condition); //передача запроса дальше по цепи
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Обработчик запроса №2
|
||||
/// </summary>
|
||||
class ConcreateHandler2 : Handler
|
||||
{
|
||||
/// <summary>
|
||||
/// Обработка запроса
|
||||
/// </summary>
|
||||
/// <param name="condition">состояние</param>
|
||||
public override void HandleRequest(int condition)
|
||||
{
|
||||
Console.WriteLine("2");
|
||||
if (condition == 2) return; //завершаем выполнение
|
||||
else if (Successor != null) //передача запроса дальше по цепи
|
||||
Successor.HandleRequest(condition);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Поведение рабочего
|
||||
/// </summary>
|
||||
interface IWorker
|
||||
{
|
||||
/// <summary>
|
||||
/// Передача обязанностей следующему рабочему
|
||||
/// </summary>
|
||||
/// <param name="worker">следующий рабочий</param >
|
||||
IWorker SetNetWorker(IWorker worker);
|
||||
|
||||
/// <summary>
|
||||
/// Рабочий принимает команду на исполнение
|
||||
/// </summary>
|
||||
/// <param name="command">команда</param>
|
||||
/// <returns>Резульат принятия</returns>
|
||||
string Execute(string command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Абстрактный рабочий, базовое описание структуры каждого
|
||||
/// </summary>
|
||||
abstract class AbsWorker : IWorker
|
||||
{
|
||||
private IWorker nextWorker;
|
||||
public AbsWorker() => nextWorker = null;
|
||||
|
||||
/// <summary>
|
||||
/// Изменяемый процесс обработки команды в классах наследниках
|
||||
/// У каждого рабочего свой процесс выполнени
|
||||
/// </summary>
|
||||
/// <param name="command">команда</param>
|
||||
/// <returns>Результат</returns>
|
||||
public virtual string Execute(string command)
|
||||
{
|
||||
if (nextWorker == null) return string.Empty;
|
||||
return nextWorker.Execute(command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Передача обязанностей другому рабочему
|
||||
/// </summary>
|
||||
/// <param name="worker">Другой рабочий</param>
|
||||
/// <returns>Другой рабочий</returns>
|
||||
public IWorker SetNetWorker(IWorker worker)
|
||||
{
|
||||
nextWorker = worker;
|
||||
return worker;
|
||||
}
|
||||
}
|
||||
|
||||
class Designer : AbsWorker
|
||||
{
|
||||
public override string Execute(string command)
|
||||
{
|
||||
if (command == "Спроектировать веранду")
|
||||
return "Проектировщик выполнил команду: " + command;
|
||||
else return base.Execute(command); //если не может выполнить передаёт следующему в цепочке
|
||||
}
|
||||
}
|
||||
|
||||
class Programmer: AbsWorker
|
||||
{
|
||||
public override string Execute(string command)
|
||||
{
|
||||
if(command == "Сделать машину времени")
|
||||
return "Программист выполнил команду: " + command;
|
||||
else return base.Execute(command);
|
||||
}
|
||||
}
|
||||
|
||||
class FinishWorker : AbsWorker
|
||||
{
|
||||
public override string Execute(string command)
|
||||
{
|
||||
if (command == "Уволить работников")
|
||||
return "Начальник выполнил команду: " + command;
|
||||
else return base.Execute(command);
|
||||
}
|
||||
}
|
10
Patterns/Command/Command.csproj
Normal file
10
Patterns/Command/Command.csproj
Normal file
@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
225
Patterns/Command/Program.cs
Normal file
225
Patterns/Command/Program.cs
Normal file
@ -0,0 +1,225 @@
|
||||
/* Команда
|
||||
Инкапсулирует запрос в виде объекта
|
||||
позволяя передавать их клиентам в
|
||||
качестве параметров, ставить в очередь,
|
||||
логировать, а также поддерживать отмену
|
||||
операций
|
||||
*/
|
||||
class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
#region Пример №1 - базовое
|
||||
var initCommand = new Invoker(new ConcreteCommand(new Receiver()));
|
||||
initCommand.Run();
|
||||
initCommand.Cancel();
|
||||
Console.WriteLine("Please press Enter...");
|
||||
Console.ReadKey();
|
||||
#endregion
|
||||
#region Пример №2 - пульт управления конвеерной установкой
|
||||
var conveyor = new Conveyor(); // создаём конвеер
|
||||
var multipult = new Multipult(); // создаём пульт управления конвеером
|
||||
multipult.SetCommand(0, new ConveyorWorkCommand(conveyor));
|
||||
multipult.SetCommand(1, new ConveyorAjustCommand(conveyor));
|
||||
|
||||
multipult.PressOn(0);
|
||||
multipult.PressOn(1);
|
||||
multipult.PressCansel();
|
||||
multipult.PressCansel();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Описания общего поведения объекта
|
||||
/// </summary>
|
||||
abstract class Command
|
||||
{
|
||||
public abstract void Execute();
|
||||
public abstract void Undo();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Описание процесса создания команды
|
||||
/// </summary>
|
||||
class ConcreteCommand : Command
|
||||
{
|
||||
Receiver receiver;
|
||||
|
||||
public ConcreteCommand(Receiver receiver)
|
||||
{
|
||||
this.receiver = receiver;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Инициализация команды
|
||||
/// *вызывает его получателя
|
||||
/// </summary>
|
||||
public override void Execute()
|
||||
{
|
||||
receiver.Operation();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Остановка команды
|
||||
/// </summary>
|
||||
public override void Undo()
|
||||
{
|
||||
Console.WriteLine("Stop");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Описание возможностей получателя команды
|
||||
/// </summary>
|
||||
class Receiver
|
||||
{
|
||||
/// <summary>
|
||||
/// Обработка получателем команды
|
||||
/// </summary>
|
||||
public void Operation()
|
||||
{
|
||||
Console.WriteLine("Processing...");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Описание инициатора команды
|
||||
/// </summary>
|
||||
class Invoker
|
||||
{
|
||||
Command command;
|
||||
|
||||
/// <summary>
|
||||
/// Принимает в себя команду
|
||||
/// </summary>
|
||||
/// <param name="command">#</param>
|
||||
public Invoker(Command command)
|
||||
{
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Запускает команду
|
||||
/// </summary>
|
||||
public void Run()
|
||||
{
|
||||
command.Execute();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Отменяет выполнение команды
|
||||
/// </summary>
|
||||
public void Cancel()
|
||||
{
|
||||
command.Undo();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Поведение команды
|
||||
/// </summary>
|
||||
interface ICommand
|
||||
{
|
||||
void Positive();
|
||||
void Negative();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Класс конвеера
|
||||
/// </summary>
|
||||
class Conveyor
|
||||
{
|
||||
public void On() => Console.WriteLine("Включение конвеера");
|
||||
|
||||
public void Off() => Console.WriteLine("Выключение конвеера");
|
||||
|
||||
public void SpeedIncrease() => Console.WriteLine("Скорость конвеера увеличена");
|
||||
|
||||
public void SpeedDecrease() => Console.WriteLine("Скорость конвеера снижена");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Класс управления работой конвеера
|
||||
/// </summary>
|
||||
class ConveyorWorkCommand : ICommand
|
||||
{
|
||||
public Conveyor conveer;
|
||||
|
||||
/// <summary>
|
||||
/// Передача типа конвеера в конструторе
|
||||
/// </summary>
|
||||
/// <param name="conveer">тип</param>
|
||||
public ConveyorWorkCommand(Conveyor conveer) => this.conveer = conveer;
|
||||
|
||||
public void Negative() => conveer.Off();
|
||||
|
||||
public void Positive() => conveer.On();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Класс регулировки конвеера
|
||||
/// </summary>
|
||||
class ConveyorAjustCommand : ICommand
|
||||
{
|
||||
public Conveyor conveer;
|
||||
|
||||
/// <summary>
|
||||
/// Передача типа конвеера в конструторе
|
||||
/// </summary>
|
||||
/// <param name="conveer">тип</param>
|
||||
public ConveyorAjustCommand(Conveyor conveer) => this.conveer = conveer;
|
||||
|
||||
public void Negative() => conveer.SpeedDecrease();
|
||||
|
||||
public void Positive() => conveer.SpeedIncrease();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Пульт управления конвеером
|
||||
/// </summary>
|
||||
class Multipult
|
||||
{
|
||||
/// <summary>
|
||||
/// Все возможные команды
|
||||
/// </summary>
|
||||
private List<ICommand> commands;
|
||||
|
||||
/// <summary>
|
||||
/// История выполненных команд для возможной их отмены
|
||||
/// </summary>
|
||||
private Stack<ICommand> history;
|
||||
|
||||
public Multipult()
|
||||
{
|
||||
commands = new List<ICommand>() { null, null };
|
||||
history = new Stack<ICommand>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Устанавлием список команд по индексу кнопки
|
||||
/// </summary>
|
||||
public void SetCommand(int btn, ICommand command) => commands[btn] = command;
|
||||
|
||||
/// <summary>
|
||||
/// Вызывает команду из списка по указанному индексу
|
||||
/// и запишет в историю команд выполненную команду
|
||||
/// </summary>
|
||||
/// <param name="btn">идекс кнопки</param>
|
||||
public void PressOn(int btn)
|
||||
{
|
||||
commands[btn].Positive();
|
||||
history.Push(commands[btn]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Извлекает команду из истории и отменяет её
|
||||
/// </summary>
|
||||
public void PressCansel()
|
||||
{
|
||||
if(history.Count == 0) return;
|
||||
var oldC = history.Pop();
|
||||
oldC.Negative();
|
||||
}
|
||||
}
|
10
Patterns/Composite/Composite.csproj
Normal file
10
Patterns/Composite/Composite.csproj
Normal file
@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
129
Patterns/Composite/Program.cs
Normal file
129
Patterns/Composite/Program.cs
Normal file
@ -0,0 +1,129 @@
|
||||
/* Компоновщик
|
||||
Компонует объекты в древовидную структуру по принципу "часть-целое",
|
||||
представляя их в виде иерархии. Позволяет
|
||||
клиенту одинаково обращаться как к отдельному,
|
||||
так и к целому поддереву
|
||||
*/
|
||||
class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
#region Пример №1 - базовое
|
||||
var paths = new Paths(new Dictionary<int, Directory>());
|
||||
paths.components.Add(1, new Directory("C"));
|
||||
paths.components[1].Add(new Folder("SYSTEM"));
|
||||
paths.components[1].Add(new Folder("DATA"));
|
||||
paths.components[1].Add(new File("test.txt"));
|
||||
paths.components.Add(0, new Directory("F"));
|
||||
paths.components[0].Add(new File("resize.cs"));
|
||||
paths.Print();
|
||||
Console.ReadKey();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Абстракция компонента файловой системы (дерева) - пути до файла
|
||||
/// </summary>
|
||||
abstract class Component
|
||||
{
|
||||
protected string name;
|
||||
|
||||
public Component(string name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public virtual void Add(Component component) { }
|
||||
public abstract void Remove(Component component);
|
||||
public abstract void Print();
|
||||
}
|
||||
|
||||
class Paths : Component
|
||||
{
|
||||
public Dictionary<int,Directory> components;
|
||||
|
||||
public Paths(Dictionary<int, Directory> components) : base ("")
|
||||
{
|
||||
this.components = components;
|
||||
}
|
||||
|
||||
public override void Print()
|
||||
{
|
||||
foreach (var component in components)
|
||||
{
|
||||
component.Value.Print();
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
|
||||
public override void Remove(Component component)
|
||||
{
|
||||
Console.WriteLine("Delete Path" + this.name);
|
||||
}
|
||||
}
|
||||
|
||||
class Directory : Component
|
||||
{
|
||||
public List<Component> components = new();
|
||||
|
||||
public Directory(string name)
|
||||
: base(name)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Add(Component component)
|
||||
{
|
||||
components.Add(component);
|
||||
}
|
||||
|
||||
public override void Print()
|
||||
{
|
||||
Console.Write(this.name + ":");
|
||||
foreach (var component in components)
|
||||
{
|
||||
component.Print();
|
||||
}
|
||||
}
|
||||
|
||||
public override void Remove(Component component)
|
||||
{
|
||||
component.Remove(component);
|
||||
}
|
||||
}
|
||||
|
||||
class Folder : Component
|
||||
{
|
||||
public Folder(string name)
|
||||
: base(name)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Print()
|
||||
{
|
||||
Console.Write("\\" + this.name);
|
||||
}
|
||||
|
||||
public override void Remove(Component component)
|
||||
{
|
||||
Console.WriteLine(this.name + " Delete");
|
||||
}
|
||||
}
|
||||
|
||||
class File : Component
|
||||
{
|
||||
public File(string name)
|
||||
: base(name)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Print()
|
||||
{
|
||||
Console.Write("\\" + this.name);
|
||||
}
|
||||
|
||||
public override void Remove(Component component)
|
||||
{
|
||||
Console.WriteLine(this.name + " Delete");
|
||||
}
|
||||
}
|
10
Patterns/Decorator/Decorator.csproj
Normal file
10
Patterns/Decorator/Decorator.csproj
Normal file
@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
62
Patterns/Decorator/Program.cs
Normal file
62
Patterns/Decorator/Program.cs
Normal file
@ -0,0 +1,62 @@
|
||||
/* Декоратор
|
||||
Динамически предоставляет объекту
|
||||
дополнительные возможности. Представляет
|
||||
собой гибкую альтернативу наследованию
|
||||
для расширения функциональности.
|
||||
*/
|
||||
class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
#region Пример №1 - базовое
|
||||
Pizza r = new RussianPizza();
|
||||
Console.WriteLine(r.GetCost());
|
||||
Pizza i = new TomatoPizza(r);
|
||||
Console.WriteLine(i.GetCost());
|
||||
Console.ReadKey();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
abstract class Pizza
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public Pizza(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
public abstract int GetCost();
|
||||
}
|
||||
|
||||
class RussianPizza : Pizza
|
||||
{
|
||||
public RussianPizza() : base("Russian Pizza")
|
||||
{
|
||||
}
|
||||
|
||||
public override int GetCost()
|
||||
{
|
||||
return 1000;
|
||||
}
|
||||
}
|
||||
|
||||
abstract class PizzaDecorator : Pizza
|
||||
{
|
||||
protected Pizza pizza;
|
||||
protected PizzaDecorator(string name, Pizza pizza) : base(name)
|
||||
{
|
||||
this.pizza = pizza;
|
||||
}
|
||||
}
|
||||
|
||||
class TomatoPizza : PizzaDecorator
|
||||
{
|
||||
public TomatoPizza(Pizza pizza) : base(pizza.Name + ", tomato", pizza)
|
||||
{
|
||||
}
|
||||
|
||||
public override int GetCost()
|
||||
{
|
||||
return pizza.GetCost() + 100;
|
||||
}
|
||||
}
|
10
Patterns/Dict/DictionaryInfo.csproj
Normal file
10
Patterns/Dict/DictionaryInfo.csproj
Normal file
@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>disable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
116
Patterns/Dict/Program.cs
Normal file
116
Patterns/Dict/Program.cs
Normal file
@ -0,0 +1,116 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Specialized;
|
||||
using System.Diagnostics;
|
||||
|
||||
class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// Стандартный Dictionary
|
||||
/// Быстрый поиск с помощью ключей, можно добавлять и удалять элементы
|
||||
/// </summary>
|
||||
private static readonly Dictionary<string, object> Dictionary = new();
|
||||
|
||||
/// <summary>
|
||||
/// ListDictionary
|
||||
/// Он меньше и быстрее, чем Hashtable если количество элементов равно 10 или меньше
|
||||
/// </summary>
|
||||
private static readonly ListDictionary LDictionary = new()
|
||||
{
|
||||
{ "key", "value"}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// HybridDictionary
|
||||
/// Рекомендуется для случаев, когда количество элементов в словаре неизвестно.
|
||||
/// Он использует улучшенную производительность ListDictionary с небольшими коллекциями
|
||||
/// и предлагает гибкость переключения на Hashtable , которая обрабатывает большие коллекции лучше
|
||||
/// </summary>
|
||||
private static readonly HybridDictionary HDictionary = new()
|
||||
{
|
||||
{ "key", "value"}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// OrderedDictionary
|
||||
/// Он всегда упорядочен при выводе foreach
|
||||
/// Ключ не может быть нулевым , но значение может быть.
|
||||
/// Каждый элемент представляет собой пару ключ/значение, хранящуюся в объекте DictionaryEntry
|
||||
/// Доступ к элементам возможен либо по ключу, либо по индексу.
|
||||
/// [!]
|
||||
/// если элементов больше 20-ти быстрее при цикле for
|
||||
/// если элементов меньше 15-20 быстрее в foreach чем for
|
||||
/// </summary>
|
||||
private static readonly OrderedDictionary ODictionary = new()
|
||||
{
|
||||
{"01", "odin"},
|
||||
{"02", "dva"},
|
||||
{"03", "tri"},
|
||||
{"04", "chetiri"},
|
||||
{"06", "pyat"},
|
||||
{"07", "pyat"},
|
||||
{"08", "pyat"},
|
||||
{"09", "pyat"},
|
||||
{"10", "pyat"},
|
||||
{"11", "pyat"},
|
||||
{"12", "pyat"},
|
||||
{"13", "pyat"},
|
||||
{"14", "pyat"},
|
||||
{"15", "pyat"},
|
||||
{"16", "pyat"},
|
||||
{"17", "pyat"},
|
||||
{"18", "pyat"},
|
||||
{"19", "pyat"},
|
||||
{"20", "pyat"},
|
||||
{"21", "pyat"},
|
||||
{"22", "pyat"},
|
||||
{"23", "pyat"},
|
||||
{"24", "pyat"},
|
||||
{"25", "pyat"},
|
||||
{"26", "pyat"},
|
||||
{"27", "pyat"},
|
||||
{"28", "pyat"},
|
||||
{"29", "pyat"},
|
||||
{"30", "pyat"},
|
||||
{"31", "pyat"}
|
||||
};
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// SortedDictionary
|
||||
/// Дерево бинарного поиска, в котором все элементы отсортированы на основе ключа
|
||||
/// Быстрее вставляет и удаляет элементы
|
||||
/// </summary>
|
||||
private static readonly SortedDictionary<int, string> SDictionary = new();
|
||||
|
||||
/// <summary>
|
||||
/// ConcurrentDictionary
|
||||
/// Потокобезопасная коллекция пар "ключ-значение", доступ к которой могут одновременно получать несколько потоков.
|
||||
/// по умолчанию 4 потока на запись concurrencyLevel = 4
|
||||
/// первоначальное число элементов 31 сapacity = 31
|
||||
/// В отличие от обычного Dictionary, можно производить вставку в ConcurrentDictionary или удаление из него прямо во время перечисления
|
||||
/// </summary>
|
||||
private static readonly ConcurrentDictionary<int, string> СoncurrentDictionary = new();
|
||||
|
||||
static void Main()
|
||||
{
|
||||
Stopwatch stopwatch = new Stopwatch();
|
||||
stopwatch.Start();
|
||||
for(int i = 0; i < ODictionary.Count; i++)
|
||||
{
|
||||
string val = (string)ODictionary[i];
|
||||
Console.WriteLine(val);
|
||||
}
|
||||
stopwatch.Stop();
|
||||
Console.WriteLine("[for][el > 20]: " + stopwatch.Elapsed);
|
||||
stopwatch.Reset();
|
||||
stopwatch.Start();
|
||||
foreach (DictionaryEntry item in ODictionary)
|
||||
{
|
||||
Console.WriteLine(item.Value);
|
||||
}
|
||||
stopwatch.Stop();
|
||||
Console.WriteLine("[foreach][el > 20]: " + stopwatch.Elapsed);
|
||||
Console.ReadKey();
|
||||
}
|
||||
}
|
10
Patterns/Facade/Facade.csproj
Normal file
10
Patterns/Facade/Facade.csproj
Normal file
@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
55
Patterns/Facade/Program.cs
Normal file
55
Patterns/Facade/Program.cs
Normal file
@ -0,0 +1,55 @@
|
||||
/* Фасад
|
||||
Предоставляет единый интерфейс к группе
|
||||
интерфейсов подсистемы. Определяет высокоуровневый
|
||||
интерфейс, делая систему проще для использования.
|
||||
*/
|
||||
class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
#region Пример №1 - базовое
|
||||
var facade = new Facade(new A(), new B());
|
||||
facade.Start();
|
||||
Console.ReadKey();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
class Facade
|
||||
{
|
||||
ILogic logic1;
|
||||
ILogic logic2;
|
||||
public Facade(ILogic logic1, ILogic logic2)
|
||||
{
|
||||
this.logic1 = logic1;
|
||||
this.logic2 = logic2;
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
logic1.Process();
|
||||
logic2.Process();
|
||||
}
|
||||
}
|
||||
|
||||
interface ILogic
|
||||
{
|
||||
void Process();
|
||||
}
|
||||
|
||||
|
||||
class A : ILogic
|
||||
{
|
||||
public void Process()
|
||||
{
|
||||
Console.WriteLine("Some Process " + GetType().Name);
|
||||
}
|
||||
}
|
||||
|
||||
class B : ILogic
|
||||
{
|
||||
public void Process()
|
||||
{
|
||||
Console.WriteLine("Some Process " + GetType().Name);
|
||||
}
|
||||
}
|
10
Patterns/FactoryMethod/FactoryMethod.csproj
Normal file
10
Patterns/FactoryMethod/FactoryMethod.csproj
Normal file
@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
120
Patterns/FactoryMethod/Program.cs
Normal file
120
Patterns/FactoryMethod/Program.cs
Normal file
@ -0,0 +1,120 @@
|
||||
/* Фабричный метод
|
||||
Определяет интерфейс для создания объекта,
|
||||
но позволяет подклассам решать, какой класс создавать.
|
||||
Позволяет делегировать создание класса
|
||||
объектам класса.
|
||||
*/
|
||||
class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
#region Пример №1 - базовое
|
||||
var ltd = new WoodDeveloper();
|
||||
ltd.Create();
|
||||
|
||||
var rss = new OfficeDeveloper();
|
||||
rss.Create();
|
||||
|
||||
Creator<WoodDeveloper> ltdEx = new Creator<WoodDeveloper>();
|
||||
var a1 = ltdEx.FactoryMethod();
|
||||
a1.Create();
|
||||
Creator<OfficeDeveloper> rssEx = new Creator<OfficeDeveloper>();
|
||||
var a2 = rssEx.FactoryMethod();
|
||||
a2.Create();
|
||||
|
||||
Console.ReadKey();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// *** представления через обобщения (нельзя инициализировать через параметризированный конструктор)
|
||||
/// </summary>
|
||||
/// <typeparam name="T">обобщающий тип</typeparam>
|
||||
class Creator<T> where T : Developer, new()
|
||||
{
|
||||
public T FactoryMethod() { return new T(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cтроительная компания - базовая логика
|
||||
/// </summary>
|
||||
abstract class Developer
|
||||
{
|
||||
protected string Name { get; set; }
|
||||
|
||||
public Developer(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Фабричный метод
|
||||
/// </summary>
|
||||
/// <returns>House</returns>
|
||||
public abstract House Create();
|
||||
}
|
||||
|
||||
class WoodDeveloper : Developer
|
||||
{
|
||||
public WoodDeveloper() : base("Wood Develop LTD")
|
||||
{
|
||||
}
|
||||
|
||||
public override House Create()
|
||||
{
|
||||
return new PanelHouse();
|
||||
}
|
||||
}
|
||||
|
||||
class OfficeDeveloper : Developer
|
||||
{
|
||||
public OfficeDeveloper() : base("Office Develop RSS")
|
||||
{
|
||||
}
|
||||
|
||||
public override House Create()
|
||||
{
|
||||
return new OfficeHouse();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Общая логика операций над строением
|
||||
/// </summary>
|
||||
abstract class House
|
||||
{
|
||||
public abstract void Build();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Панельный дом
|
||||
/// </summary>
|
||||
class PanelHouse : House
|
||||
{
|
||||
public PanelHouse()
|
||||
{
|
||||
Build();
|
||||
}
|
||||
|
||||
public override void Build()
|
||||
{
|
||||
Console.WriteLine("Build Panel House");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Офисное здание
|
||||
/// </summary>
|
||||
class OfficeHouse : House
|
||||
{
|
||||
public OfficeHouse()
|
||||
{
|
||||
Build();
|
||||
}
|
||||
|
||||
public override void Build()
|
||||
{
|
||||
Console.WriteLine("Build Office House");
|
||||
}
|
||||
}
|
10
Patterns/FluentBuilder/FluentBuilder.csproj
Normal file
10
Patterns/FluentBuilder/FluentBuilder.csproj
Normal file
@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
68
Patterns/FluentBuilder/Program.cs
Normal file
68
Patterns/FluentBuilder/Program.cs
Normal file
@ -0,0 +1,68 @@
|
||||
/* Гибкий(плавный, текучий) строитель (интерфейс)
|
||||
Позволяет упростить процесс создания сложных
|
||||
объектов с помощью методов-цепочек, которые
|
||||
наделяют объект каким-то определенным качеством
|
||||
*/
|
||||
class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
#region Пример №1 - базовое
|
||||
User user = new User().Create().SetName("Alex").SetPassword("admin");
|
||||
Console.WriteLine(user);
|
||||
Console.ReadKey();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Шаблон пользователя
|
||||
/// </summary>
|
||||
class User
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Password { get; set; }
|
||||
|
||||
public UserBuilder Create()
|
||||
{
|
||||
return new UserBuilder();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"Name {Name}, Password {Password}";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Шаблон гибкого строителя конфигурации пользователя
|
||||
/// </summary>
|
||||
class UserBuilder
|
||||
{
|
||||
private User CurrentUser { get; set; }
|
||||
public UserBuilder()
|
||||
{
|
||||
CurrentUser = new User();
|
||||
}
|
||||
|
||||
public UserBuilder SetName(string name)
|
||||
{
|
||||
CurrentUser.Name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public UserBuilder SetPassword(string password)
|
||||
{
|
||||
CurrentUser.Password = password;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// преобразуем тип Builder в тип User для которого он использовался
|
||||
/// </summary>
|
||||
/// <param name="builder">строитель</param>
|
||||
public static implicit operator User(UserBuilder builder)
|
||||
{
|
||||
return builder.CurrentUser;
|
||||
}
|
||||
}
|
10
Patterns/Flyweight/Flyweight.csproj
Normal file
10
Patterns/Flyweight/Flyweight.csproj
Normal file
@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
97
Patterns/Flyweight/Program.cs
Normal file
97
Patterns/Flyweight/Program.cs
Normal file
@ -0,0 +1,97 @@
|
||||
/* Приспособленец
|
||||
Благодаря совместному использованию,
|
||||
поддерживает эффективную работу
|
||||
с большим количеством объектов.
|
||||
(для оптимизации работы с памятью)
|
||||
*/
|
||||
class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
#region Пример №1 - базовое
|
||||
double longtitude = 22.33;
|
||||
double latitude = 55.11;
|
||||
|
||||
HouseFactory houseFactory = new HouseFactory();
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
House panelH = houseFactory.GetHouse("Panel");
|
||||
if(panelH != null)
|
||||
panelH.Build(longtitude, latitude);
|
||||
longtitude += 0.1;
|
||||
latitude += 0.1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
House officeH = houseFactory.GetHouse("Office");
|
||||
if (officeH != null)
|
||||
officeH.Build(longtitude, latitude);
|
||||
longtitude += 0.1;
|
||||
latitude += 0.1;
|
||||
}
|
||||
|
||||
Console.ReadKey();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
abstract class House
|
||||
{
|
||||
/// <summary>
|
||||
/// Кол-во этажей - внутреннее состояние
|
||||
/// </summary>
|
||||
protected int stages;
|
||||
|
||||
/// <summary>
|
||||
/// Внешнее состояние действия
|
||||
/// </summary>
|
||||
/// <param name="latitude"></param>
|
||||
/// <param name="longitude"></param>
|
||||
public abstract void Build(double latitude, double longitude);
|
||||
}
|
||||
|
||||
class PanelHouse : House
|
||||
{
|
||||
public PanelHouse()
|
||||
{
|
||||
stages = 5;
|
||||
}
|
||||
|
||||
public override void Build(double latitude, double longitude)
|
||||
{
|
||||
Console.WriteLine($"PanelHouse Build stages-{stages} {latitude}, {longitude}");
|
||||
}
|
||||
}
|
||||
|
||||
class OfficeHouse : House
|
||||
{
|
||||
public OfficeHouse()
|
||||
{
|
||||
stages = 50;
|
||||
}
|
||||
|
||||
public override void Build(double latitude, double longitude)
|
||||
{
|
||||
Console.WriteLine($"OfficeHouse Build stages-{stages} {latitude}, {longitude}");
|
||||
}
|
||||
}
|
||||
|
||||
class HouseFactory
|
||||
{
|
||||
Dictionary<string, House> houses = new Dictionary<string, House>();
|
||||
|
||||
public HouseFactory()
|
||||
{
|
||||
houses.Add("Panel", new PanelHouse());
|
||||
houses.Add("Office", new OfficeHouse());
|
||||
}
|
||||
|
||||
public House GetHouse(string key)
|
||||
{
|
||||
if (houses.ContainsKey(key))
|
||||
return houses[key];
|
||||
else
|
||||
return null;
|
||||
}
|
||||
}
|
10
Patterns/Interpreter/Interpreter.csproj
Normal file
10
Patterns/Interpreter/Interpreter.csproj
Normal file
@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
148
Patterns/Interpreter/Program.cs
Normal file
148
Patterns/Interpreter/Program.cs
Normal file
@ -0,0 +1,148 @@
|
||||
/* Интерпретатор
|
||||
Получая формальный язык, определяет
|
||||
представление его грамматики и интерпретатор,
|
||||
использующий это представление для обработки
|
||||
выражений языка (Применяется для часто повторяющихся операций)
|
||||
*/
|
||||
class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
#region Пример №1 - базовое
|
||||
var context = new Context();
|
||||
//создаём переменные
|
||||
int x = 5;
|
||||
int y = 8;
|
||||
int z = 2;
|
||||
int k = 10;
|
||||
//задаём переменные в контекст
|
||||
context.SetVariable("x", x);
|
||||
context.SetVariable("y", y);
|
||||
context.SetVariable("z", z);
|
||||
context.SetVariable("k", k);
|
||||
//(x + y - z) * k
|
||||
var expressionAdd = new AddExpression(new NumberExpression("x"),
|
||||
new NumberExpression("y"));
|
||||
var expressionSub = new SubstructExpression(expressionAdd,
|
||||
new NumberExpression("z"));
|
||||
var expressionPow = new PowExpression(expressionSub, new NumberExpression("k"));
|
||||
Console.WriteLine(expressionPow.Interpret(context));
|
||||
Console.WriteLine("Please press Enter...");
|
||||
Console.ReadKey();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Агрегатор выражений
|
||||
/// </summary>
|
||||
class Context
|
||||
{
|
||||
Dictionary<string, int> variables;
|
||||
|
||||
public Context()
|
||||
{
|
||||
variables = new Dictionary<string, int>();
|
||||
}
|
||||
|
||||
public int GetVariable(string name)
|
||||
{
|
||||
if(variables.ContainsKey(name))
|
||||
return variables[name];
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void SetVariable(string name, int value)
|
||||
{
|
||||
if(variables.ContainsKey(name))
|
||||
variables[name] = value;
|
||||
else
|
||||
variables.Add(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Поведение интерпретатора
|
||||
/// </summary>
|
||||
interface IExpression
|
||||
{
|
||||
int Interpret(Context context);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Терминальное выражение
|
||||
/// </summary>
|
||||
class NumberExpression : IExpression
|
||||
{
|
||||
string Name { get; set; }
|
||||
public NumberExpression(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public int Interpret(Context context)
|
||||
{
|
||||
return context.GetVariable(Name);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Нетерминальное выражение для сложения
|
||||
/// </summary>
|
||||
class AddExpression : IExpression
|
||||
{
|
||||
IExpression LeftExpression { get; set; }
|
||||
IExpression RightExpression { get; set; }
|
||||
|
||||
public AddExpression(IExpression left, IExpression right)
|
||||
{
|
||||
LeftExpression = left;
|
||||
RightExpression = right;
|
||||
}
|
||||
|
||||
public int Interpret(Context context)
|
||||
{
|
||||
return LeftExpression.Interpret(context) + RightExpression.Interpret(context);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Нетерминальное выражение для умножения
|
||||
/// </summary>
|
||||
class PowExpression : IExpression
|
||||
{
|
||||
IExpression LeftExpression { get; set; }
|
||||
IExpression RightExpression { get; set; }
|
||||
|
||||
public PowExpression(IExpression left, IExpression right)
|
||||
{
|
||||
LeftExpression = left;
|
||||
RightExpression = right;
|
||||
}
|
||||
|
||||
public int Interpret(Context context)
|
||||
{
|
||||
return LeftExpression.Interpret(context) * RightExpression.Interpret(context);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Нетерминальное выражение для вычитания
|
||||
/// </summary>
|
||||
class SubstructExpression : IExpression
|
||||
{
|
||||
IExpression LeftExpression { get; set; }
|
||||
IExpression RightExpression { get; set; }
|
||||
|
||||
public SubstructExpression(IExpression left, IExpression right)
|
||||
{
|
||||
LeftExpression = left;
|
||||
RightExpression = right;
|
||||
}
|
||||
|
||||
public int Interpret(Context context)
|
||||
{
|
||||
return LeftExpression.Interpret(context) - RightExpression.Interpret(context);
|
||||
}
|
||||
}
|
10
Patterns/Iterator/Iterator.csproj
Normal file
10
Patterns/Iterator/Iterator.csproj
Normal file
@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
263
Patterns/Iterator/Program.cs
Normal file
263
Patterns/Iterator/Program.cs
Normal file
@ -0,0 +1,263 @@
|
||||
/* Итератор
|
||||
Предоставляет способ последовательного
|
||||
доступа к множеству, независимо от его
|
||||
внутреннего устройства
|
||||
*/
|
||||
class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
#region Пример №1 - базовое
|
||||
Library library = new Library();
|
||||
Reader reader = new Reader();
|
||||
reader.SetBooks(library);
|
||||
Console.ReadKey();
|
||||
#endregion
|
||||
#region Пример №2 - пример работы стека
|
||||
DataStack stack = new DataStack();
|
||||
for (int i = 0; i < 5; i++)
|
||||
stack.Push(i);
|
||||
|
||||
DataStack stackCopy = new DataStack(stack);
|
||||
|
||||
Console.WriteLine(stack == stackCopy); //true
|
||||
|
||||
stackCopy.Push(10);
|
||||
|
||||
Console.WriteLine(stack == stackCopy); //false
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Читатель
|
||||
/// </summary>
|
||||
class Reader
|
||||
{
|
||||
public void SetBooks(Library library)
|
||||
{
|
||||
IBookIterator iterator = library.CreateNumerator();
|
||||
while(iterator.HasNext())
|
||||
{
|
||||
Book book = iterator.Next();
|
||||
Console.WriteLine(book.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Поведение поиска библиотеки
|
||||
/// </summary>
|
||||
interface IBookIterator
|
||||
{
|
||||
bool HasNext();
|
||||
Book Next();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Поведение библиотеки
|
||||
/// </summary>
|
||||
interface IBookNumerable
|
||||
{
|
||||
IBookIterator CreateNumerator();
|
||||
int Count { get; }
|
||||
Book this[int index] { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Класс книги
|
||||
/// </summary>
|
||||
class Book
|
||||
{
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Класс библиотеки книг
|
||||
/// </summary>
|
||||
class Library : IBookNumerable
|
||||
{
|
||||
private Book[] Books { get; set; }
|
||||
|
||||
public Library()
|
||||
{
|
||||
Books = new Book[]
|
||||
{
|
||||
new Book(){ Name = "James"},
|
||||
new Book(){ Name = "Karl"},
|
||||
new Book(){ Name = "Rogan"}
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Вызов книги
|
||||
/// </summary>
|
||||
/// <param name="index">индекс в библиотеке</param>
|
||||
/// <returns>Book</returns>
|
||||
public Book this[int index] => Books[index];
|
||||
|
||||
/// <summary>
|
||||
/// Количество книг в библиотеке
|
||||
/// </summary>
|
||||
public int Count => Books.Length;
|
||||
|
||||
/// <summary>
|
||||
/// Перейти к следующей библиотеке
|
||||
/// </summary>
|
||||
/// <returns>IBookIterator(LibraryNumenator)</returns>
|
||||
public IBookIterator CreateNumerator() => new LibraryNumenator(this);
|
||||
}
|
||||
|
||||
class LibraryNumenator : IBookIterator
|
||||
{
|
||||
IBookNumerable Aggregate { get; set; }
|
||||
int index = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Передача коллекции книг в Library
|
||||
/// </summary>
|
||||
/// <param name="bookNumerable"></param>
|
||||
public LibraryNumenator(IBookNumerable bookNumerable)
|
||||
{
|
||||
Aggregate = bookNumerable;
|
||||
}
|
||||
|
||||
public bool HasNext() => index < Aggregate.Count;
|
||||
|
||||
public Book Next() => Aggregate[index++];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Класс стека данных
|
||||
/// </summary>
|
||||
public class DataStack
|
||||
{
|
||||
private int[] items = new int[10];
|
||||
/// <summary>
|
||||
/// Длинна массива данных в этом стеке
|
||||
/// </summary>
|
||||
private int lenght;
|
||||
|
||||
public DataStack() => lenght = -1;
|
||||
|
||||
/// <summary>
|
||||
/// Для копирования экземпляра класса
|
||||
/// </summary>
|
||||
/// <param name="myStack">Экземпляр данного класса</param>
|
||||
public DataStack(DataStack myStack)
|
||||
{
|
||||
this.items = myStack.items;
|
||||
this.lenght = myStack.lenght;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Свойство геттера для поля items
|
||||
/// </summary>
|
||||
public int[] Items { get => items; }
|
||||
|
||||
/// <summary>
|
||||
/// Свойство геттера для поля lenght
|
||||
/// </summary>
|
||||
public int Lenght { get => lenght; }
|
||||
|
||||
/// <summary>
|
||||
/// Добавление элементов в массив
|
||||
/// </summary>
|
||||
/// <param name="value">значение</param>
|
||||
public void Push(int value) => items[++lenght] = value;
|
||||
|
||||
/// <summary>
|
||||
/// Получение последнего элемента
|
||||
/// </summary>
|
||||
/// <returns>значение</returns>
|
||||
public int Pop() => items[lenght--];
|
||||
|
||||
/// <summary>
|
||||
/// Переопределение оператора сравнения двух экземпляров данного класса
|
||||
/// </summary>
|
||||
/// <param name="left"></param>
|
||||
/// <param name="right"></param>
|
||||
/// <returns>bool</returns>
|
||||
public static bool operator ==(DataStack left, DataStack right)
|
||||
{
|
||||
StackIterator it1 = new StackIterator(left),
|
||||
it2 = new StackIterator(right);
|
||||
|
||||
while (it1.IsEnd() || it2.IsEnd())
|
||||
{
|
||||
if (it1.Get() != it2.Get()) break;
|
||||
it1++;
|
||||
it2++;
|
||||
}
|
||||
|
||||
return !it1.IsEnd() && !it2.IsEnd();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Переопределение оператора сравнения двух экземпляров данного класса
|
||||
/// </summary>
|
||||
/// <param name="left"></param>
|
||||
/// <param name="right"></param>
|
||||
/// <returns>bool</returns>
|
||||
public static bool operator !=(DataStack left, DataStack right)
|
||||
{
|
||||
StackIterator it1 = new StackIterator(left),
|
||||
it2 = new StackIterator(right);
|
||||
|
||||
while (it1.IsEnd() || it2.IsEnd())
|
||||
{
|
||||
if (it1.Get() != it2.Get()) break;
|
||||
it1++;
|
||||
it2++;
|
||||
}
|
||||
|
||||
return !it1.IsEnd() && !it2.IsEnd();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Перечислитель
|
||||
/// </summary>
|
||||
class StackIterator
|
||||
{
|
||||
private DataStack stack;
|
||||
private int index;
|
||||
|
||||
/// <summary>
|
||||
/// Инициализируем поля перечислителя
|
||||
/// </summary>
|
||||
/// <param name="dataStack">данные</param>
|
||||
public StackIterator(DataStack dataStack)
|
||||
{
|
||||
this.stack = dataStack;
|
||||
this.index = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Переопределение опреатора инкрементирования
|
||||
/// </summary>
|
||||
/// <param name="s">новый переданный экземпляр класса</param>
|
||||
/// <returns>экземпляр класса с инкрементированым значением index</returns>
|
||||
public static StackIterator operator ++(StackIterator s)
|
||||
{
|
||||
s.index++;
|
||||
return s;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Возвращает значение элемента поля стека
|
||||
/// через его свойство по текущему индексу
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public int Get()
|
||||
{
|
||||
if(index < stack.Lenght) return stack.Items[index];
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Возвращет true при достижении предельного размера стека
|
||||
/// </summary>
|
||||
/// <returns>bool</returns>
|
||||
public bool IsEnd() => index != stack.Lenght + 1;
|
||||
}
|
23
Patterns/LetCode.Tests/LetCode.Tests.csproj
Normal file
23
Patterns/LetCode.Tests/LetCode.Tests.csproj
Normal file
@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="2.2.10" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="2.2.10" />
|
||||
<PackageReference Include="coverlet.collector" Version="3.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\LetCode\LetCode.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
65
Patterns/LetCode.Tests/Tests.cs
Normal file
65
Patterns/LetCode.Tests/Tests.cs
Normal file
@ -0,0 +1,65 @@
|
||||
namespace LetCode.Tests
|
||||
{
|
||||
[TestClass]
|
||||
public class Tests
|
||||
{
|
||||
/// <summary>
|
||||
/// Èíäåêñû ÷èñåë â ìàññèâå îáðàçóþùèõ ÷èñëî target
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TwoSumTest()
|
||||
{
|
||||
// arrange
|
||||
int[] input = { 1, 2, 3 };
|
||||
int[] expected = { 0, 2 };
|
||||
|
||||
// act
|
||||
var actual = LetCodeTasks.TwoSum(input, 4);
|
||||
|
||||
// arrange
|
||||
CollectionAssert.AreEqual(expected, actual, $"actual: {string.Join(',', actual)}, expected: {string.Join(',', expected)}");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void IsPalindromeTest()
|
||||
{
|
||||
// arrange
|
||||
int input = 99;
|
||||
bool expected = true;
|
||||
|
||||
// act
|
||||
var actual = LetCodeTasks.IsPalindrome(input);
|
||||
|
||||
// arrange
|
||||
Assert.AreEqual(expected, actual, $"actual: {actual}, expected: {expected}");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void RomanToIntTest()
|
||||
{
|
||||
// arrange
|
||||
string input = "MCMXCIV";
|
||||
int expected = 1994;
|
||||
|
||||
// act
|
||||
var actual = LetCodeTasks.RomanToInt(input);
|
||||
|
||||
// arrange
|
||||
Assert.AreEqual(expected, actual, $"actual: {actual}, expected: {expected}");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void LongestCommonPrefixTest()
|
||||
{
|
||||
// arrange
|
||||
string[] input = { "XXVIII", "XX", "XXII" };
|
||||
string expected = "XX";
|
||||
|
||||
// act
|
||||
var actual = LetCodeTasks.LongestCommonPrefix(input);
|
||||
|
||||
// arrange
|
||||
Assert.AreEqual(expected, actual, $"actual: {actual}, expected: {expected}");
|
||||
}
|
||||
}
|
||||
}
|
1
Patterns/LetCode.Tests/Usings.cs
Normal file
1
Patterns/LetCode.Tests/Usings.cs
Normal file
@ -0,0 +1 @@
|
||||
global using Microsoft.VisualStudio.TestTools.UnitTesting;
|
10
Patterns/LetCode/LetCode.csproj
Normal file
10
Patterns/LetCode/LetCode.csproj
Normal file
@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
160
Patterns/LetCode/Program.cs
Normal file
160
Patterns/LetCode/Program.cs
Normal file
@ -0,0 +1,160 @@
|
||||
public static class LetCodeTasks
|
||||
{
|
||||
/// <summary>
|
||||
/// Какие числа массива дают в сумме указанное число
|
||||
/// </summary>
|
||||
/// <param name="nums">Массив чисел</param>
|
||||
/// <param name="target">Искомая сумма</param>
|
||||
/// <returns>Массив индексов чисел</returns>
|
||||
public static int[] TwoSum(int[] nums, int target)
|
||||
{
|
||||
int countNew = 0;
|
||||
int[] weeks = { };
|
||||
for (int k = 0; k < nums.Length-1; k++)
|
||||
{
|
||||
for(int i = 1; i < nums.Length; i++)
|
||||
{
|
||||
int a1 = nums[k];
|
||||
int a2 = nums[i];
|
||||
if (a1 + a2 == target)
|
||||
{
|
||||
if(k != i && k < i)
|
||||
{
|
||||
countNew++;
|
||||
Array.Resize(ref weeks, weeks.Length + 2);
|
||||
weeks[weeks.Length - 2] = k;
|
||||
weeks[weeks.Length - 1] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return weeks;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Проверяет число на верность свойствам полиндрома
|
||||
/// </summary>
|
||||
/// <param name="x">Число</param>
|
||||
/// <returns>Полиндром или нет</returns>
|
||||
public static bool IsPalindrome(int x)
|
||||
{
|
||||
if(x.ToString().Length > 3)
|
||||
{
|
||||
for (int i = 0; i < x.ToString().Length; i++)
|
||||
{
|
||||
if (x.ToString()[i] != x.ToString()[x.ToString().Length - (i + 1)])
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(x >= 0 && x.ToString()[0] == x.ToString()[x.ToString().Length-1])
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Переводит римские цифры в реальное число
|
||||
/// </summary>
|
||||
/// <param name="s">Римский символ</param>
|
||||
/// <returns>Число</returns>
|
||||
public static int RomanToInt(string s)
|
||||
{
|
||||
var mapNumbers = new Dictionary<int, char>()
|
||||
{
|
||||
{ 1, 'I' }, { 5, 'V' }, { 10, 'X' }, { 50, 'L' }, { 100, 'C' }, { 500, 'D' }, { 1000, 'M' }
|
||||
};
|
||||
char symTmp = ' ';
|
||||
int[] sumArray = { };
|
||||
for (int i = 0; i < s.Length; i++)
|
||||
{
|
||||
foreach (var number in mapNumbers.Values)
|
||||
{
|
||||
if(number == s[i])
|
||||
{
|
||||
int numberRes = 0;
|
||||
switch($"{symTmp}{number}")
|
||||
{
|
||||
case "IV":
|
||||
numberRes = 4;
|
||||
Array.Resize(ref sumArray, sumArray.Length - 1);
|
||||
break;
|
||||
case "IX":
|
||||
numberRes = 9;
|
||||
Array.Resize(ref sumArray, sumArray.Length - 1);
|
||||
break;
|
||||
case "XL":
|
||||
numberRes = 40;
|
||||
Array.Resize(ref sumArray, sumArray.Length - 1);
|
||||
break;
|
||||
case "XC":
|
||||
numberRes = 90;
|
||||
Array.Resize(ref sumArray, sumArray.Length - 1);
|
||||
break;
|
||||
case "CD":
|
||||
numberRes = 400;
|
||||
Array.Resize(ref sumArray, sumArray.Length - 1);
|
||||
break;
|
||||
case "CM":
|
||||
numberRes = 900;
|
||||
Array.Resize(ref sumArray, sumArray.Length - 1);
|
||||
break;
|
||||
}
|
||||
if(numberRes == 0)
|
||||
numberRes = mapNumbers.Where(x => x.Value == number).FirstOrDefault().Key;
|
||||
Array.Resize(ref sumArray, sumArray.Length + 1);
|
||||
sumArray[sumArray.Length - 1] = numberRes;
|
||||
symTmp = number;
|
||||
}
|
||||
}
|
||||
}
|
||||
return sumArray.Sum();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Вычисляет совпадение частей слов в массиве слов
|
||||
/// </summary>
|
||||
/// <param name="strs">Массив слов</param>
|
||||
/// <returns>Подстрока обобщающая все слова</returns>
|
||||
public static string LongestCommonPrefix(string[] strs)
|
||||
{
|
||||
if (strs.Length == 0)
|
||||
return "";
|
||||
if(strs.Length == 1)
|
||||
return strs[0];
|
||||
string prefix = string.Empty;
|
||||
int[] leghts = { };
|
||||
int tmpIndex = 0;
|
||||
for (int i = 1; i < strs.Length; i++)
|
||||
{
|
||||
char[] word1 = strs[i-1].ToCharArray();
|
||||
char[] word2 = strs[i].ToCharArray();
|
||||
tmpIndex = 0;
|
||||
for (int j = 0; j < word1.Length; j++)
|
||||
{
|
||||
if (word2.Length >= j + 1 && word1[j] == word2[j])
|
||||
{
|
||||
tmpIndex++;
|
||||
if (prefix.Length < j + 1)
|
||||
prefix += word1[j];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tmpIndex == 0)
|
||||
return "";
|
||||
break;
|
||||
}
|
||||
}
|
||||
Array.Resize(ref leghts, leghts.Length + 1);
|
||||
leghts[leghts.Length - 1] = tmpIndex;
|
||||
}
|
||||
if (prefix.Length > 0)
|
||||
prefix = prefix.Substring(0, leghts.Min());
|
||||
else
|
||||
return "";
|
||||
return prefix;
|
||||
}
|
||||
|
||||
static void Main()
|
||||
{
|
||||
Console.ReadKey();
|
||||
}
|
||||
}
|
10
Patterns/Mediator/Mediator.csproj
Normal file
10
Patterns/Mediator/Mediator.csproj
Normal file
@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
112
Patterns/Mediator/Program.cs
Normal file
112
Patterns/Mediator/Program.cs
Normal file
@ -0,0 +1,112 @@
|
||||
/* Посредник
|
||||
Определяет объект инкапсулирующий способ
|
||||
взаимодействия объектов. Обеспечивает слабую связь,
|
||||
избавляя их от необходимости ссылаться друг на друга
|
||||
и даёт возможность независимо изменять их взаимодействие.
|
||||
*/
|
||||
class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
#region Пример №1 - базовое
|
||||
ManagerMediator mediator = new ManagerMediator();
|
||||
Colleague customer = new CustomerCollegue(mediator);
|
||||
Colleague programmer = new ProgrammerCollegue(mediator);
|
||||
Colleague tester = new TesterCollegue(mediator);
|
||||
mediator.Customer = customer;
|
||||
mediator.Programmer = programmer;
|
||||
mediator.Tester = tester;
|
||||
customer.Send("Есть заказ! Нужно сделать REST API");
|
||||
programmer.Send("REST API готов, нужно протестировать swagger");
|
||||
tester.Send("Тест прошёл успешно, документация отличная!");
|
||||
Console.ReadKey();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Интерфейс для взаимодействия с посредником
|
||||
/// </summary>
|
||||
abstract class Mediator
|
||||
{
|
||||
public abstract void Send(string message, Colleague colleague);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Интерфейс для взаимодействия с коллегами
|
||||
/// </summary>
|
||||
abstract class Colleague
|
||||
{
|
||||
Mediator Mediator { get; set; }
|
||||
|
||||
public Colleague(Mediator mediator)
|
||||
{
|
||||
Mediator = mediator;
|
||||
}
|
||||
|
||||
public virtual void Send(string message)
|
||||
{
|
||||
Mediator.Send(message, this);
|
||||
}
|
||||
|
||||
public abstract void Notify(string message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Непосредственный заказчик
|
||||
/// </summary>
|
||||
class CustomerCollegue : Colleague
|
||||
{
|
||||
public CustomerCollegue(Mediator mediator) : base(mediator) {}
|
||||
|
||||
public override void Notify(string message)
|
||||
{
|
||||
Console.WriteLine($"Сообщение заказчику: {message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Программист
|
||||
/// </summary>
|
||||
class ProgrammerCollegue : Colleague
|
||||
{
|
||||
public ProgrammerCollegue(Mediator mediator) : base(mediator) { }
|
||||
|
||||
public override void Notify(string message)
|
||||
{
|
||||
Console.WriteLine($"Сообщение программисту: {message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Тестировщик
|
||||
/// </summary>
|
||||
class TesterCollegue : Colleague
|
||||
{
|
||||
public TesterCollegue(Mediator mediator) : base(mediator) { }
|
||||
|
||||
public override void Notify(string message)
|
||||
{
|
||||
Console.WriteLine($"Сообщение тестировщику: {message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Посредник
|
||||
/// </summary>
|
||||
class ManagerMediator : Mediator
|
||||
{
|
||||
public Colleague Customer { get; set; }
|
||||
public Colleague Programmer { get; set; }
|
||||
public Colleague Tester { get; set; }
|
||||
|
||||
public override void Send(string message, Colleague colleague)
|
||||
{
|
||||
if(Customer == colleague) //если отправитель заказчик значит есть новый заказ
|
||||
Programmer.Notify(message); //отправляем сообщение программисту - сделать заказ
|
||||
else if(Programmer == colleague) //если отправитель программист
|
||||
Tester.Notify(message); //отправляем сообщение тестировщику
|
||||
else if(Tester == colleague) //если отправитель тестировщик
|
||||
Customer.Notify(message); //значит оповещаем заказчика
|
||||
}
|
||||
}
|
10
Patterns/Memento/Memento.csproj
Normal file
10
Patterns/Memento/Memento.csproj
Normal file
@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>disable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
119
Patterns/Memento/Program.cs
Normal file
119
Patterns/Memento/Program.cs
Normal file
@ -0,0 +1,119 @@
|
||||
/* Хранитель + Одиночка
|
||||
Не нарушая инкапсуляцию, определяет
|
||||
и сохраняет внутреннее состояние объекта и
|
||||
позволяет позже восстановить объект в этом
|
||||
состоянии
|
||||
*/
|
||||
class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
#region Пример №1 - базовое
|
||||
using (var hero = new Hero())
|
||||
{
|
||||
hero.Shoot();
|
||||
}
|
||||
using (var heroMan = new Hero())
|
||||
{
|
||||
heroMan.RestoreState(GameHistory.Instance.History.Pop());
|
||||
heroMan.Shoot();
|
||||
}
|
||||
Console.ReadKey();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Класс героя
|
||||
/// </summary>
|
||||
class Hero : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Количество патронов
|
||||
/// </summary>
|
||||
private int patrons = 10;
|
||||
|
||||
/// <summary>
|
||||
/// Выстрел
|
||||
/// </summary>
|
||||
public void Shoot()
|
||||
{
|
||||
if(patrons > 0)
|
||||
{
|
||||
patrons--;
|
||||
Console.WriteLine($"Осталось {patrons} патронов...");
|
||||
}
|
||||
else
|
||||
Console.WriteLine("Нет патронов");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Сохранение состояния
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public HeroMemento SaveState()
|
||||
{
|
||||
Console.WriteLine($"Сохранено - {patrons}");
|
||||
return new HeroMemento(patrons);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Восстановление состояния
|
||||
/// </summary>
|
||||
/// <param name="memento">Хранитель состояния</param>
|
||||
public void RestoreState(HeroMemento memento)
|
||||
{
|
||||
patrons = memento.Patrons;
|
||||
Console.WriteLine($"Загружено - {patrons}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Удаление из памяти + сохранение в истории последнего состояния
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
GameHistory.Instance.History.Push(SaveState());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Memento - Хранитель состояния
|
||||
/// </summary>
|
||||
class HeroMemento
|
||||
{
|
||||
public int Patrons { get; private set; }
|
||||
|
||||
public HeroMemento(int patrons)
|
||||
{
|
||||
Patrons = patrons;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Caretaker - смотритель состояния
|
||||
/// </summary>
|
||||
class GameHistory
|
||||
{
|
||||
private static GameHistory instance;
|
||||
public Stack<HeroMemento> History { get; set; }
|
||||
|
||||
private GameHistory()
|
||||
{
|
||||
History = new Stack<HeroMemento>();
|
||||
}
|
||||
|
||||
public static GameHistory Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if(instance == null)
|
||||
instance = new GameHistory();
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
History.Clear();
|
||||
}
|
||||
}
|
10
Patterns/Observer/Observer.csproj
Normal file
10
Patterns/Observer/Observer.csproj
Normal file
@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
103
Patterns/Observer/Program.cs
Normal file
103
Patterns/Observer/Program.cs
Normal file
@ -0,0 +1,103 @@
|
||||
/* Наблюдатель
|
||||
Определяет зависимость один ко многим
|
||||
между объектами так, что когда один меняет
|
||||
своё состояние, все зависимые объекты оповещаются
|
||||
и обновляются автоматически
|
||||
*/
|
||||
class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
#region Пример №1 - базовое
|
||||
var concreteObservable = new ConcreteObservable();
|
||||
concreteObservable.AddObserver(new Observer("Job"));
|
||||
concreteObservable.AddObserver(new Observer("Robin"));
|
||||
concreteObservable.AddObserver(new Observer("Jaz"));
|
||||
concreteObservable.AddObserver(new Observer("John"));
|
||||
Console.ReadKey();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Поведение наблюдателя
|
||||
/// </summary>
|
||||
interface IObservable
|
||||
{
|
||||
/// <summary>
|
||||
/// Добавить наблюдаемого
|
||||
/// </summary>
|
||||
/// <param name="observer">Наблюдаемый</param>
|
||||
void AddObserver(IObserver observer);
|
||||
/// <summary>
|
||||
/// Удалить наблюдаемого
|
||||
/// </summary>
|
||||
/// <param name="observer">Наблюдаемый</param>
|
||||
void RemoveObserver(IObserver observer);
|
||||
/// <summary>
|
||||
/// Оповестить всех наблюдаемых
|
||||
/// </summary>
|
||||
void NotifyObservers();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Реализация конкретного наблюдателя
|
||||
/// </summary>
|
||||
class ConcreteObservable : IObservable
|
||||
{
|
||||
/// <summary>
|
||||
/// Список наблюдаемых
|
||||
/// </summary>
|
||||
private List<IObserver> _observers;
|
||||
|
||||
public ConcreteObservable()
|
||||
{
|
||||
_observers = new List<IObserver>();
|
||||
}
|
||||
|
||||
public void AddObserver(IObserver observer)
|
||||
{
|
||||
Console.WriteLine("Event Add Observer");
|
||||
NotifyObservers();
|
||||
_observers.Add(observer);
|
||||
}
|
||||
|
||||
public void NotifyObservers()
|
||||
{
|
||||
if(_observers.Count == 0) Console.WriteLine("Не кого оповещать...");
|
||||
foreach (var observer in _observers)
|
||||
observer.Update();
|
||||
}
|
||||
|
||||
public void RemoveObserver(IObserver observer)
|
||||
{
|
||||
_observers.Remove(observer);
|
||||
NotifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Поведение наблюдаемого
|
||||
/// </summary>
|
||||
interface IObserver
|
||||
{
|
||||
void Update();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Наблюдаемый
|
||||
/// </summary>
|
||||
class Observer : IObserver
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public Observer(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
Console.WriteLine($"Update {Name}");
|
||||
}
|
||||
}
|
269
Patterns/Patterns Programming.sln
Normal file
269
Patterns/Patterns Programming.sln
Normal file
@ -0,0 +1,269 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.2.32616.157
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Behavioral(Поведенческие)", "Behavioral(Поведенческие)", "{749199BB-F36F-4019-BFEB-B04475AB5140}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Structural(Структурные)", "Structural(Структурные)", "{3E3D01F2-BFF2-417A-BEAD-0E0AD3547A8D}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Creational(Порождающие)", "Creational(Порождающие)", "{6B6B76CA-287A-4FA5-99FE-8098611020F9}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Memento", "Memento\Memento.csproj", "{B4BD097B-27B4-4AAE-AC40-E0CA633B2A32}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ChainOfResponsibility", "ChainOfResponsibility\ChainOfResponsibility.csproj", "{CFC9F6BF-FC2B-446E-8FB5-92A1E06CAE91}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Observer", "Observer\Observer.csproj", "{72179984-1F4B-4C89-8E29-49D8C8B18A94}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Command", "Command\Command.csproj", "{C4EBB3CE-6BBD-473E-8CAC-012015F8FEA1}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "State", "State\State.csproj", "{5EA8980C-B0B1-4C20-93C8-92EFE4B88708}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Interpreter", "Interpreter\Interpreter.csproj", "{E470CB5E-7369-44DB-8192-5A2567865A83}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Strategy", "Strategy\Strategy.csproj", "{6566D5A3-F886-4E66-9E98-7FA536D7B4D4}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Iterator", "Iterator\Iterator.csproj", "{2BFCAE0E-EBBC-4673-AC56-AA007679A15F}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TemplateMethod", "TemplateMethod\TemplateMethod.csproj", "{2411F3F1-D28B-4939-85D9-921847678065}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mediator", "Mediator\Mediator.csproj", "{09C6E1FA-6553-4C92-9D38-613A9A8D155B}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Visitor", "Visitor\Visitor.csproj", "{737EB7A2-98B4-473A-81B9-9CAB3BEB69CF}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Base Logic(Базовые понятия)", "Base Logic(Базовые понятия)", "{4FF822AA-F380-4D92-86B0-50FE5CE6BCEE}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BaseInfo", "Base\BaseInfo.csproj", "{3E397CB2-2AAF-4D66-855D-E2BA198C380E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Base.Tests", "BaseTests\Base.Tests.csproj", "{90CB9984-E9D1-4821-BA45-D2C668A81813}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DictionaryInfo", "Dict\DictionaryInfo.csproj", "{279CA287-2FCE-45C7-BBD8-4E3941B09028}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LetCode", "LetCode\LetCode.csproj", "{71DA93E5-2EB8-4C26-9537-3C1F18DFEC15}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Adapter", "Adapter\Adapter.csproj", "{467EF678-626C-4CBB-B608-234CA2DD8613}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Proxy", "Proxy\Proxy.csproj", "{6BED2E46-471C-484E-A7BA-EFD41A981EF3}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bridge", "Bridge\Bridge.csproj", "{47297A10-E472-454B-B333-5554789B8D21}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Composite", "Composite\Composite.csproj", "{34A7974D-A37A-4D79-AF2A-5EECC9295884}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Decorator", "Decorator\Decorator.csproj", "{751A645A-8E65-4556-A322-5170CC3CA905}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Facade", "Facade\Facade.csproj", "{770B90B9-DD17-4279-AE68-FCC6E3783D05}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flyweight", "Flyweight\Flyweight.csproj", "{A0DB1337-5532-49C3-99DD-BEBE27F9B382}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AbstractFactory", "AbstractFactory\AbstractFactory.csproj", "{28A8AFD1-7FDB-45E4-A349-1BDD1FEB53C2}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FactoryMethod", "FactoryMethod\FactoryMethod.csproj", "{206CBCB3-8D1F-47A7-B510-AC9D34C8CBD3}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Builder", "Builder\Builder.csproj", "{B4567CE3-9BEC-445E-8830-B4B206FA7641}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentBuilder", "FluentBuilder\FluentBuilder.csproj", "{BA3B2D0E-484B-4075-92F5-D84B10EFDE4D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Prototype", "Prototype\Prototype.csproj", "{F92E5A05-034A-43E4-A7DB-0073C3E322EC}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Singleton", "Singleton\Singleton.csproj", "{E17B2354-AD60-4083-BA38-6A9BD85F81B3}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LetCode.Tests", "LetCode.Tests\LetCode.Tests.csproj", "{34F0E125-BE37-42FF-A679-4EBA9F29D86D}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Принципы проектирования", "Принципы проектирования", "{941BD935-75AD-4FEC-8D97-FD5D55905CF1}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "1_Принцип единственной обязанности", "1_Принцип единственной обязанности\1_Принцип единственной обязанности.csproj", "{4CEA5C3D-9E87-4AF9-8683-905A46D7006C}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "2_Принцип открытости, закрытости", "2_Принцип открытости, закрытости\2_Принцип открытости, закрытости.csproj", "{9CB78E60-6FFB-47C3-9BF3-F20FD7573C80}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "3_Принцип подстановки Барбары Лисков", "3_Принцип подстановки Барбары Лисков\3_Принцип подстановки Барбары Лисков.csproj", "{9A9FCDC5-8E2E-4CD1-9DCB-204A6A166732}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "4_Принцип разделения интерфейсов", "4_Принцип разделения интерфейсов\4_Принцип разделения интерфейсов.csproj", "{0268644C-135F-4217-AC55-B9139E2EA41B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "5_Принцип инверсии зависимостей", "5_Принцип инверсии зависимостей\5_Принцип инверсии зависимостей.csproj", "{C7CF08B8-7D0D-47D0-BA43-2488EF6E16E6}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{B4BD097B-27B4-4AAE-AC40-E0CA633B2A32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B4BD097B-27B4-4AAE-AC40-E0CA633B2A32}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B4BD097B-27B4-4AAE-AC40-E0CA633B2A32}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B4BD097B-27B4-4AAE-AC40-E0CA633B2A32}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CFC9F6BF-FC2B-446E-8FB5-92A1E06CAE91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CFC9F6BF-FC2B-446E-8FB5-92A1E06CAE91}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CFC9F6BF-FC2B-446E-8FB5-92A1E06CAE91}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CFC9F6BF-FC2B-446E-8FB5-92A1E06CAE91}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{72179984-1F4B-4C89-8E29-49D8C8B18A94}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{72179984-1F4B-4C89-8E29-49D8C8B18A94}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{72179984-1F4B-4C89-8E29-49D8C8B18A94}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{72179984-1F4B-4C89-8E29-49D8C8B18A94}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C4EBB3CE-6BBD-473E-8CAC-012015F8FEA1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C4EBB3CE-6BBD-473E-8CAC-012015F8FEA1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C4EBB3CE-6BBD-473E-8CAC-012015F8FEA1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C4EBB3CE-6BBD-473E-8CAC-012015F8FEA1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5EA8980C-B0B1-4C20-93C8-92EFE4B88708}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5EA8980C-B0B1-4C20-93C8-92EFE4B88708}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5EA8980C-B0B1-4C20-93C8-92EFE4B88708}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5EA8980C-B0B1-4C20-93C8-92EFE4B88708}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E470CB5E-7369-44DB-8192-5A2567865A83}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E470CB5E-7369-44DB-8192-5A2567865A83}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E470CB5E-7369-44DB-8192-5A2567865A83}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E470CB5E-7369-44DB-8192-5A2567865A83}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6566D5A3-F886-4E66-9E98-7FA536D7B4D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6566D5A3-F886-4E66-9E98-7FA536D7B4D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6566D5A3-F886-4E66-9E98-7FA536D7B4D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6566D5A3-F886-4E66-9E98-7FA536D7B4D4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2BFCAE0E-EBBC-4673-AC56-AA007679A15F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2BFCAE0E-EBBC-4673-AC56-AA007679A15F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2BFCAE0E-EBBC-4673-AC56-AA007679A15F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2BFCAE0E-EBBC-4673-AC56-AA007679A15F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2411F3F1-D28B-4939-85D9-921847678065}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2411F3F1-D28B-4939-85D9-921847678065}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2411F3F1-D28B-4939-85D9-921847678065}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2411F3F1-D28B-4939-85D9-921847678065}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{09C6E1FA-6553-4C92-9D38-613A9A8D155B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{09C6E1FA-6553-4C92-9D38-613A9A8D155B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{09C6E1FA-6553-4C92-9D38-613A9A8D155B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{09C6E1FA-6553-4C92-9D38-613A9A8D155B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{737EB7A2-98B4-473A-81B9-9CAB3BEB69CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{737EB7A2-98B4-473A-81B9-9CAB3BEB69CF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{737EB7A2-98B4-473A-81B9-9CAB3BEB69CF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{737EB7A2-98B4-473A-81B9-9CAB3BEB69CF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3E397CB2-2AAF-4D66-855D-E2BA198C380E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3E397CB2-2AAF-4D66-855D-E2BA198C380E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3E397CB2-2AAF-4D66-855D-E2BA198C380E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3E397CB2-2AAF-4D66-855D-E2BA198C380E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{90CB9984-E9D1-4821-BA45-D2C668A81813}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{90CB9984-E9D1-4821-BA45-D2C668A81813}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{90CB9984-E9D1-4821-BA45-D2C668A81813}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{90CB9984-E9D1-4821-BA45-D2C668A81813}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{279CA287-2FCE-45C7-BBD8-4E3941B09028}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{279CA287-2FCE-45C7-BBD8-4E3941B09028}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{279CA287-2FCE-45C7-BBD8-4E3941B09028}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{279CA287-2FCE-45C7-BBD8-4E3941B09028}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{71DA93E5-2EB8-4C26-9537-3C1F18DFEC15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{71DA93E5-2EB8-4C26-9537-3C1F18DFEC15}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{71DA93E5-2EB8-4C26-9537-3C1F18DFEC15}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{71DA93E5-2EB8-4C26-9537-3C1F18DFEC15}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{467EF678-626C-4CBB-B608-234CA2DD8613}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{467EF678-626C-4CBB-B608-234CA2DD8613}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{467EF678-626C-4CBB-B608-234CA2DD8613}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{467EF678-626C-4CBB-B608-234CA2DD8613}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6BED2E46-471C-484E-A7BA-EFD41A981EF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6BED2E46-471C-484E-A7BA-EFD41A981EF3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6BED2E46-471C-484E-A7BA-EFD41A981EF3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6BED2E46-471C-484E-A7BA-EFD41A981EF3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{47297A10-E472-454B-B333-5554789B8D21}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{47297A10-E472-454B-B333-5554789B8D21}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{47297A10-E472-454B-B333-5554789B8D21}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{47297A10-E472-454B-B333-5554789B8D21}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{34A7974D-A37A-4D79-AF2A-5EECC9295884}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{34A7974D-A37A-4D79-AF2A-5EECC9295884}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{34A7974D-A37A-4D79-AF2A-5EECC9295884}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{34A7974D-A37A-4D79-AF2A-5EECC9295884}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{751A645A-8E65-4556-A322-5170CC3CA905}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{751A645A-8E65-4556-A322-5170CC3CA905}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{751A645A-8E65-4556-A322-5170CC3CA905}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{751A645A-8E65-4556-A322-5170CC3CA905}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{770B90B9-DD17-4279-AE68-FCC6E3783D05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{770B90B9-DD17-4279-AE68-FCC6E3783D05}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{770B90B9-DD17-4279-AE68-FCC6E3783D05}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{770B90B9-DD17-4279-AE68-FCC6E3783D05}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A0DB1337-5532-49C3-99DD-BEBE27F9B382}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A0DB1337-5532-49C3-99DD-BEBE27F9B382}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A0DB1337-5532-49C3-99DD-BEBE27F9B382}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A0DB1337-5532-49C3-99DD-BEBE27F9B382}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{28A8AFD1-7FDB-45E4-A349-1BDD1FEB53C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{28A8AFD1-7FDB-45E4-A349-1BDD1FEB53C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{28A8AFD1-7FDB-45E4-A349-1BDD1FEB53C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{28A8AFD1-7FDB-45E4-A349-1BDD1FEB53C2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{206CBCB3-8D1F-47A7-B510-AC9D34C8CBD3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{206CBCB3-8D1F-47A7-B510-AC9D34C8CBD3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{206CBCB3-8D1F-47A7-B510-AC9D34C8CBD3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{206CBCB3-8D1F-47A7-B510-AC9D34C8CBD3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B4567CE3-9BEC-445E-8830-B4B206FA7641}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B4567CE3-9BEC-445E-8830-B4B206FA7641}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B4567CE3-9BEC-445E-8830-B4B206FA7641}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B4567CE3-9BEC-445E-8830-B4B206FA7641}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BA3B2D0E-484B-4075-92F5-D84B10EFDE4D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BA3B2D0E-484B-4075-92F5-D84B10EFDE4D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BA3B2D0E-484B-4075-92F5-D84B10EFDE4D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BA3B2D0E-484B-4075-92F5-D84B10EFDE4D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F92E5A05-034A-43E4-A7DB-0073C3E322EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F92E5A05-034A-43E4-A7DB-0073C3E322EC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F92E5A05-034A-43E4-A7DB-0073C3E322EC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F92E5A05-034A-43E4-A7DB-0073C3E322EC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E17B2354-AD60-4083-BA38-6A9BD85F81B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E17B2354-AD60-4083-BA38-6A9BD85F81B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E17B2354-AD60-4083-BA38-6A9BD85F81B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E17B2354-AD60-4083-BA38-6A9BD85F81B3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{34F0E125-BE37-42FF-A679-4EBA9F29D86D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{34F0E125-BE37-42FF-A679-4EBA9F29D86D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{34F0E125-BE37-42FF-A679-4EBA9F29D86D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{34F0E125-BE37-42FF-A679-4EBA9F29D86D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4CEA5C3D-9E87-4AF9-8683-905A46D7006C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4CEA5C3D-9E87-4AF9-8683-905A46D7006C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4CEA5C3D-9E87-4AF9-8683-905A46D7006C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4CEA5C3D-9E87-4AF9-8683-905A46D7006C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9CB78E60-6FFB-47C3-9BF3-F20FD7573C80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9CB78E60-6FFB-47C3-9BF3-F20FD7573C80}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9CB78E60-6FFB-47C3-9BF3-F20FD7573C80}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9CB78E60-6FFB-47C3-9BF3-F20FD7573C80}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9A9FCDC5-8E2E-4CD1-9DCB-204A6A166732}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9A9FCDC5-8E2E-4CD1-9DCB-204A6A166732}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9A9FCDC5-8E2E-4CD1-9DCB-204A6A166732}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9A9FCDC5-8E2E-4CD1-9DCB-204A6A166732}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0268644C-135F-4217-AC55-B9139E2EA41B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0268644C-135F-4217-AC55-B9139E2EA41B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0268644C-135F-4217-AC55-B9139E2EA41B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0268644C-135F-4217-AC55-B9139E2EA41B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C7CF08B8-7D0D-47D0-BA43-2488EF6E16E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C7CF08B8-7D0D-47D0-BA43-2488EF6E16E6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C7CF08B8-7D0D-47D0-BA43-2488EF6E16E6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C7CF08B8-7D0D-47D0-BA43-2488EF6E16E6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{B4BD097B-27B4-4AAE-AC40-E0CA633B2A32} = {749199BB-F36F-4019-BFEB-B04475AB5140}
|
||||
{CFC9F6BF-FC2B-446E-8FB5-92A1E06CAE91} = {749199BB-F36F-4019-BFEB-B04475AB5140}
|
||||
{72179984-1F4B-4C89-8E29-49D8C8B18A94} = {749199BB-F36F-4019-BFEB-B04475AB5140}
|
||||
{C4EBB3CE-6BBD-473E-8CAC-012015F8FEA1} = {749199BB-F36F-4019-BFEB-B04475AB5140}
|
||||
{5EA8980C-B0B1-4C20-93C8-92EFE4B88708} = {749199BB-F36F-4019-BFEB-B04475AB5140}
|
||||
{E470CB5E-7369-44DB-8192-5A2567865A83} = {749199BB-F36F-4019-BFEB-B04475AB5140}
|
||||
{6566D5A3-F886-4E66-9E98-7FA536D7B4D4} = {749199BB-F36F-4019-BFEB-B04475AB5140}
|
||||
{2BFCAE0E-EBBC-4673-AC56-AA007679A15F} = {749199BB-F36F-4019-BFEB-B04475AB5140}
|
||||
{2411F3F1-D28B-4939-85D9-921847678065} = {749199BB-F36F-4019-BFEB-B04475AB5140}
|
||||
{09C6E1FA-6553-4C92-9D38-613A9A8D155B} = {749199BB-F36F-4019-BFEB-B04475AB5140}
|
||||
{737EB7A2-98B4-473A-81B9-9CAB3BEB69CF} = {749199BB-F36F-4019-BFEB-B04475AB5140}
|
||||
{3E397CB2-2AAF-4D66-855D-E2BA198C380E} = {4FF822AA-F380-4D92-86B0-50FE5CE6BCEE}
|
||||
{90CB9984-E9D1-4821-BA45-D2C668A81813} = {4FF822AA-F380-4D92-86B0-50FE5CE6BCEE}
|
||||
{279CA287-2FCE-45C7-BBD8-4E3941B09028} = {4FF822AA-F380-4D92-86B0-50FE5CE6BCEE}
|
||||
{71DA93E5-2EB8-4C26-9537-3C1F18DFEC15} = {4FF822AA-F380-4D92-86B0-50FE5CE6BCEE}
|
||||
{467EF678-626C-4CBB-B608-234CA2DD8613} = {3E3D01F2-BFF2-417A-BEAD-0E0AD3547A8D}
|
||||
{6BED2E46-471C-484E-A7BA-EFD41A981EF3} = {3E3D01F2-BFF2-417A-BEAD-0E0AD3547A8D}
|
||||
{47297A10-E472-454B-B333-5554789B8D21} = {3E3D01F2-BFF2-417A-BEAD-0E0AD3547A8D}
|
||||
{34A7974D-A37A-4D79-AF2A-5EECC9295884} = {3E3D01F2-BFF2-417A-BEAD-0E0AD3547A8D}
|
||||
{751A645A-8E65-4556-A322-5170CC3CA905} = {3E3D01F2-BFF2-417A-BEAD-0E0AD3547A8D}
|
||||
{770B90B9-DD17-4279-AE68-FCC6E3783D05} = {3E3D01F2-BFF2-417A-BEAD-0E0AD3547A8D}
|
||||
{A0DB1337-5532-49C3-99DD-BEBE27F9B382} = {3E3D01F2-BFF2-417A-BEAD-0E0AD3547A8D}
|
||||
{28A8AFD1-7FDB-45E4-A349-1BDD1FEB53C2} = {6B6B76CA-287A-4FA5-99FE-8098611020F9}
|
||||
{206CBCB3-8D1F-47A7-B510-AC9D34C8CBD3} = {6B6B76CA-287A-4FA5-99FE-8098611020F9}
|
||||
{B4567CE3-9BEC-445E-8830-B4B206FA7641} = {6B6B76CA-287A-4FA5-99FE-8098611020F9}
|
||||
{BA3B2D0E-484B-4075-92F5-D84B10EFDE4D} = {6B6B76CA-287A-4FA5-99FE-8098611020F9}
|
||||
{F92E5A05-034A-43E4-A7DB-0073C3E322EC} = {6B6B76CA-287A-4FA5-99FE-8098611020F9}
|
||||
{E17B2354-AD60-4083-BA38-6A9BD85F81B3} = {6B6B76CA-287A-4FA5-99FE-8098611020F9}
|
||||
{34F0E125-BE37-42FF-A679-4EBA9F29D86D} = {4FF822AA-F380-4D92-86B0-50FE5CE6BCEE}
|
||||
{4CEA5C3D-9E87-4AF9-8683-905A46D7006C} = {941BD935-75AD-4FEC-8D97-FD5D55905CF1}
|
||||
{9CB78E60-6FFB-47C3-9BF3-F20FD7573C80} = {941BD935-75AD-4FEC-8D97-FD5D55905CF1}
|
||||
{9A9FCDC5-8E2E-4CD1-9DCB-204A6A166732} = {941BD935-75AD-4FEC-8D97-FD5D55905CF1}
|
||||
{0268644C-135F-4217-AC55-B9139E2EA41B} = {941BD935-75AD-4FEC-8D97-FD5D55905CF1}
|
||||
{C7CF08B8-7D0D-47D0-BA43-2488EF6E16E6} = {941BD935-75AD-4FEC-8D97-FD5D55905CF1}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {6A7DE462-3436-49E8-A6F0-59158DFB417F}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
132
Patterns/Prototype/Program.cs
Normal file
132
Patterns/Prototype/Program.cs
Normal file
@ -0,0 +1,132 @@
|
||||
/* Прототип
|
||||
Определяет несколько видов объектов,
|
||||
чтобы при создании использовать объект-прототип
|
||||
и создаёт новые объекты, копируя прототип
|
||||
(техника клонирования объектов)
|
||||
*/
|
||||
class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
#region Пример №1 - базовое
|
||||
IFigure cube = new Cube(10, 10);
|
||||
IFigure cloneCube = cube.Clone();
|
||||
IFigure cloneMemberCube = cube.CloneMember();
|
||||
cube.GetInfo();
|
||||
cloneCube.GetInfo();
|
||||
cloneMemberCube.GetInfo();
|
||||
#endregion
|
||||
|
||||
#region Пример №2
|
||||
IEntity entity = new Predator(10, 1000);
|
||||
var clone = entity.CloneEntity();
|
||||
entity.GetInfo();
|
||||
clone.GetInfo();
|
||||
Console.ReadKey();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Поведение фигуры
|
||||
/// </summary>
|
||||
interface IFigure
|
||||
{
|
||||
IFigure Clone();
|
||||
IFigure? CloneMember();
|
||||
void GetInfo();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Шаблон куба
|
||||
/// </summary>
|
||||
class Cube : IFigure
|
||||
{
|
||||
int Width { get; set; }
|
||||
int Height { get; set; }
|
||||
|
||||
public Cube(int width, int heght)
|
||||
{
|
||||
Width = width;
|
||||
Height = heght;
|
||||
}
|
||||
|
||||
public IFigure Clone()
|
||||
{
|
||||
return new Cube(Width, Height);
|
||||
}
|
||||
|
||||
public IFigure? CloneMember()
|
||||
{
|
||||
return this.MemberwiseClone() as IFigure;
|
||||
}
|
||||
|
||||
public void GetInfo()
|
||||
{
|
||||
Console.WriteLine($"Cube {Width}/{Height}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Треугольник
|
||||
/// </summary>
|
||||
class Rect : IFigure
|
||||
{
|
||||
int Width { get; set; }
|
||||
int Height { get; set; }
|
||||
|
||||
public Rect(int width, int heght)
|
||||
{
|
||||
Width = width;
|
||||
Height = heght;
|
||||
}
|
||||
|
||||
public IFigure Clone()
|
||||
{
|
||||
return new Rect(Width, Height);
|
||||
}
|
||||
|
||||
public IFigure? CloneMember()
|
||||
{
|
||||
return this.MemberwiseClone() as IFigure;
|
||||
}
|
||||
|
||||
public void GetInfo()
|
||||
{
|
||||
Console.WriteLine($"Rect {Width}/{Height}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Поведение сущности
|
||||
/// </summary>
|
||||
interface IEntity
|
||||
{
|
||||
IEntity CloneEntity();
|
||||
void GetInfo();
|
||||
}
|
||||
|
||||
abstract record Animal(int Paws, int Weight) : IEntity
|
||||
{
|
||||
public abstract IEntity CloneEntity();
|
||||
public abstract void GetInfo();
|
||||
}
|
||||
|
||||
record Predator(int Paws, int Weight) : Animal(Paws, Weight)
|
||||
{
|
||||
public override IEntity CloneEntity()
|
||||
=> this with { };
|
||||
|
||||
public override void GetInfo()
|
||||
=> Console.WriteLine($"Predator w={Weight} p={Paws}");
|
||||
}
|
||||
|
||||
record Person(int IQ) : IEntity
|
||||
{
|
||||
public IEntity CloneEntity()
|
||||
=> this with { };
|
||||
|
||||
public void GetInfo()
|
||||
=> Console.WriteLine($"Peaple with IQ={IQ}");
|
||||
}
|
||||
|
10
Patterns/Prototype/Prototype.csproj
Normal file
10
Patterns/Prototype/Prototype.csproj
Normal file
@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
94
Patterns/Proxy/Program.cs
Normal file
94
Patterns/Proxy/Program.cs
Normal file
@ -0,0 +1,94 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
/* Заместитель
|
||||
Предоставляет объект-заместитель другого объекта
|
||||
для контроля доступа к нему
|
||||
*/
|
||||
class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
#region Пример №1 - базовое
|
||||
using (IBook book = new BookStoreProxy())
|
||||
{
|
||||
//читаем первую страницу
|
||||
Page page1 = book.GetPage(1);
|
||||
Console.WriteLine(page1.Text);
|
||||
//читаем первую страницу
|
||||
Page page2 = book.GetPage(2);
|
||||
Console.WriteLine(page1.Text);
|
||||
//возвращаемся на первую страницу
|
||||
page1 = book.GetPage(1);
|
||||
Console.WriteLine(page1.Text);
|
||||
}
|
||||
Console.ReadKey();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// отдельная страница книги
|
||||
/// </summary>
|
||||
/// <param name="Id">Идентификатор</param>
|
||||
/// <param name="Number">Номер</param>
|
||||
/// <param name="Text">Содержимое</param>
|
||||
record Page(int Id, int Number, string Text);
|
||||
|
||||
class PageContext : DbContext
|
||||
{
|
||||
public DbSet<Page> Pages { get; set; }
|
||||
}
|
||||
|
||||
interface IBook : IDisposable
|
||||
{
|
||||
Page GetPage(int number);
|
||||
}
|
||||
|
||||
class BookStore : IBook
|
||||
{
|
||||
PageContext db;
|
||||
|
||||
public BookStore()
|
||||
{
|
||||
db = new PageContext();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
db.Dispose();
|
||||
}
|
||||
|
||||
public Page GetPage(int number)
|
||||
{
|
||||
return db.Pages.FirstOrDefault(p => p.Number == number);
|
||||
}
|
||||
}
|
||||
|
||||
class BookStoreProxy : IBook
|
||||
{
|
||||
List<Page> Pages;
|
||||
BookStore bookStore;
|
||||
|
||||
public BookStoreProxy()
|
||||
{
|
||||
Pages = new List<Page>();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (bookStore != null)
|
||||
bookStore.Dispose();
|
||||
}
|
||||
|
||||
public Page GetPage(int number)
|
||||
{
|
||||
Page page = Pages.FirstOrDefault(p => p.Number == number);
|
||||
if(page == null)
|
||||
{
|
||||
if(bookStore == null)
|
||||
bookStore = new BookStore();
|
||||
page = bookStore.GetPage(number);
|
||||
Pages.Add(page);
|
||||
}
|
||||
return page;
|
||||
}
|
||||
}
|
14
Patterns/Proxy/Proxy.csproj
Normal file
14
Patterns/Proxy/Proxy.csproj
Normal file
@ -0,0 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.8" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
44
Patterns/Singleton/Program.cs
Normal file
44
Patterns/Singleton/Program.cs
Normal file
@ -0,0 +1,44 @@
|
||||
/* Одиночка
|
||||
Гарантирует что класс имеет только
|
||||
один экземпляр и представляет глобальную
|
||||
точку доступа к нему
|
||||
*/
|
||||
|
||||
class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
#region Пример №1 - базовое
|
||||
(new Thread(() =>
|
||||
{
|
||||
Console.WriteLine(GameHistory.Instance.History[1]);
|
||||
})).Start();
|
||||
Console.WriteLine(GameHistory.Instance.History[0]);
|
||||
Console.ReadKey();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
class GameHistory
|
||||
{
|
||||
private static object syncRoot = new();
|
||||
private static GameHistory _instance;
|
||||
public static GameHistory Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
lock(syncRoot)
|
||||
{
|
||||
if(_instance == null)
|
||||
_instance = new GameHistory();
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
public string[] History { get; set; }
|
||||
private GameHistory()
|
||||
{
|
||||
History = new[] { "One History",
|
||||
"Two History"};
|
||||
}
|
||||
}
|
10
Patterns/Singleton/Singleton.csproj
Normal file
10
Patterns/Singleton/Singleton.csproj
Normal file
@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
76
Patterns/State/Program.cs
Normal file
76
Patterns/State/Program.cs
Normal file
@ -0,0 +1,76 @@
|
||||
/* Состояние
|
||||
Позволяет объекту изменять
|
||||
своё поведение в зависимости от
|
||||
внутреннего состояния
|
||||
*/
|
||||
class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
#region Пример №1 - базовое
|
||||
var contextA = new Context(new StateA());
|
||||
var contextB = new Context(new StateB());
|
||||
contextA.Request();
|
||||
contextB.Request();
|
||||
Console.ReadKey();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Абстракция состояния
|
||||
/// </summary>
|
||||
abstract class State
|
||||
{
|
||||
public abstract void Handle(Context context);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Реализация состояния A
|
||||
/// </summary>
|
||||
class StateA : State
|
||||
{
|
||||
public StateA()
|
||||
{
|
||||
Console.WriteLine("State-A Create...");
|
||||
}
|
||||
|
||||
public override void Handle(Context context)
|
||||
{
|
||||
context.State = new StateB();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Реализация состояния B
|
||||
/// </summary>
|
||||
class StateB : State
|
||||
{
|
||||
public StateB()
|
||||
{
|
||||
Console.WriteLine("State-B Create...");
|
||||
}
|
||||
|
||||
public override void Handle(Context context)
|
||||
{
|
||||
context.State = new StateA();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Контекст со своим состоянием
|
||||
/// </summary>
|
||||
class Context
|
||||
{
|
||||
public State State { get; set; }
|
||||
|
||||
public Context(State state)
|
||||
{
|
||||
State = state;
|
||||
}
|
||||
|
||||
public void Request()
|
||||
{
|
||||
State.Handle(this);
|
||||
}
|
||||
}
|
10
Patterns/State/State.csproj
Normal file
10
Patterns/State/State.csproj
Normal file
@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
6
Patterns/Strategy/ILogReader.cs
Normal file
6
Patterns/Strategy/ILogReader.cs
Normal file
@ -0,0 +1,6 @@
|
||||
namespace Strategy;
|
||||
|
||||
internal interface ILogReader
|
||||
{
|
||||
List<LogEntry> Read();
|
||||
}
|
15
Patterns/Strategy/LogEntry.cs
Normal file
15
Patterns/Strategy/LogEntry.cs
Normal file
@ -0,0 +1,15 @@
|
||||
namespace Strategy;
|
||||
|
||||
public enum LogType
|
||||
{
|
||||
Debug,
|
||||
Warning,
|
||||
Fatal
|
||||
}
|
||||
|
||||
public struct LogEntry
|
||||
{
|
||||
public DateTime DateTime { get; set; }
|
||||
public LogType LogType { get; set; }
|
||||
public string Message { get; set; }
|
||||
}
|
17
Patterns/Strategy/LogFileReader.cs
Normal file
17
Patterns/Strategy/LogFileReader.cs
Normal file
@ -0,0 +1,17 @@
|
||||
namespace Strategy;
|
||||
|
||||
public class LogFileReader : ILogReader
|
||||
{
|
||||
public List<LogEntry> Read()
|
||||
{
|
||||
return new List<LogEntry>()
|
||||
{
|
||||
new LogEntry()
|
||||
{
|
||||
DateTime = DateTime.Now,
|
||||
LogType = LogType.Debug,
|
||||
Message = GetType().Name
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
21
Patterns/Strategy/LogProcessor.cs
Normal file
21
Patterns/Strategy/LogProcessor.cs
Normal file
@ -0,0 +1,21 @@
|
||||
namespace Strategy;
|
||||
|
||||
public class LogProcessor
|
||||
{
|
||||
private readonly Func<List<LogEntry>> _logimporter;
|
||||
|
||||
public LogProcessor(Func<List<LogEntry>> logImporter)
|
||||
{
|
||||
_logimporter = logImporter;
|
||||
}
|
||||
|
||||
public void ProcessLogs()
|
||||
{
|
||||
foreach (var logEntry in _logimporter.Invoke())
|
||||
{
|
||||
Console.WriteLine(logEntry.DateTime);
|
||||
Console.WriteLine(logEntry.LogType);
|
||||
Console.WriteLine(logEntry.Message);
|
||||
}
|
||||
}
|
||||
}
|
218
Patterns/Strategy/Program.cs
Normal file
218
Patterns/Strategy/Program.cs
Normal file
@ -0,0 +1,218 @@
|
||||
/* Стратегия
|
||||
Определяет группу алгоритмов,
|
||||
инкапсулирует их и делает взаимозаменяемыми.
|
||||
Позволяет изменять алгоритм независимо от клиентов,
|
||||
его использующих.
|
||||
*/
|
||||
/*
|
||||
* На чем строилось:
|
||||
* СЕРГЕЙ ТЕПЛЯКОВ - Паттерны проектирования на платформе .Net
|
||||
* ШЕВЧУК, АХРИМЕНКО, КАСЬЯНОВ - Приемы объектно-ориентированного проектирования
|
||||
*
|
||||
* ПАТТЕРНЫ ПОВЕДЕНИЯ
|
||||
* Паттерн №1: Стратегия
|
||||
*
|
||||
* - является более контекстно зависимой операцией
|
||||
*
|
||||
* Причины применения:
|
||||
* 1.необходимость инкапсуляции поведения или алгоритма
|
||||
* 2.необходимость замены поведения или алгоритма во время исполнения
|
||||
*
|
||||
* Другими словами, стратегия обеспечивает точку расширения системы
|
||||
* в определенной плоскости: класс-контекст (LogProcessor) принимает экземпляр стратегии (LogFileReader)
|
||||
* и не знает, какой вариант стратегии он собирается использовать.
|
||||
*
|
||||
* Особенность:
|
||||
* Передача интерфейса ILogReader классу LogProcessor увеличивает гибкость,
|
||||
* но в то же время повышает сложность.
|
||||
* Теперь клиентам класса LogProcessor нужно решить, какую реализацию использовать,
|
||||
* или переложить эту ответственность на вызывающий код.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ВМЕСТО
|
||||
* классической стратегии на основе наследования
|
||||
* можно использовать стратегию на основе делегатов
|
||||
*
|
||||
* ПРИМЕР: Стратегия сортировки
|
||||
*/
|
||||
|
||||
/*
|
||||
* ВАЖНО: Гибкость не бывает бесплатной, поэтому выделять стратегии стоит тогда,
|
||||
* когда действительно нужна замена поведения во время исполнения.
|
||||
*/
|
||||
using Strategy;
|
||||
|
||||
class Program
|
||||
{
|
||||
#region Пример №3 - Сomparer
|
||||
public static void SortListId(List<Employee> list)
|
||||
{
|
||||
list.Sort(new EmployeeByIdComparer()); //используем функтор
|
||||
}
|
||||
|
||||
public static void SortListName(List<Employee> list)
|
||||
{
|
||||
list.Sort((x, y) => x.Name.CompareTo(y.Name)); //используем делегат
|
||||
}
|
||||
#endregion
|
||||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
#region Пример №1 - базовое
|
||||
var car = new Car(new PetrolMove());
|
||||
car.Move();
|
||||
car.Movable = new ElectronicMove();
|
||||
car.Move();
|
||||
Console.ReadKey();
|
||||
#endregion
|
||||
#region Пример №2 - ILogReader
|
||||
LogFileReader logFileReader = new LogFileReader();
|
||||
//создали делегат который принимает в себя метод,
|
||||
//в результате выполнения которого возвращается List<LogEntry>
|
||||
Func<List<LogEntry>> _import = () => logFileReader.Read();
|
||||
LogProcessor processor = new LogProcessor(_import);
|
||||
processor.ProcessLogs();
|
||||
#endregion
|
||||
#region Пример №3 - Сomparer
|
||||
List<Employee> employees = new List<Employee>
|
||||
{
|
||||
new Employee
|
||||
{
|
||||
Id = 8,
|
||||
Name = "asmus"
|
||||
},
|
||||
new Employee
|
||||
{
|
||||
Id = 1,
|
||||
Name = "robin"
|
||||
},
|
||||
new Employee
|
||||
{
|
||||
Id = 2,
|
||||
Name = "satan"
|
||||
},
|
||||
new Employee
|
||||
{
|
||||
Id = 5,
|
||||
Name = "dastin"
|
||||
}
|
||||
};
|
||||
SortListId(employees); //отсортировали по id через функтор
|
||||
SortListName(employees); //отсортировали по Name через делегат
|
||||
Console.WriteLine();
|
||||
var comparer = new EmployeeByIdComparer();
|
||||
var set = new SortedSet<Employee>(comparer); //конструктор принимает IComparable
|
||||
//нет конструктора, принимающего делегат Comparison<T>
|
||||
//можно создать небольшой адаптерный фабричный класс
|
||||
var comparer_factory = ComparerFactory.Create<Employee>((x, y) => x.Id.CompareTo(y.Id));
|
||||
//он помещает сюда фабрику
|
||||
var set_factory = new SortedSet<Employee>(comparer_factory);
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Поведение движения
|
||||
/// </summary>
|
||||
interface IMovable
|
||||
{
|
||||
void Move();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Бензиновый двигатель
|
||||
/// </summary>
|
||||
class PetrolMove : IMovable
|
||||
{
|
||||
public void Move()
|
||||
{
|
||||
Console.WriteLine("Движение на бензине");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Электродвигатель
|
||||
/// </summary>
|
||||
class ElectronicMove : IMovable
|
||||
{
|
||||
public void Move()
|
||||
{
|
||||
Console.WriteLine("Движение на электричестве");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Автомобиль
|
||||
/// </summary>
|
||||
class Car
|
||||
{
|
||||
/// <summary>
|
||||
/// Cпособ передвижения автомобиля
|
||||
/// </summary>
|
||||
public IMovable Movable { private get; set; }
|
||||
|
||||
public Car(IMovable movable)
|
||||
{
|
||||
Movable = movable;
|
||||
}
|
||||
|
||||
public void Move()
|
||||
{
|
||||
Movable.Move();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Employee
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string? Name { get; set; }
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format($"ID={Id}, Name={Name}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Реализует интерфейс сортировки
|
||||
/// Добавлет возможность сортировки по ID по возрастающей
|
||||
/// </summary>
|
||||
class EmployeeByIdComparer : IComparer<Employee>
|
||||
{
|
||||
int IComparer<Employee>.Compare(Employee? x, Employee? y)
|
||||
{
|
||||
if (x is Employee xx && y is Employee yy)
|
||||
return xx.Id.CompareTo(yy.Id);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Фабричный шаблон для создания экземпляров IComparer
|
||||
/// </summary>
|
||||
class ComparerFactory
|
||||
{
|
||||
public static IComparer<T> Create<T>(Comparison<T> comparer)
|
||||
{
|
||||
return new DelegateComparer<T>(comparer);
|
||||
}
|
||||
|
||||
private class DelegateComparer<T> : IComparer<T>
|
||||
{
|
||||
private readonly Comparison<T> _comparer;
|
||||
|
||||
public DelegateComparer(Comparison<T> comparer)
|
||||
{
|
||||
_comparer = comparer;
|
||||
}
|
||||
|
||||
public int Compare(T? x, T? y)
|
||||
{
|
||||
if (x == null || y == null)
|
||||
return 0;
|
||||
return _comparer(x, y);
|
||||
}
|
||||
}
|
||||
}
|
10
Patterns/Strategy/Strategy.csproj
Normal file
10
Patterns/Strategy/Strategy.csproj
Normal file
@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
17
Patterns/Strategy/WindowsEventLogReader.cs
Normal file
17
Patterns/Strategy/WindowsEventLogReader.cs
Normal file
@ -0,0 +1,17 @@
|
||||
namespace Strategy;
|
||||
|
||||
public class WindowsEventLogReader : ILogReader
|
||||
{
|
||||
public List<LogEntry> Read()
|
||||
{
|
||||
return new List<LogEntry>()
|
||||
{
|
||||
new LogEntry()
|
||||
{
|
||||
DateTime = DateTime.Now,
|
||||
Message = GetType().Name,
|
||||
LogType = LogType.Debug
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
115
Patterns/TemplateMethod/Program.cs
Normal file
115
Patterns/TemplateMethod/Program.cs
Normal file
@ -0,0 +1,115 @@
|
||||
/* Шаблонный метод
|
||||
Определяет алгоритм, некоторые этапы которого
|
||||
делегируются подклассам. Позволяет подклассам
|
||||
переопределить эти этапы, не меняя структуру алгоритма.
|
||||
*/
|
||||
class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
#region Пример №1 - базовое
|
||||
new School().Learn();
|
||||
new University().Learn();
|
||||
Console.ReadKey();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Представление образовательного процесса
|
||||
/// </summary>
|
||||
abstract class Education
|
||||
{
|
||||
/// <summary>
|
||||
/// Обучение
|
||||
/// </summary>
|
||||
public virtual void Learn()
|
||||
{
|
||||
Enter();
|
||||
Study();
|
||||
PassExams();
|
||||
GetDocument();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение документа об окончании образования
|
||||
/// </summary>
|
||||
protected abstract void GetDocument();
|
||||
/// <summary>
|
||||
/// Cдача экзаменов в учебном заведении
|
||||
/// </summary>
|
||||
protected abstract void PassExams();
|
||||
/// <summary>
|
||||
/// Обучение в учебном заведении
|
||||
/// </summary>
|
||||
protected abstract void Study();
|
||||
/// <summary>
|
||||
/// Поступление в учебное заведение
|
||||
/// </summary>
|
||||
protected abstract void Enter();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Школа реализовывающее процесс образования со своими дополнениями
|
||||
/// </summary>
|
||||
class School : Education
|
||||
{
|
||||
protected override void Enter()
|
||||
{
|
||||
Console.WriteLine("Поступил в школу");
|
||||
}
|
||||
|
||||
protected override void GetDocument()
|
||||
{
|
||||
Console.WriteLine("Получил аттестат");
|
||||
}
|
||||
|
||||
protected override void PassExams()
|
||||
{
|
||||
Console.WriteLine("Сдал ЕГЭ и ОГЭ");
|
||||
}
|
||||
|
||||
public void ExtraExams()
|
||||
{
|
||||
Console.WriteLine("Ходил на олимпиады");
|
||||
}
|
||||
|
||||
protected override void Study()
|
||||
{
|
||||
Console.WriteLine("Обучился 11 классов");
|
||||
}
|
||||
|
||||
public override void Learn()
|
||||
{
|
||||
base.Learn();
|
||||
ExtraExams();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Университет реализовывающий процесса образования
|
||||
/// </summary>
|
||||
class University : Education
|
||||
{
|
||||
protected override void Enter()
|
||||
{
|
||||
Console.WriteLine("Поступил в университет");
|
||||
}
|
||||
|
||||
protected override void GetDocument()
|
||||
{
|
||||
Console.WriteLine("Получил диплом");
|
||||
}
|
||||
|
||||
protected override void PassExams()
|
||||
{
|
||||
Console.WriteLine("Сдал экзамены и зачёты");
|
||||
}
|
||||
|
||||
protected override void Study()
|
||||
{
|
||||
Console.WriteLine("Ходил на пары");
|
||||
Console.WriteLine("Ходил на лекции");
|
||||
Console.WriteLine("Сдавал лабораторные работы");
|
||||
}
|
||||
}
|
10
Patterns/TemplateMethod/TemplateMethod.csproj
Normal file
10
Patterns/TemplateMethod/TemplateMethod.csproj
Normal file
@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
138
Patterns/Visitor/Program.cs
Normal file
138
Patterns/Visitor/Program.cs
Normal file
@ -0,0 +1,138 @@
|
||||
/* Посетитель
|
||||
Представляет собой операцию, которая
|
||||
будет выполнена над объектами группы классов.
|
||||
Даёт возможность определить новую операцию
|
||||
без изменения кода классов, над которыми
|
||||
эта операция производитcя.
|
||||
*/
|
||||
class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
#region Пример №1 - базовое
|
||||
var bank = new Bank();
|
||||
bank.Add(new Person(Name: "Joshua", Number: 1997));
|
||||
bank.Add(new Company(Name: "Microsoft", Number: 1904));
|
||||
bank.Accept(new HtmlVisitor());
|
||||
bank.Accept(new XmlVisitor());
|
||||
Console.ReadKey();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Поведение посетителя
|
||||
/// отделяет логику сериализации от классов в которых она применима
|
||||
/// </summary>
|
||||
interface IVisitor
|
||||
{
|
||||
void VisitPersonAcc(Person person);
|
||||
void VisitCompanyAcc(Company company);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Поведение аккаунта
|
||||
/// </summary>
|
||||
interface IAccaunt
|
||||
{
|
||||
void Accept(IVisitor visitor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Шаблон банка
|
||||
/// </summary>
|
||||
class Bank
|
||||
{
|
||||
List<IAccaunt> Accaunts;
|
||||
|
||||
public Bank()
|
||||
{
|
||||
Accaunts = new List<IAccaunt>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Добавить аккаунт
|
||||
/// </summary>
|
||||
/// <param name="accaunt">аккаунт</param>
|
||||
public void Add(IAccaunt accaunt)
|
||||
{
|
||||
Accaunts.Add(accaunt);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Удаллить аккаунт
|
||||
/// </summary>
|
||||
/// <param name="accaunt">аккаунт</param>
|
||||
public void Remove(IAccaunt accaunt)
|
||||
{
|
||||
Accaunts.Remove(accaunt);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получить доступ к своему аккаунту
|
||||
/// </summary>
|
||||
/// <param name="visitor">пользователь</param>
|
||||
public void Accept(IVisitor visitor)
|
||||
{
|
||||
foreach (var accaunt in Accaunts)
|
||||
accaunt.Accept(visitor);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Пользователь
|
||||
/// </summary>
|
||||
/// <param name="Name">Имя</param>
|
||||
/// <param name="Number">Номер</param>
|
||||
record Person(string Name, int Number) : IAccaunt
|
||||
{
|
||||
public void Accept(IVisitor visitor)
|
||||
{
|
||||
visitor.VisitPersonAcc(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Компания
|
||||
/// </summary>
|
||||
/// <param name="Name">Имя</param>
|
||||
/// <param name="Number">Номер</param>
|
||||
record Company(string Name, int Number) : IAccaunt
|
||||
{
|
||||
public void Accept(IVisitor visitor)
|
||||
{
|
||||
visitor.VisitCompanyAcc(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// HTML сериализатор
|
||||
/// </summary>
|
||||
class HtmlVisitor : IVisitor
|
||||
{
|
||||
public void VisitCompanyAcc(Company company)
|
||||
{
|
||||
Console.WriteLine($"[HTML] {company}");
|
||||
}
|
||||
|
||||
public void VisitPersonAcc(Person person)
|
||||
{
|
||||
Console.WriteLine($"[HTML] {person}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// XML сериализатор
|
||||
/// </summary>
|
||||
class XmlVisitor : IVisitor
|
||||
{
|
||||
public void VisitCompanyAcc(Company company)
|
||||
{
|
||||
Console.WriteLine($"[XML] {company}");
|
||||
}
|
||||
|
||||
public void VisitPersonAcc(Person person)
|
||||
{
|
||||
Console.WriteLine($"[XML] {person}");
|
||||
}
|
||||
}
|
10
Patterns/Visitor/Visitor.csproj
Normal file
10
Patterns/Visitor/Visitor.csproj
Normal file
@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
156
README.md
Normal file
156
README.md
Normal file
@ -0,0 +1,156 @@
|
||||
<p align="center">
|
||||
<!-- <p align="center">
|
||||
<img src="/" width="100%" alt="Banner">
|
||||
<a></a> -->
|
||||
<!-- </p> -->
|
||||
<p align="center">
|
||||
<a href="https://git.io/typing-svg"><img src="https://readme-typing-svg.demolab.com?font=Fira+Code&pause=1000¢er=true&vCenter=true&width=435&lines=%D0%9F%D0%BE%D0%B2%D1%82%D0%BE%D1%80%D0%B5%D0%BD%D0%B8%D0%B5+-+%D0%BC%D0%B0%D1%82%D1%8C+%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D1%8F" alt="Typing SVG" /></a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://sites.google.com/view/dvurechensky" target="_blank"><img alt="Static Badge" src="https://img.shields.io/badge/Dvurechensky-N-blue"></a>
|
||||
<img src="https://img.shields.io/badge/Csharp-VS2022-blue?logo=csharp&logoColor=FFFF00">
|
||||
</p>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<h1 align="center">🔱 Шаблоны проектирования 🔱<h1>
|
||||
</p>
|
||||
|
||||
## Описание содержимого 💼
|
||||
|
||||
- ⌛ Определения: **class, abstract class, struct, interface, record**
|
||||
- ⌛ Разбор: **принципы SOLID, наследование, типы Dictionary, Unit тестирование**
|
||||
- ⌛ Бонус: **решение [LetCode](https://leetcode.com/) задач**
|
||||
- 😈 Такие паттерны как:
|
||||
>
|
||||
<h1 align="center">🌐 Behavioral - Поведенческие [11]🌐<h1><br>
|
||||
<table align="center">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Паттерн</th>
|
||||
<th>Краткое определение</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="width: 500px; padding: 18px;">💢 <a href="/Patterns/ChainOfResponsibility/Program.cs">ChainOfResponsibility</a> - Цепочка обязанностей</td>
|
||||
<td style="width: 500px; padding: 18px;">🔎 Избегает связывание отправителя запроса с его получателем, давая возможность обработать запрос более чем одному объекту.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width: 500px; padding: 18px;">💢 <a href="/Patterns/Command/Program.cs">Command</a> - Команда</td>
|
||||
<td style="width: 500px; padding: 18px;">🔎 Инкапсулирует запрос в виде объекта позволяя передавать их клиентам в качестве параметров, ставить в очередь, логировать, а также поддерживать отмену операций.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width: 500px; padding: 18px;">💢 <a href="/Patterns/Interpreter/Program.cs">Interpreter</a> - Интерпретатор</td>
|
||||
<td style="width: 500px; padding: 18px;">🔎 Получая формальный язык, определяет представление его грамматики и интерпретатор, использующий это представление для обработки выражений языка.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width: 500px; padding: 18px;">💢 <a href="/Patterns/Iterator/Program.cs">Iterator</a> - Итератор</td>
|
||||
<td style="width: 500px; padding: 18px;">🔎 Предоставляет способ последовательного доступа к множеству, независимо от его внутреннего устройства.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width: 500px; padding: 18px;">💢 <a href="/Patterns/Mediator/Program.cs">Mediator</a> - Посредник</td>
|
||||
<td style="width: 500px; padding: 18px;">🔎 Определяет объект инкапсулирующий способ взаимодействия объектов. Обеспечивает слабую связь, избавляя их от необходимости ссылаться друг на друга и даёт возможность независимо изменять их взаимодействие.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width: 500px; padding: 18px;">💢 <a href="/Patterns/Memento/Program.cs">Memento</a> - Хранитель</td>
|
||||
<td style="width: 500px; padding: 18px;">🔎 Не нарушая инкапсуляцию, определяет и сохраняет внутреннее состояние объекта и позволяет позже восстановить объект в этом состоянии.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width: 500px; padding: 18px;">💢 <a href="/Patterns/Observer/Program.cs">Observer</a> - Наблюдатель</td>
|
||||
<td style="width: 500px; padding: 18px;">🔎 Определяет зависимость один ко многим между объектами так, что когда один меняет своё состояние, все зависимые объекты оповещаются и обновляются автоматически.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width: 500px; padding: 18px;">💢 <a href="/Patterns/State/Program.cs">State</a> - Состояние</td>
|
||||
<td style="width: 500px; padding: 18px;">🔎 Позволяет объекту изменять своё поведение в зависимости от внутреннего состояния.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width: 500px; padding: 18px;">💢 <a href="/Patterns/Strategy/Program.cs">Strategy</a> - Стратегия</td>
|
||||
<td style="width: 500px; padding: 18px;">🔎 Определяет группу алгоритмов, инкапсулирует их и делает взаимозаменяемыми. Позволяет изменять алгоритм независимо от клиентов, его использующих.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width: 500px; padding: 18px;">💢 <a href="/Patterns/TemplateMethod/Program.cs">TemplateMethod</a> - Шаблонный метод</td>
|
||||
<td style="width: 500px; padding: 18px;">🔎 Определяет алгоритм, некоторые этапы которого делегируются подклассам. Позволяет подклассам переопределить эти этапы, не меняя структуру алгоритма.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width: 500px; padding: 18px;">💢 <a href="/Patterns/Visitor/Program.cs">Visitor</a> - Посетитель</td>
|
||||
<td style="width: 500px; padding: 18px;">🔎 Представляет собой операцию, которая будет выполнена над объектами группы классов. Даёт возможность определить новую операцию без изменения кода классов, над которыми эта операция производитcя.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<br>
|
||||
<h1 align="center">💡 Creational - Порождающие [6]💡<h1><br>
|
||||
<table align="center">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Паттерн</th>
|
||||
<th>Краткое определение</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="width: 500px; padding: 18px;">💢 <a href="/Patterns/AbstractFactory/Program.cs">AbstractFactory</a> - Абстрактная фабрика</td>
|
||||
<td style="width: 500px; padding: 18px;">🔎 Предоставляет интерфейс для создания групп связанных или зависимых объектов, не указывая их конкретный класс.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width: 500px; padding: 18px;">💢 <a href="/Patterns/Builder/Program.cs">Builder</a> - Строитель</td>
|
||||
<td style="width: 500px; padding: 18px;">🔎 Разделяет создание сложного объекта и его инициализацию так, что одинаковый процесс построения может может создавать объекты с разным состоянием.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width: 500px; padding: 18px;">💢 <a href="/Patterns/FactoryMethod/Program.cs">FactoryMethod</a> - Фабричный метод</td>
|
||||
<td style="width: 500px; padding: 18px;">🔎 Определяет интерфейс для создания объекта, но позволяет подклассам решать, какой класс создавать. Позволяет делегировать создание класса объектам класса.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width: 500px; padding: 18px;">💢 <a href="/Patterns/FluentBuilder/Program.cs">FluentBuilder</a> - Гибкий(плавный, текучий) строитель</td>
|
||||
<td style="width: 500px; padding: 18px;">🔎 Позволяет упростить процесс создания сложных объектов с помощью методов-цепочек, которые наделяют объект каким-то определенным качеством.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width: 500px; padding: 18px;">💢 <a href="/Patterns/Prototype/Program.cs">Prototype</a> - Прототип</td>
|
||||
<td style="width: 500px; padding: 18px;">🔎 Определяет несколько видов объектов, чтобы при создании использовать объект-прототип и создаёт новые объекты, копируя прототип (техника клонирования объектов).</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width: 500px; padding: 18px;">💢 <a href="/Patterns/Singleton/Program.cs">Singleton</a> - Одиночка</td>
|
||||
<td style="width: 500px; padding: 18px;">🔎 Гарантирует что класс имеет только один экземпляр и представляет глобальную точку доступа к нему.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<br>
|
||||
<h1 align="center">🏩 Structural - Структурные [7]🏩<h1><br>
|
||||
<table align="center">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Паттерн</th>
|
||||
<th>Краткое определение</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="width: 500px; padding: 18px;">💢 <a href="/Patterns/Adapter/Program.cs">Adapter</a> - Адаптер</td>
|
||||
<td style="width: 500px; padding: 18px;">🔎 Конвенртирует интерфейс класса в другой интерфейс, ожидаемый клиентом. Позволяет классам с разными интерфейсами работать вместе.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width: 500px; padding: 18px;">💢 <a href="/Patterns/Bridge/Program.cs">Bridge</a> - Мост</td>
|
||||
<td style="width: 500px; padding: 18px;">🔎 Разделяет абстракцию и реализацию так, чтобы они могли изменяться независимо друг от друга.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width: 500px; padding: 18px;">💢 <a href="/Patterns/Composite/Program.cs">Composite</a> - Компоновщик</td>
|
||||
<td style="width: 500px; padding: 18px;">🔎 Компонует объекты в древовидную структуру по принципу "часть-целое", представляя их в виде иерархии. Позволяет клиенту одинаково обращаться как к отдельному, так и к целому поддереву.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width: 500px; padding: 18px;">💢 <a href="/Patterns/Decorator/Program.cs">Decorator</a> - Декоратор</td>
|
||||
<td style="width: 500px; padding: 18px;">🔎 Динамически предоставляет объекту дополнительные возможности. Представляет собой гибкую альтернативу наследованию для расширения функциональности.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width: 500px; padding: 18px;">💢 <a href="/Patterns/Facade/Program.cs">Facade</a> - Фасад</td>
|
||||
<td style="width: 500px; padding: 18px;">🔎 Предоставляет единый интерфейс к группе интерфейсов подсистемы. Определяет высокоуровневый интерфейс, делая систему проще для использования.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width: 500px; padding: 18px;">💢 <a href="/Patterns/Flyweight/Program.cs">Flyweight</a> - Приспособленец</td>
|
||||
<td style="width: 500px; padding: 18px;">🔎 Благодаря совместному использованию, поддерживает эффективную работу с большим количеством объектов. (для оптимизации работы с памятью)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width: 500px; padding: 18px;">💢 <a href="/Patterns/Proxy/Program.cs">Proxy</a> - Заместитель</td>
|
||||
<td style="width: 500px; padding: 18px;">🔎 Предоставляет объект-заместитель другого объекта для контроля доступа к нему.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
Loading…
Reference in New Issue
Block a user