1.0
Main
This commit is contained in:
commit
a4cd4b4ced
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
226
.gitignore
vendored
Normal file
226
.gitignore
vendored
Normal file
@ -0,0 +1,226 @@
|
||||
# The following command works for downloading when using Git for Windows:
|
||||
# curl -LOf http://gist.githubusercontent.com/kmorcinek/2710267/raw/.gitignore
|
||||
#
|
||||
# Download this file using PowerShell v3 under Windows with the following comand:
|
||||
# Invoke-WebRequest https://gist.githubusercontent.com/kmorcinek/2710267/raw/ -OutFile .gitignore
|
||||
#
|
||||
# or wget:
|
||||
# wget --no-check-certificate http://gist.githubusercontent.com/kmorcinek/2710267/raw/.gitignore
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.sln.docstates
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Rr]elease/
|
||||
x64/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
# build folder is nowadays used for build scripts and should not be ignored
|
||||
#build/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/packages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/packages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/packages/repositories.config
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
*_i.c
|
||||
*_p.c
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.scc
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# NCrunch
|
||||
*.ncrunch*
|
||||
.*crunch*.local.xml
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.Publish.xml
|
||||
|
||||
# Windows Azure Build Output
|
||||
csx
|
||||
*.build.csdef
|
||||
|
||||
# Windows Store app package directory
|
||||
AppPackages/
|
||||
|
||||
# Others
|
||||
*.Cache
|
||||
ClientBin/
|
||||
[Ss]tyle[Cc]op.*
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.[Pp]ublish.xml
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
modulesbin/
|
||||
tempbin/
|
||||
|
||||
# EPiServer Site file (VPP)
|
||||
AppData/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file to a newer
|
||||
# Visual Studio version. Backup files are not needed, because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
|
||||
# vim
|
||||
*.txt~
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# Temp files when opening LibreOffice on ubuntu
|
||||
.~lock.*
|
||||
|
||||
# svn
|
||||
.svn
|
||||
|
||||
# CVS - Source Control
|
||||
**/CVS/
|
||||
|
||||
# Remainings from resolving conflicts in Source Control
|
||||
*.orig
|
||||
|
||||
# SQL Server files
|
||||
**/App_Data/*.mdf
|
||||
**/App_Data/*.ldf
|
||||
**/App_Data/*.sdf
|
||||
|
||||
|
||||
#LightSwitch generated files
|
||||
GeneratedArtifacts/
|
||||
_Pvt_Extensions/
|
||||
ModelManifest.xml
|
||||
|
||||
# =========================
|
||||
# Windows detritus
|
||||
# =========================
|
||||
|
||||
# Windows image file caches
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
|
||||
# Folder config file
|
||||
Desktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# OS generated files #
|
||||
Icon?
|
||||
|
||||
# Mac desktop service store files
|
||||
.DS_Store
|
||||
|
||||
# SASS Compiler cache
|
||||
.sass-cache
|
||||
|
||||
# Visual Studio 2014 CTP
|
||||
**/*.sln.ide
|
||||
|
||||
# Visual Studio temp something
|
||||
.vs/
|
||||
|
||||
# dotnet stuff
|
||||
project.lock.json
|
||||
|
||||
# VS 2015+
|
||||
*.vc.vc.opendb
|
||||
*.vc.db
|
||||
|
||||
# Rider
|
||||
.idea/
|
||||
|
||||
# Visual Studio Code
|
||||
.vscode/
|
||||
|
||||
# Output folder used by Webpack or other FE stuff
|
||||
**/node_modules/*
|
||||
**/wwwroot/*
|
||||
|
||||
# SpecFlow specific
|
||||
*.feature.cs
|
||||
*.feature.xlsx.*
|
||||
*.Specs_*.html
|
||||
|
||||
# UWP Projects
|
||||
AppPackages/
|
||||
|
||||
#####
|
||||
# End of core ignore list, below put you custom 'per project' settings (patterns or path)
|
||||
#####
|
121
LICENCE
Normal file
121
LICENCE
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.
|
@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<RootNamespace>Pattern_1_Адаптер_Adapter_</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
59
Patterns/Pattern_1-Адаптер(Adapter)/Program.cs
Normal file
59
Patterns/Pattern_1-Адаптер(Adapter)/Program.cs
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* СТРУКТУРНЫЕ ПАТТЕРНЫ
|
||||
*
|
||||
* Глава_12: Адаптер (Adapter)
|
||||
*
|
||||
* - преобразует интерфейс одного класса в интерфейс другого, который
|
||||
* ожидают клиенты. Адаптер делает возможной совместную работу
|
||||
* классов с несовместимыми интерфейсами
|
||||
*/
|
||||
|
||||
class Motorcycle { }
|
||||
|
||||
/// <summary>
|
||||
/// Что адаптируем
|
||||
/// </summary>
|
||||
class Voskhod : Motorcycle
|
||||
{
|
||||
public void Sound() => Console.WriteLine("DRDRDR");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Цель на которую нужно ориентироваться при адаптации
|
||||
/// </summary>
|
||||
interface Isport
|
||||
{
|
||||
void MakeNoise();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Пример готового объекта aдаптированного под цель
|
||||
/// </summary>
|
||||
class Honda : Motorcycle, Isport
|
||||
{
|
||||
public void MakeNoise() => Console.WriteLine("hooondaaa");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Адаптер
|
||||
/// Адаптирует простой класс под цель
|
||||
/// </summary>
|
||||
class TuningVoskhod : Isport
|
||||
{
|
||||
Voskhod moto;
|
||||
public TuningVoskhod(Voskhod moto) => this.moto = moto;
|
||||
public void MakeNoise()
|
||||
{
|
||||
Console.WriteLine("trsh");
|
||||
moto.Sound();
|
||||
}
|
||||
}
|
||||
|
||||
class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var tun = new TuningVoskhod(new Voskhod());
|
||||
tun.MakeNoise();
|
||||
}
|
||||
}
|
28
Patterns/Pattern_1-Синглтон(Singleton)/MySnippet.snippet
Normal file
28
Patterns/Pattern_1-Синглтон(Singleton)/MySnippet.snippet
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<CodeSnippet Format="1.0.0" xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
|
||||
<Header>
|
||||
<Title>Мой сниппет</Title>
|
||||
<Author>Николай</Author>
|
||||
<Shortcut>CR</Shortcut>
|
||||
<Description>генерация void метода</Description>
|
||||
<SnippetTypes>
|
||||
<SnippetType>Expansion</SnippetType>
|
||||
</SnippetTypes>
|
||||
</Header>
|
||||
<Snippet>
|
||||
<Declarations>
|
||||
<Literal>
|
||||
<ID>имя</ID>
|
||||
<Default>sb</Default>
|
||||
</Literal>
|
||||
</Declarations>
|
||||
<Code Language="CSharp">
|
||||
<![CDATA[Console.ReadLine();]]>
|
||||
</Code>
|
||||
<Imports>
|
||||
<Import>
|
||||
<Namespace>System</Namespace>
|
||||
</Import>
|
||||
</Imports>
|
||||
</Snippet>
|
||||
</CodeSnippet>
|
@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<RootNamespace>Pattern_1_Синглтон_Singleton_</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
33
Patterns/Pattern_1-Синглтон(Singleton)/Program.cs
Normal file
33
Patterns/Pattern_1-Синглтон(Singleton)/Program.cs
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* ПОРОЖДАЮЩИЕ ПАТТЕРНЫ
|
||||
*
|
||||
* Глава_8: Сиглтон, Одиночка (Singleton)
|
||||
*
|
||||
* - гантирует, что у класса есть только один экземпляр,
|
||||
* и предоставляет глобальную точку доступа к нему
|
||||
*/
|
||||
class Singleton
|
||||
{
|
||||
private Singleton()
|
||||
{
|
||||
Data = 28;
|
||||
MoreData = 90;
|
||||
}
|
||||
|
||||
public int Data { get; set; }
|
||||
public int MoreData { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Отложенный синглтон (ленивый одиночка)
|
||||
/// </summary>
|
||||
static Lazy<Singleton> uniqueInstance = new Lazy<Singleton>(() => new Singleton());
|
||||
public static Singleton Instance => uniqueInstance.Value;
|
||||
}
|
||||
|
||||
class Program
|
||||
{
|
||||
public static void Main()
|
||||
{
|
||||
Console.WriteLine(Singleton.Instance.Data);
|
||||
}
|
||||
}
|
43
Patterns/Pattern_1-Синглтон(Singleton)/voidSnippet.snippet
Normal file
43
Patterns/Pattern_1-Синглтон(Singleton)/voidSnippet.snippet
Normal file
@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<CodeSnippet Format="1.0.0" xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
|
||||
<Header>
|
||||
<Title>Мой сниппет</Title>
|
||||
<Author>Николай</Author>
|
||||
<Shortcut>void</Shortcut>
|
||||
<Description>генерация void метода</Description>
|
||||
<SnippetTypes>
|
||||
<SnippetType>Expansion</SnippetType>
|
||||
</SnippetTypes>
|
||||
</Header>
|
||||
<Snippet>
|
||||
<Declarations>
|
||||
<Literal>
|
||||
<ID>public</ID>
|
||||
<ToolTip>Модификатор доступности</ToolTip>
|
||||
<Default>public</Default>
|
||||
</Literal>
|
||||
<Literal>
|
||||
<ID>void</ID>
|
||||
<ToolTip>Тип возвращаемого значения</ToolTip>
|
||||
<Default>void</Default>
|
||||
</Literal>
|
||||
<Literal>
|
||||
<ID>name</ID>
|
||||
<ToolTip>Имя метода</ToolTip>
|
||||
<Default>name</Default>
|
||||
</Literal>
|
||||
<Literal>
|
||||
<ID>value</ID>
|
||||
<ToolTip>Возвращаемое значение</ToolTip>
|
||||
<Default>value</Default>
|
||||
</Literal>
|
||||
</Declarations>
|
||||
<Code Language="CSharp">
|
||||
<![CDATA[
|
||||
$public$ $void$ $name$()
|
||||
{
|
||||
return $value$;
|
||||
}]]>
|
||||
</Code>
|
||||
</Snippet>
|
||||
</CodeSnippet>
|
7
Patterns/Pattern_1-Стратегия/ILogReader.cs
Normal file
7
Patterns/Pattern_1-Стратегия/ILogReader.cs
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
namespace Behavioral;
|
||||
|
||||
public interface ILogReader
|
||||
{
|
||||
List<LogEntry> Read();
|
||||
}
|
15
Patterns/Pattern_1-Стратегия/LogEntry.cs
Normal file
15
Patterns/Pattern_1-Стратегия/LogEntry.cs
Normal file
@ -0,0 +1,15 @@
|
||||
namespace Behavioral;
|
||||
|
||||
public enum LogType
|
||||
{
|
||||
Debug,
|
||||
Warning,
|
||||
Fatal
|
||||
}
|
||||
|
||||
public struct LogEntry
|
||||
{
|
||||
public DateTime DateTime { get; set; }
|
||||
public LogType Severity { get; set; }
|
||||
public string Message { get; set; }
|
||||
}
|
17
Patterns/Pattern_1-Стратегия/LogFileReader.cs
Normal file
17
Patterns/Pattern_1-Стратегия/LogFileReader.cs
Normal file
@ -0,0 +1,17 @@
|
||||
namespace Behavioral;
|
||||
|
||||
public class LogFileReader : ILogReader
|
||||
{
|
||||
public List<LogEntry> Read()
|
||||
{
|
||||
return new List<LogEntry>()
|
||||
{
|
||||
new LogEntry()
|
||||
{
|
||||
DateTime = DateTime.Now,
|
||||
Message = GetType().Name,
|
||||
Severity = LogType.Debug
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
21
Patterns/Pattern_1-Стратегия/LogProcessor.cs
Normal file
21
Patterns/Pattern_1-Стратегия/LogProcessor.cs
Normal file
@ -0,0 +1,21 @@
|
||||
namespace Behavioral;
|
||||
|
||||
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.Severity);
|
||||
Console.WriteLine(logEntry.Message);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<RootNamespace>Pattern_1-Стратегия</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
157
Patterns/Pattern_1-Стратегия/Program.cs
Normal file
157
Patterns/Pattern_1-Стратегия/Program.cs
Normal file
@ -0,0 +1,157 @@
|
||||
namespace Behavioral;
|
||||
|
||||
/*
|
||||
* На чем строилось:
|
||||
* СЕРГЕЙ ТЕПЛЯКОВ - Паттерны проектирования на платформе .Net
|
||||
* ШЕВЧУК, АХРИМЕНКО, КАСЬЯНОВ - Приемы объектно-ориентированного проектирования
|
||||
*
|
||||
* ПАТТЕРНЫ ПОВЕДЕНИЯ
|
||||
* Паттерн_1: Стратегия
|
||||
*
|
||||
* ! является более контекстно зависимой операцией
|
||||
*
|
||||
* Причины применения:
|
||||
* 1.необходимость инкапсуляции поведения или алгоритма
|
||||
* 2.необходимость замены поведения или алгоритма во время исполнения
|
||||
*
|
||||
* Другими словами, стратегия обеспечивает точку расширения системы
|
||||
* в определенной плоскости: класс-контекст (LogProcessor) принимает экземпляр стратегии (LogFileReader)
|
||||
* и не знает, какой вариант стратегии он собирается использовать.
|
||||
*
|
||||
* Особенность:
|
||||
* Передача интерфейса ILogReader классу LogProcessor увеличивает гибкость,
|
||||
* но в то же время повышает сложность.
|
||||
* Теперь клиентам класса LogProcessor нужно решить, какую реализацию использовать,
|
||||
* или переложить эту ответственность на вызывающий код.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ВМЕСТО
|
||||
* классической стратегии на основе наследования
|
||||
* можно использовать стратегию на основе делегатов
|
||||
*
|
||||
* ПРИМЕР: Стратегия сортировки
|
||||
*/
|
||||
|
||||
/*
|
||||
* ВАЖНО: Гибкость не бывает бесплатной, поэтому выделять стратегии стоит тогда,
|
||||
* когда действительно нужна замена поведения во время исполнения.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Program
|
||||
{
|
||||
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)); //используем делегат
|
||||
}
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
var logFileReader = new LogFileReader();
|
||||
|
||||
/*
|
||||
создали делегат который принимает в себя метод,
|
||||
в результате выполнения которого возвращается List<LogEntry>
|
||||
*/
|
||||
Func<List<LogEntry>> _import = () => logFileReader.Read();
|
||||
|
||||
new LogProcessor(_import).ProcessLogs();
|
||||
|
||||
var 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); //он помещает сюда фабрику - ту что умеет создавать
|
||||
}
|
||||
}
|
17
Patterns/Pattern_1-Стратегия/WindowsEventLogReader.cs
Normal file
17
Patterns/Pattern_1-Стратегия/WindowsEventLogReader.cs
Normal file
@ -0,0 +1,17 @@
|
||||
namespace Behavioral;
|
||||
|
||||
public class WindowsEventLogReader : ILogReader
|
||||
{
|
||||
public List<LogEntry> Read()
|
||||
{
|
||||
return new List<LogEntry>()
|
||||
{
|
||||
new LogEntry()
|
||||
{
|
||||
DateTime = DateTime.Now,
|
||||
Message = GetType().Name,
|
||||
Severity = LogType.Debug
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
15
Patterns/Pattern_2-Абстрактная фабрика(Abstract Factory)/Pattern_2-Абстрактная фабрика(Abstract Factory).csproj
Normal file
15
Patterns/Pattern_2-Абстрактная фабрика(Abstract Factory)/Pattern_2-Абстрактная фабрика(Abstract Factory).csproj
Normal file
@ -0,0 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<RootNamespace>Pattern_2_Абстрактная_фабрика_Abstract_Factory_</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BenchmarkDotNet" Version="0.13.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
@ -0,0 +1,129 @@
|
||||
/*
|
||||
* ПОРОЖДАЮЩИЕ ПАТТЕРНЫ
|
||||
*
|
||||
* Глава_9: Абстрактная фабрика (Abstract Factory)
|
||||
*
|
||||
* - скрыть сложную логику инициализации
|
||||
* - упростить поддержку функционала и его дополнение
|
||||
* (крайне рекдо используется)
|
||||
*/
|
||||
|
||||
using BenchmarkDotNet.Attributes;
|
||||
|
||||
/// <summary>
|
||||
/// Фабрика
|
||||
/// </summary>
|
||||
interface ICar
|
||||
{
|
||||
void Drive();
|
||||
}
|
||||
|
||||
class RacingCar : ICar
|
||||
{
|
||||
public void Drive() => Console.WriteLine("Ты на гоночном болиде едешь!");
|
||||
}
|
||||
|
||||
class ConcreteCar : ICar
|
||||
{
|
||||
public void Drive() => Console.WriteLine("Ты на бетономешалке едешь!");
|
||||
}
|
||||
|
||||
class UnknownCar : ICar
|
||||
{
|
||||
public void Drive() => Console.WriteLine("Ты на неизвестном едешь!");
|
||||
}
|
||||
|
||||
enum TypeCar
|
||||
{
|
||||
Truck,
|
||||
Racing
|
||||
}
|
||||
|
||||
class CarFactory
|
||||
{
|
||||
public static ICar ProductCar(TypeCar type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case TypeCar.Truck: return new RacingCar();
|
||||
case TypeCar.Racing: return new ConcreteCar();
|
||||
default: return new UnknownCar();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[MemoryDiagnoser]
|
||||
[RankColumn]
|
||||
public class Benchmark
|
||||
{
|
||||
[Benchmark]
|
||||
public void ArrayListBench()
|
||||
{
|
||||
CarFactory.ProductCar(TypeCar.Truck).Drive();
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void ListBench()
|
||||
{
|
||||
var test = CarFactory.ProductCar(TypeCar.Truck);
|
||||
test.Drive();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Абстрактная фабрика
|
||||
/// </summary>
|
||||
interface ICarFactory
|
||||
{
|
||||
ICar ProductCar(TypeCar type);
|
||||
}
|
||||
|
||||
class CarFactory_abstr : ICarFactory
|
||||
{
|
||||
public ICar ProductCar(TypeCar type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case TypeCar.Truck: return new ConcreteCar();
|
||||
case TypeCar.Racing: return new RacingCar();
|
||||
default: return new UnknownCar();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TuningCarFactory_abstr : ICarFactory
|
||||
{
|
||||
public ICar ProductCar(TypeCar type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case TypeCar.Truck: return new ConcreteCar();
|
||||
case TypeCar.Racing: return new RacingCar();
|
||||
default: return new UnknownCar();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AbstractFactory
|
||||
{
|
||||
public static ICarFactory GetFactory(bool tuning)
|
||||
=> tuning ? new TuningCarFactory_abstr() : new CarFactory_abstr();
|
||||
}
|
||||
|
||||
|
||||
class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
//BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);
|
||||
CarFactory.ProductCar(TypeCar.Truck).Drive();
|
||||
CarFactory.ProductCar(TypeCar.Racing).Drive();
|
||||
CarFactory.ProductCar((TypeCar)4).Drive();
|
||||
|
||||
AbstractFactory.GetFactory(true).ProductCar(TypeCar.Truck).Drive();
|
||||
|
||||
var factory = AbstractFactory.GetFactory(false);
|
||||
ICar car = factory.ProductCar(TypeCar.Racing);
|
||||
car.Drive();
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<RootNamespace>Pattern_2_Фасад_Facade_</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
88
Patterns/Pattern_2-Фасад(Facade)/Program.cs
Normal file
88
Patterns/Pattern_2-Фасад(Facade)/Program.cs
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* СТРУКТУРНЫЕ ПАТТЕРНЫ
|
||||
*
|
||||
* Глава_13: Фасад (Facade)
|
||||
*
|
||||
* - предоставляет унифицированный интерфейс вместо набора
|
||||
* интерфейсов некоторой подсистемы. Фасад определяет
|
||||
* интерфейс более высокого уровня, который упрощает использование подсистемы
|
||||
*/
|
||||
|
||||
class NICPc
|
||||
{
|
||||
public void C0()
|
||||
=> Console.WriteLine("осуществляется программирование регистров микросхемы Host Bridge");
|
||||
public void C1()
|
||||
=> Console.WriteLine("с помощью последовательных циклов запись/чтение определяется тип памяти");
|
||||
public void C2()
|
||||
=> Console.WriteLine("проверяются первые 256 Кб памяти, для использования как транзитный буфер");
|
||||
public void C6()
|
||||
=> Console.WriteLine("по спец. алгоритму определяется наличие, тип и параметры External Cache.");
|
||||
public void CF()
|
||||
=> Console.WriteLine("определяется тип процессора, а результат помещается в CMOS");
|
||||
public void Step05()
|
||||
=> Console.WriteLine("осуществляется проверка и инициализация контроллера клавиатуры");
|
||||
public void Step07()
|
||||
=> Console.WriteLine("проверяется функционирование CMOS и напряжение питания батареи");
|
||||
public void StepBE()
|
||||
=> Console.WriteLine("программируются конфигурационные регистры Host Bridge и PIIX значениями, взятыми из BIOS");
|
||||
public void Step0A()
|
||||
=> Console.WriteLine("генерируется таблица векторов прерываний, а также первичная настройка подсистемы управления");
|
||||
public void Step0B()
|
||||
=> Console.WriteLine("проверяется контрольная сумма блока ячеек BIOS");
|
||||
public void Step0C()
|
||||
=> Console.WriteLine("инициализируется блок переменных BIOS");
|
||||
public void Step0D0E()
|
||||
=> Console.WriteLine("определяется наличие видеоадаптера путём проверки наличия сигнатуры 55AA");
|
||||
public void Step3031()
|
||||
=> Console.WriteLine("определяется объём Base Memory и External Memory, вступительный экран");
|
||||
public void Step3D()
|
||||
=> Console.WriteLine("инициализируется PS/2 mouse.");
|
||||
public void Step41()
|
||||
=> Console.WriteLine("производится инициализация подсистемы гибких дисков.");
|
||||
public void Step45()
|
||||
=> Console.WriteLine("инициализируется сопроцессор FPU");
|
||||
public void StepF()
|
||||
=> Console.WriteLine("Приветствие");
|
||||
}
|
||||
|
||||
class Facade
|
||||
{
|
||||
NICPc pc;
|
||||
|
||||
public Facade(NICPc pc)
|
||||
{
|
||||
this.pc = pc;
|
||||
}
|
||||
|
||||
public void Power()
|
||||
{
|
||||
pc.C0();
|
||||
pc.C1();
|
||||
pc.C2();
|
||||
pc.C6();
|
||||
pc.CF();
|
||||
pc.Step05();
|
||||
pc.Step07();
|
||||
pc.StepBE();
|
||||
pc.Step0A();
|
||||
pc.Step0B();
|
||||
pc.Step0C();
|
||||
pc.Step0D0E();
|
||||
pc.Step3031();
|
||||
pc.Step3D();
|
||||
pc.Step41();
|
||||
pc.Step45();
|
||||
pc.StepF();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
new Facade(new NICPc()).Power();
|
||||
}
|
||||
}
|
6
Patterns/Pattern_2-Шаблонный метод/ExceptionLogEntry.cs
Normal file
6
Patterns/Pattern_2-Шаблонный метод/ExceptionLogEntry.cs
Normal file
@ -0,0 +1,6 @@
|
||||
namespace Creational;
|
||||
|
||||
public struct ExceptionLogEntry
|
||||
{
|
||||
public string Message { get; set; }
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<RootNamespace>Pattern_2_Шаблонный_метод</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.ServiceModel.Primitives" Version="4.9.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Pattern_1-Стратегия\Pattern_1-Стратегия(Strategy).csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
227
Patterns/Pattern_2-Шаблонный метод/Program.cs
Normal file
227
Patterns/Pattern_2-Шаблонный метод/Program.cs
Normal file
@ -0,0 +1,227 @@
|
||||
/*
|
||||
* ПАТТЕРНЫ ПОВЕДЕНИЯ
|
||||
*
|
||||
* Глава_2 и 10: Фабричный метод(виртуальный конструктор) и Шаблонный метод (Паттерн поведения)
|
||||
*
|
||||
* — это каркас, в который наследники могут
|
||||
* подставить реализации недостающих элементов.
|
||||
*
|
||||
* - позволяет более четко определить «контракт» между базовым классом и потомками
|
||||
*/
|
||||
|
||||
using Behavioral;
|
||||
using Creational;
|
||||
using System.ServiceModel;
|
||||
using System.Text;
|
||||
|
||||
/*
|
||||
* Теперь все реализации читателей логов будут вынуждены следовать согласованному протоколу
|
||||
*/
|
||||
public abstract class LogReader
|
||||
{
|
||||
private int _currentPosition;
|
||||
|
||||
/// <summary>
|
||||
/// Определяет алгоритм импорта
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<LogEntry> ReadLogEntry()
|
||||
{
|
||||
return ReadEntries(ref _currentPosition).Select(ParseLogEntry);
|
||||
}
|
||||
|
||||
protected abstract IEnumerable<string> ReadEntries(ref int position);
|
||||
|
||||
protected abstract LogEntry ParseLogEntry(string stringEntry);
|
||||
}
|
||||
|
||||
/*
|
||||
* 2.1: Локальный шаблонный метод на основе делегатов
|
||||
*
|
||||
* ! является более контекстно зависимой операцией
|
||||
*
|
||||
* Использование наследования является слишком тяжеловесным решением,
|
||||
* поэтому в таких случаях применяется подход, при котором переменный шаг алгоритма задается делегатом
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Поведение сервиса сохранения записей
|
||||
/// </summary>
|
||||
interface ILogSaver
|
||||
{
|
||||
void UploadLogEntries(IEnumerable<LogEntry>logEntries);
|
||||
void UploadExceptions(IEnumerable<ExceptionLogEntry> exceptions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Прокси - класс инкапсулирует особенности работы
|
||||
/// с WCF - инфраструктурой
|
||||
/// </summary>
|
||||
class LogSaverProxy : ILogSaver
|
||||
{
|
||||
/// <summary>
|
||||
/// Подключение к службе
|
||||
/// </summary>
|
||||
class LogSaverClient : ClientBase<ILogSaver>
|
||||
{
|
||||
public ILogSaver LogSaver
|
||||
{
|
||||
get { return Channel; }
|
||||
}
|
||||
}
|
||||
|
||||
public void UploadExceptions(IEnumerable<ExceptionLogEntry> exceptions)
|
||||
{
|
||||
UseProxyClient(c => c.UploadExceptions(exceptions));
|
||||
}
|
||||
|
||||
public void UploadLogEntries(IEnumerable<LogEntry> logEntries)
|
||||
{
|
||||
UseProxyClient(c => c.UploadLogEntries(logEntries));
|
||||
}
|
||||
|
||||
private void UseProxyClient(Action<ILogSaver> accessor)
|
||||
{
|
||||
var client = new LogSaverClient();
|
||||
try
|
||||
{
|
||||
accessor(client.LogSaver);
|
||||
client.Close();
|
||||
}
|
||||
catch (CommunicationException e)
|
||||
{
|
||||
client.Abort();
|
||||
Console.WriteLine(e.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Подход на основе делегатов может не только применяться для определения
|
||||
* локальных действий внутри класса, но и передаваться извне другому объекту
|
||||
* в аргументах конструктора.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 2.2: Шаблонный метод на основе методов расширения
|
||||
*/
|
||||
|
||||
public abstract class LogEntryBase
|
||||
{
|
||||
public DateTime EntryDateTime { get; internal set; }
|
||||
public LogType Severity { get; internal set; }
|
||||
public string? Message { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// ExceptionLogEntry - будет возвращать информацию об исключении
|
||||
/// </summary>
|
||||
public string? AdditionalInformation { get; internal set; }
|
||||
}
|
||||
|
||||
public static class LogEntryBaseEx
|
||||
{
|
||||
public static string GetText(this LogEntryBase logEntry)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendFormat("{0}", logEntry.EntryDateTime)
|
||||
.AppendFormat("{0}", logEntry.Severity)
|
||||
.AppendLine(logEntry.Message)
|
||||
.AppendLine(logEntry.AdditionalInformation);
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Абстракция для взаимодействия с фабриками
|
||||
/// </summary>
|
||||
public abstract class Creator
|
||||
{
|
||||
private Product? product;
|
||||
|
||||
public abstract Product ProductFactoryMethod(int x, int y);
|
||||
public abstract Product ProductFactoryMethod_2(int x, int y);
|
||||
|
||||
public void AnProductOperation(int x, int y)
|
||||
{
|
||||
product = ProductFactoryMethod(x, y);
|
||||
}
|
||||
|
||||
public void AnProductOperation_2(int x, int y)
|
||||
{
|
||||
product = ProductFactoryMethod_2(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Конкретная фабрика
|
||||
/// </summary>
|
||||
public class ConcreteCreator : Creator
|
||||
{
|
||||
public override Product ProductFactoryMethod(int x, int y)
|
||||
{
|
||||
return new ConcreteProduct(x, y);
|
||||
}
|
||||
|
||||
public override Product ProductFactoryMethod_2(int x, int y)
|
||||
{
|
||||
return new ConcreteProduct_2(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Абстракция для взаимодействия с продуктами
|
||||
/// </summary>
|
||||
public abstract class Product
|
||||
{
|
||||
public abstract void GetText();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Конкретный продукт
|
||||
/// </summary>
|
||||
public class ConcreteProduct : Product
|
||||
{
|
||||
public ConcreteProduct(int x, int y)
|
||||
{
|
||||
Console.WriteLine($"x {x} y {y}");
|
||||
}
|
||||
|
||||
public override void GetText()
|
||||
{
|
||||
Console.WriteLine("1");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class ConcreteProduct_2 : Product
|
||||
{
|
||||
public ConcreteProduct_2(int x, int y)
|
||||
{
|
||||
Console.WriteLine($"x2 {x} y2 {y}");
|
||||
}
|
||||
|
||||
public override void GetText()
|
||||
{
|
||||
Console.WriteLine("2");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
Product product1 = null;
|
||||
Product product2 = null;
|
||||
var creator = new ConcreteCreator(); //Инициализирую фабрику
|
||||
product1 = creator.ProductFactoryMethod(1, 2);
|
||||
product2 = creator.ProductFactoryMethod_2(1, 2);
|
||||
|
||||
Console.WriteLine($"{product1.GetType().Name} {product2.GetType().Name}");
|
||||
|
||||
product1.GetText();
|
||||
product2.GetText();
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<RootNamespace>Pattern_3_Декоратор_Decorator_</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
144
Patterns/Pattern_3-Декоратор(Decorator)/Program.cs
Normal file
144
Patterns/Pattern_3-Декоратор(Decorator)/Program.cs
Normal file
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* СТРУКТУРНЫЕ ПАТТЕРНЫ
|
||||
*
|
||||
* Глава_14: Декоратор (Decorator)
|
||||
*
|
||||
* - динамически добавляет объекту новые обязанности. Является гибкой
|
||||
* альтернативой порождению подклассов с целью расширения функциональности
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Пример №1
|
||||
/// </summary>
|
||||
public sealed class Car
|
||||
{
|
||||
public string Model { get; set; }
|
||||
public Car(string model, IEnumerable<string> options)
|
||||
{
|
||||
|
||||
}
|
||||
public List<string> Options { get; protected set; }
|
||||
public int GetPrice() { return 0; }
|
||||
public void Move() { }
|
||||
public void Stop() { }
|
||||
public override string ToString()
|
||||
{
|
||||
return base.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
class MyCar
|
||||
{
|
||||
protected Car baseCar;
|
||||
public MyCar(string model, IEnumerable<string> options)
|
||||
{
|
||||
baseCar = new Car(model, options);
|
||||
}
|
||||
public List<string> Options { get => baseCar.Options; }
|
||||
public int GetPrice() => baseCar.GetPrice() + 100;
|
||||
|
||||
public void Move() { baseCar.Move(); }
|
||||
public void Stop() { baseCar.Stop(); }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{baseCar?.ToString()} +++";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Пример №2 (Динамический декоратор)
|
||||
/// </summary>
|
||||
class Pizza
|
||||
{
|
||||
public virtual string MakePizza() => "Dough =>";
|
||||
}
|
||||
|
||||
class ChickenPizza : Pizza
|
||||
{
|
||||
Pizza pizza;
|
||||
public ChickenPizza(Pizza pizza)
|
||||
{
|
||||
this.pizza = pizza;
|
||||
}
|
||||
public override string MakePizza()
|
||||
=> pizza.MakePizza() + "ChickenPizza =>";
|
||||
}
|
||||
|
||||
class MeatPizza : Pizza
|
||||
{
|
||||
Pizza pizza;
|
||||
public MeatPizza(Pizza pizza)
|
||||
{
|
||||
this.pizza = pizza;
|
||||
}
|
||||
public override string MakePizza()
|
||||
=> pizza.MakePizza() + "MeatPizza =>";
|
||||
}
|
||||
|
||||
class CheesePizza : Pizza
|
||||
{
|
||||
Pizza pizza;
|
||||
public CheesePizza(Pizza pizza)
|
||||
{
|
||||
this.pizza = pizza;
|
||||
}
|
||||
public override string MakePizza()
|
||||
=> pizza.MakePizza() + "CheesePizza =>";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Пример №3 (статический декоратор - используем обобщение)
|
||||
/// </summary>
|
||||
public abstract class Pizza_Abstr
|
||||
{
|
||||
public virtual string MakePizza() => string.Empty;
|
||||
}
|
||||
|
||||
public class ChickPizza : Pizza_Abstr
|
||||
{
|
||||
public ChickPizza() { }
|
||||
public override string MakePizza() => "ChickPizza => ";
|
||||
}
|
||||
|
||||
public class Pepper<T> : Pizza_Abstr
|
||||
where T : Pizza_Abstr, new ()
|
||||
{
|
||||
T pizza;
|
||||
public Pepper() => pizza = new T();
|
||||
public override string MakePizza()
|
||||
{
|
||||
return $"{pizza.MakePizza()} Pepper =>";
|
||||
}
|
||||
}
|
||||
|
||||
public class Olives<T> : Pizza_Abstr
|
||||
where T : Pizza_Abstr, new()
|
||||
{
|
||||
T pizza;
|
||||
public Olives() => pizza = new T();
|
||||
public override string MakePizza()
|
||||
{
|
||||
return $"{pizza.MakePizza()} Olives =>";
|
||||
}
|
||||
}
|
||||
|
||||
class Program
|
||||
{
|
||||
public static void Main(string[] argv)
|
||||
{
|
||||
#region 2
|
||||
Pizza chickenPizza = new ChickenPizza(new Pizza());
|
||||
Console.WriteLine(chickenPizza.MakePizza()); // Dough -> ChickenPizza ->
|
||||
var chickenCheesePizza = new CheesePizza(new ChickenPizza(new Pizza()));
|
||||
Console.WriteLine(chickenCheesePizza.MakePizza());
|
||||
#endregion
|
||||
|
||||
#region 3
|
||||
Pizza_Abstr pizza_Abstr = new ChickPizza();
|
||||
Console.WriteLine(pizza_Abstr.MakePizza());
|
||||
Pizza_Abstr chickenOlivesPizza = new Olives<ChickPizza>();
|
||||
Console.WriteLine(chickenOlivesPizza.MakePizza());
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<RootNamespace>Pattern_3_Посредник_Mediator_</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
123
Patterns/Pattern_3-Посредник(Mediator)/Program.cs
Normal file
123
Patterns/Pattern_3-Посредник(Mediator)/Program.cs
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* ПАТТЕРНЫ ПОВЕДЕНИЯ
|
||||
*
|
||||
* Глава_3: Фабричный метод(виртуальный конструктор)
|
||||
*
|
||||
* - определяет объект, инкапсулирующий способ взаимодействия множества объектов.
|
||||
* - это клей, связывающий несколько независимых классов между собой.
|
||||
* Он избавляет классы от необходимости ссылаться друг на друга,
|
||||
* позволяя тем самым их независимо изменять и анализировать
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Посредники
|
||||
/// Предоставляет интерфейс для организации
|
||||
/// процесса по обмену информацией между объектами типа Colleague.
|
||||
/// </summary>
|
||||
abstract class Mediator
|
||||
{
|
||||
public abstract void Send(string message, Colleague colleague);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Конкретный посредник
|
||||
/// Реализует алгоритм взаимодействия между объектами-коллегами
|
||||
/// </summary>
|
||||
class ConcreteMediator : Mediator
|
||||
{
|
||||
public Fermer Fermer { get; set; }
|
||||
public Cannery Cannery { get; set; }
|
||||
public Shop Shop { get; set; }
|
||||
|
||||
public override void Send(string message, Colleague colleague)
|
||||
{
|
||||
if(colleague == Fermer)
|
||||
{
|
||||
Cannery.MakeKetchup(message);
|
||||
}
|
||||
if(colleague == Cannery)
|
||||
{
|
||||
Shop.SellKetshup(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Коллеги
|
||||
/// Предоставляет интерфейс для организации процесса
|
||||
/// взаимодействия объектов-коллег с объектом типа Mediator.
|
||||
/// </summary>
|
||||
abstract class Colleague
|
||||
{
|
||||
protected Mediator mediator;
|
||||
|
||||
public Colleague(Mediator mediator)
|
||||
{
|
||||
this.mediator = mediator; //передаем ссылку на абстрактный класс посредника
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Фермер
|
||||
/// Каждый объект-коллега знает только об объекте-медиаторе.
|
||||
/// Все объекты-коллеги обмениваются информацией
|
||||
/// только через посредника (медиатора).
|
||||
/// </summary>
|
||||
class Fermer : Colleague
|
||||
{
|
||||
public Fermer(Mediator mediator)
|
||||
: base(mediator) { }
|
||||
|
||||
public void GrowTomato()
|
||||
{
|
||||
string tomato = "Tomato";
|
||||
Console.WriteLine($"{this.GetType().Name} raised {tomato}");
|
||||
mediator.Send(tomato, this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Завод
|
||||
/// </summary>
|
||||
class Cannery : Colleague
|
||||
{
|
||||
public Cannery(Mediator mediator)
|
||||
: base(mediator) { }
|
||||
|
||||
public void MakeKetchup(string message)
|
||||
{
|
||||
string ketchup = message + " Ketchup";
|
||||
Console.WriteLine($"{this.GetType().Name} produced {ketchup}");
|
||||
mediator.Send(ketchup, this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Магазин
|
||||
/// </summary>
|
||||
class Shop : Colleague
|
||||
{
|
||||
public Shop(Mediator mediator)
|
||||
: base(mediator) { }
|
||||
public void SellKetshup(string message)
|
||||
{
|
||||
Console.WriteLine($"{this.GetType().Name} sold {message}");
|
||||
}
|
||||
}
|
||||
|
||||
class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
ConcreteMediator mediator = new ConcreteMediator();
|
||||
var cannery = new Cannery(mediator);
|
||||
var fermer = new Fermer(mediator);
|
||||
var shop = new Shop(mediator);
|
||||
|
||||
mediator.Cannery = cannery;
|
||||
mediator.Fermer = fermer;
|
||||
mediator.Shop = shop;
|
||||
|
||||
fermer.GrowTomato();
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<RootNamespace>Pattern_3_Строитель_Builder_</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
170
Patterns/Pattern_3-Строитель(Builder)/Program.cs
Normal file
170
Patterns/Pattern_3-Строитель(Builder)/Program.cs
Normal file
@ -0,0 +1,170 @@
|
||||
/*
|
||||
* ПОРОЖДАЮЩИЕ ПАТТЕРНЫ
|
||||
*
|
||||
* Глава_11: Строитель (Builder)
|
||||
*
|
||||
* - строитель отделяет конструирование сложного объекта
|
||||
* от его представления, так что в результате одного и того же
|
||||
* процесса конструирования могут получаться разные представления.
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Шаблон адреса
|
||||
/// </summary>
|
||||
class Address
|
||||
{
|
||||
public string Street { get; set; }
|
||||
public string House { get; set; }
|
||||
|
||||
public Address(string street, string house)
|
||||
{
|
||||
Street = street;
|
||||
House = house;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Представление с точки зрения паттерна
|
||||
/// </summary>
|
||||
class AddressElement
|
||||
{
|
||||
public string Title { get; set; }
|
||||
public string Value { get; set; }
|
||||
private List<AddressElement> Elements { get; set; }
|
||||
|
||||
public void AddElement(string title, string value)
|
||||
{
|
||||
Elements.Add(new AddressElement(title, value));
|
||||
}
|
||||
|
||||
public AddressElement(string title, string value)
|
||||
{
|
||||
Elements = new List<AddressElement>();
|
||||
Title = title;
|
||||
Value = value;
|
||||
}
|
||||
|
||||
private string Print(string indent = "") => "";
|
||||
public override string ToString() => "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Конструирует корневую главную ячейку
|
||||
/// </summary>
|
||||
class AddressBuilder
|
||||
{
|
||||
AddressElement address;
|
||||
|
||||
public static AddressBuilder Build(string title, string value)
|
||||
=> new AddressBuilder { address = new AddressElement(title, value) };
|
||||
|
||||
private AddressBuilder() { }
|
||||
|
||||
public AddressBuilder AddItem(string title, string value)
|
||||
{
|
||||
address.AddElement(title, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public override string ToString() => address.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Классическое представление паттерна
|
||||
/// </summary>
|
||||
class Address_Classic
|
||||
{
|
||||
public string? Country { get; set; }
|
||||
public string? City { get; set; }
|
||||
public string? Street { get; set; }
|
||||
public string? House { get; set; }
|
||||
public string? Number { get; set; }
|
||||
public override string ToString()
|
||||
{
|
||||
return $"Country: {(string.IsNullOrEmpty(Country) ? "unknown" : Country)}\n" +
|
||||
$"City: {(string.IsNullOrEmpty(City) ? "unknown" : City)}\n" +
|
||||
$"Street: {(string.IsNullOrEmpty(Street) ? "unknown" : Street)}\n" +
|
||||
$"House: {(string.IsNullOrEmpty(House) ? "unknown" : House)}\n" +
|
||||
$"Number: {(string.IsNullOrEmpty(Number) ? "unknown" : Number)}\n";
|
||||
}
|
||||
}
|
||||
|
||||
interface IAddressBuilder
|
||||
{
|
||||
IAddressBuilder SetCountry(string country);
|
||||
IAddressBuilder SetCity(string city);
|
||||
IAddressBuilder SetStreet(string street);
|
||||
IAddressBuilder SetHouse(string house);
|
||||
IAddressBuilder SetNumber(string number);
|
||||
Address_Classic Build();
|
||||
}
|
||||
|
||||
class AddressBuilder_Classic : IAddressBuilder
|
||||
{
|
||||
Address_Classic address_Classic;
|
||||
public AddressBuilder_Classic() => address_Classic = new Address_Classic();
|
||||
public Address_Classic Build() => address_Classic;
|
||||
|
||||
public IAddressBuilder SetCity(string city)
|
||||
{
|
||||
address_Classic.City = city;
|
||||
return this;
|
||||
}
|
||||
|
||||
public IAddressBuilder SetCountry(string country)
|
||||
{
|
||||
address_Classic.Country = country;
|
||||
return this;
|
||||
}
|
||||
|
||||
public IAddressBuilder SetHouse(string house)
|
||||
{
|
||||
address_Classic.House = house;
|
||||
return this;
|
||||
}
|
||||
|
||||
public IAddressBuilder SetNumber(string number)
|
||||
{
|
||||
address_Classic.Number = number;
|
||||
return this;
|
||||
}
|
||||
|
||||
public IAddressBuilder SetStreet(string street)
|
||||
{
|
||||
address_Classic.Street = street;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
AddressBuilder addressBuilder =
|
||||
AddressBuilder
|
||||
.Build("Адрес", "Рабочий адрес")
|
||||
.AddItem("Индекс", "214000")
|
||||
.AddItem("страна", "РФ");
|
||||
|
||||
Console.WriteLine("");
|
||||
|
||||
//Классический конструктор
|
||||
|
||||
Address_Classic address_Classic = new AddressBuilder_Classic()
|
||||
.SetCountry("country")
|
||||
.SetCity("Moscow")
|
||||
.SetHouse("Home")
|
||||
.SetNumber("25")
|
||||
.Build();
|
||||
|
||||
Console.WriteLine(address_Classic);
|
||||
|
||||
address_Classic = new AddressBuilder_Classic()
|
||||
.SetCountry("New York")
|
||||
.SetStreet("Skobelevskaya")
|
||||
.Build();
|
||||
|
||||
Console.WriteLine(address_Classic);
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<RootNamespace>Pattern_4_Итератор_Iterator_</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
333
Patterns/Pattern_4-Итератор(Iterator)/Program.cs
Normal file
333
Patterns/Pattern_4-Итератор(Iterator)/Program.cs
Normal file
@ -0,0 +1,333 @@
|
||||
/*
|
||||
* ПАТТЕРНЫ ПОВЕДЕНИЯ
|
||||
*
|
||||
* Глава_4: Итератор
|
||||
*
|
||||
* - представляет доступ ко всем элементам составного объекта, не раскрывая его внутреннего представления
|
||||
*/
|
||||
|
||||
/*
|
||||
* пример техники "перечисляемый-перечислитель"
|
||||
*/
|
||||
|
||||
interface IEnumerable
|
||||
{
|
||||
IEnumerator GetEnumenator();
|
||||
}
|
||||
|
||||
class Bank : IEnumerable
|
||||
{
|
||||
List<Banknote> bankVault = new List<Banknote>()
|
||||
{
|
||||
new Banknote(), new Banknote(),
|
||||
new Banknote(), new Banknote()
|
||||
};
|
||||
|
||||
|
||||
public Banknote this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
return bankVault[index];
|
||||
}
|
||||
set
|
||||
{
|
||||
bankVault.Insert(index, value);
|
||||
}
|
||||
}
|
||||
|
||||
public int Count { get { return bankVault.Count; } }
|
||||
|
||||
public IEnumerator GetEnumenator()
|
||||
{
|
||||
return new Cashier(this);
|
||||
}
|
||||
}
|
||||
|
||||
class Banknote
|
||||
{
|
||||
public string Nominal = "100 $";
|
||||
}
|
||||
|
||||
interface IEnumerator
|
||||
{
|
||||
bool MoveNext();
|
||||
void Reset();
|
||||
object Current { get; }
|
||||
}
|
||||
|
||||
|
||||
class Cashier : IEnumerator
|
||||
{
|
||||
private Bank bank;
|
||||
private int current = -1;
|
||||
|
||||
public Cashier(Bank bank)
|
||||
{
|
||||
this.bank = bank;
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
if(current < bank.Count - 1)
|
||||
{
|
||||
current++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
current = -1;
|
||||
}
|
||||
|
||||
public object Current
|
||||
{
|
||||
get
|
||||
{
|
||||
return bank[current];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
class SimpleSet<T>
|
||||
{
|
||||
int index;//какой именно элемент нужно возвращать
|
||||
readonly T[] storage;
|
||||
public SimpleSet(params T[] args)
|
||||
{
|
||||
storage = args;
|
||||
Reset();
|
||||
}
|
||||
|
||||
//свойство возвращающее элеент нашего хранилища
|
||||
public T Current => storage[index++];
|
||||
//можно ли продолжать обход массива
|
||||
public bool MoveNext => index < storage.Length;
|
||||
//обнуление значение индекса обхода
|
||||
public void Reset() => index = 0;
|
||||
}
|
||||
|
||||
class SimleSetYeild<T> : IEnumerable<T>// IEnumerator<T>,
|
||||
{
|
||||
//int index;
|
||||
readonly T[] storage;
|
||||
public SimleSetYeild(params T[] args)
|
||||
{
|
||||
storage = args;
|
||||
//Reset();
|
||||
}
|
||||
|
||||
//public T Current => storage[index++];
|
||||
|
||||
//object System.Collections.IEnumerator.Current => Current;
|
||||
|
||||
//public void Dispose(){}
|
||||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
var len = storage.Length;
|
||||
for (int i = 0; i < len; i++)
|
||||
yield return storage[i]; //позволяет вернуть значение и перейти на следующую итерацию цикла
|
||||
}
|
||||
|
||||
//public bool MoveNext() => index < storage.Length;
|
||||
//public void Reset() => index = 0;
|
||||
|
||||
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => this.GetEnumerator();
|
||||
}
|
||||
|
||||
class Dish : IEnumerable<int>
|
||||
{
|
||||
public Dish(string Name, int Weight, int Proteins = 0, int Fats = 0, int Carbohydrates = 0)
|
||||
{
|
||||
this.Name = Name;
|
||||
this.Weight = Weight;
|
||||
//this.Proteins = Proteins;
|
||||
//this.Fats = Fats;
|
||||
nutrients = new Dictionary<string, int>
|
||||
{
|
||||
["Proteins"] = Proteins,
|
||||
["Fats"] = Fats,
|
||||
["Carbohydrates"] = Carbohydrates
|
||||
};
|
||||
}
|
||||
|
||||
//допы
|
||||
readonly Dictionary<string, int> nutrients;
|
||||
public int Proteins => nutrients[nameof(Proteins)];
|
||||
public int Fats => nutrients[nameof(Fats)];
|
||||
public int Carbohydrates => nutrients[nameof(Carbohydrates)];
|
||||
|
||||
public double AverageNutrients => nutrients.Values.Average();
|
||||
|
||||
//init - только в конструкторе может изменять значения свойства
|
||||
public string Name { get; init; }
|
||||
public int Weight { get; init; }
|
||||
//public int Proteins { get; set; }
|
||||
//public int Fats { get; set; }
|
||||
//public int Average => (Proteins + Fats) / 2;
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{nameof(Name)} : {Name} {nameof(Weight)} : {Weight}";
|
||||
}
|
||||
|
||||
|
||||
public IEnumerator<int> GetEnumerator() => nutrients.Values.GetEnumerator();
|
||||
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
}
|
||||
|
||||
class Menu : IEnumerable<Dish>
|
||||
{
|
||||
public Dish Pizza { get; init; }
|
||||
public Dish Coffee { get; init; }
|
||||
public Dish Soup { get; init; }
|
||||
|
||||
public IEnumerator<Dish> GetEnumerator()
|
||||
{
|
||||
//В каком порядке перечислять
|
||||
yield return Pizza;
|
||||
yield return Coffee;
|
||||
yield return Soup;
|
||||
}
|
||||
|
||||
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => (System.Collections.IEnumerator)this;
|
||||
}
|
||||
|
||||
public class Node<T>
|
||||
{
|
||||
public T Value { get; set; }
|
||||
public Node<T> Left { get; set; }
|
||||
public Node<T> Right { get; set; }
|
||||
public Node<T> Parent { get; set; }
|
||||
public Node (T value) => Value = value;
|
||||
public Node (T value, Node<T> left = null, Node<T> right = null)
|
||||
: this(value)
|
||||
{
|
||||
Left = left;
|
||||
Right = right;
|
||||
if(Left != null) Left.Parent = this;
|
||||
if(Right != null) Right.Parent = this;
|
||||
}
|
||||
|
||||
public override string ToString() => Value.ToString();
|
||||
}
|
||||
|
||||
//обход самого дерева
|
||||
public class InOrderIterator<T>
|
||||
{
|
||||
public Node<T> Current { get; set; }
|
||||
private readonly Node<T> root;
|
||||
private bool detourStarted;
|
||||
//принимает корневой элемент с которого начнёт обход
|
||||
public InOrderIterator(Node<T> root)
|
||||
{
|
||||
this.root = Current = root;
|
||||
Reset();
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
Current = root;
|
||||
while(Current.Left != null) Current = Current.Left;
|
||||
detourStarted = !true;
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
if (!detourStarted)
|
||||
{
|
||||
detourStarted = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Current.Right != null)
|
||||
{
|
||||
Current = Current.Right;
|
||||
while (Current.Left != null) Current = Current.Left;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
var temp = Current.Parent;
|
||||
while(temp != null && Current == temp.Right)
|
||||
{
|
||||
Current = temp;
|
||||
temp = temp.Parent;
|
||||
}
|
||||
Current = temp;
|
||||
return Current != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
IEnumerable bank = new Bank();
|
||||
|
||||
IEnumerator cashier = bank.GetEnumenator();
|
||||
|
||||
while(cashier.MoveNext())
|
||||
{
|
||||
if(cashier.Current is Banknote banknote)
|
||||
Console.WriteLine(banknote.Nominal);
|
||||
}
|
||||
|
||||
//стандартное реализация паттерна Итератор
|
||||
var array = Enumerable.Range(1, 10).ToArray();
|
||||
foreach (var item in array)
|
||||
Console.WriteLine($"array: {item} ");
|
||||
|
||||
SimpleSet<int> set = new (array);
|
||||
set.Reset();
|
||||
while(set.MoveNext)
|
||||
Console.WriteLine($"set: {set.Current}");
|
||||
|
||||
//Вторая реализация паттерна
|
||||
SimleSetYeild<int> setyeild = new(array);
|
||||
foreach (var item in setyeild) Console.WriteLine($"setyeild: {item}");
|
||||
|
||||
Menu menu = new()
|
||||
{
|
||||
Coffee = new("Latte", 200, 111, 222, 333),
|
||||
Soup = new("Tom ", 230),
|
||||
Pizza = new("Margarita", 600),
|
||||
};
|
||||
|
||||
//foreach (var dish in menu) Console.WriteLine(dish);
|
||||
foreach (var dish in menu)
|
||||
{
|
||||
Console.WriteLine($"{dish} - Average: {dish.AverageNutrients} [ ");
|
||||
foreach (var st in dish)
|
||||
{
|
||||
Console.WriteLine($"{nameof(st)} {st}");
|
||||
}
|
||||
Console.WriteLine("] ");
|
||||
}
|
||||
|
||||
//пример обхода деревьев (паттерн)
|
||||
var three = new Node<string>(value: "html",
|
||||
left: new(value: "head",
|
||||
left: new(value: "title"),
|
||||
right: new(value: "meta")),
|
||||
right: new(value: "body",
|
||||
left: new(value: "h1",
|
||||
left: new(value: "a")),
|
||||
right: new(value: "ul",
|
||||
left: new(value: "li"),
|
||||
right: new(value: "li")))
|
||||
);
|
||||
|
||||
var rlr = new InOrderIterator<string>(three);
|
||||
while (rlr.MoveNext()) Console.WriteLine($"{rlr.Current}");
|
||||
Console.WriteLine();
|
||||
rlr.Reset();
|
||||
while (rlr.MoveNext()) Console.WriteLine($"{rlr.Current}");
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<RootNamespace>Pattern_4_Компоновщик_Composite_</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
166
Patterns/Pattern_4-Компоновщик(Composite)/Program.cs
Normal file
166
Patterns/Pattern_4-Компоновщик(Composite)/Program.cs
Normal file
@ -0,0 +1,166 @@
|
||||
/*
|
||||
* СТРУКТУРНЫЕ ПАТТЕРНЫ
|
||||
*
|
||||
* Глава_15: Компоновщик (Composite)
|
||||
*
|
||||
* - компонует объекты в древовидные структуры для представления
|
||||
* иерархий «часть — целое». Позволяет клиентам единообразно
|
||||
* трактовать индивидуальные и составные объекты
|
||||
*/
|
||||
|
||||
class UIElement
|
||||
{
|
||||
public UIElement(string name)
|
||||
{
|
||||
Children = new List<UIElement>();
|
||||
}
|
||||
public List<UIElement> Children { get; set; }
|
||||
public string Name { get; set; }
|
||||
public int Width { get; set; }
|
||||
public int Height { get; set; }
|
||||
protected virtual string Draw(string p = "") { return p; }
|
||||
public override string ToString() => $"{Draw()}";
|
||||
}
|
||||
|
||||
class TextBox : UIElement
|
||||
{
|
||||
public TextBox(string name = "textBox") : base(name) { }
|
||||
}
|
||||
|
||||
class Label : UIElement
|
||||
{
|
||||
public Label(string name = "label") : base(name) { }
|
||||
}
|
||||
|
||||
class Panel : UIElement
|
||||
{
|
||||
public Panel(string name = "panel") : base(name) { }
|
||||
}
|
||||
|
||||
class TextBlock : UIElement
|
||||
{
|
||||
public TextBlock(string name = "textBlock") : base(name) { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Пример отправки писем группе адресатов
|
||||
/// </summary>
|
||||
interface IEMail
|
||||
{
|
||||
void Send();
|
||||
string Name { get; set; }
|
||||
}
|
||||
|
||||
class Group : IEMail
|
||||
{
|
||||
public Group(params IEMail[] es) => Append(es);
|
||||
|
||||
public List<IEMail> eMails = new();
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public void Append(params IEMail[] es) {
|
||||
foreach (var item in es) eMails.Add(item);
|
||||
}
|
||||
|
||||
public void Send() {
|
||||
foreach(var item in eMails) item.Send();
|
||||
}
|
||||
}
|
||||
|
||||
class EMail : IEMail
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public void Send() => Console.WriteLine($"Send {Name}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Генератор файловой системы
|
||||
/// </summary>
|
||||
abstract class IFileSystem
|
||||
{
|
||||
protected virtual IFileSystem AddItem(IFileSystem element) => this;
|
||||
public abstract void PrintInfo(string w = "");
|
||||
public string Title { get; set; }
|
||||
}
|
||||
|
||||
class Document : IFileSystem
|
||||
{
|
||||
public override void PrintInfo(string w = "")
|
||||
{
|
||||
Console.WriteLine($"{w}{Title}");
|
||||
}
|
||||
}
|
||||
|
||||
class Folder : IFileSystem
|
||||
{
|
||||
private readonly List<IFileSystem> fileSystem;
|
||||
public Folder() => fileSystem = new();
|
||||
|
||||
public IFileSystem AddElement(params IFileSystem[] element)
|
||||
{
|
||||
foreach (var item in element) AddItem(item);
|
||||
return this;
|
||||
}
|
||||
|
||||
public override void PrintInfo(string w = "")
|
||||
{
|
||||
Console.WriteLine($"{w}{Title}");
|
||||
foreach (var item in fileSystem) item.PrintInfo(w);
|
||||
}
|
||||
|
||||
protected override IFileSystem AddItem(IFileSystem element)
|
||||
{
|
||||
fileSystem.Add(element);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] argv)
|
||||
{
|
||||
#region 1
|
||||
var panel1 = new Panel("panel1");
|
||||
var tb1 = new TextBox("textBox1");
|
||||
var tb2 = new TextBox("textBox2");
|
||||
panel1.Children.Add(tb1);
|
||||
var panel2 = new Panel("panel2");
|
||||
var tb3 = new TextBox("textBox3");
|
||||
var lbl1 = new Label("label1");
|
||||
lbl1.Children.Add(new TextBlock("textBlock1"));
|
||||
panel2.Children.Add(tb3);
|
||||
panel2.Children.Add(lbl1);
|
||||
panel1.Children.Add(panel2);
|
||||
panel1.Children.Add(tb2);
|
||||
|
||||
Console.WriteLine(panel1);
|
||||
#endregion
|
||||
#region 2
|
||||
EMail c = new EMail() { Name = "nik" };
|
||||
c.Send();
|
||||
EMail r = new EMail() { Name = "nikr" };
|
||||
r.Send();
|
||||
EMail u = new EMail() { Name = "niku" };
|
||||
u.Send();
|
||||
EMail d = new EMail() { Name = "nikd" };
|
||||
d.Send();
|
||||
|
||||
Group cr = new Group(c, r, u);
|
||||
cr.Send();
|
||||
|
||||
//3
|
||||
new Folder() { Title = "C:/"}
|
||||
.AddElement(new Folder() { Title = "Windows/"}
|
||||
.AddElement(new Folder() { Title = "System32/" }
|
||||
.AddElement(new Document() { Title = "system.xml"}),
|
||||
new Folder() { Title = "Driver/"}
|
||||
.AddElement(new Folder() { Title = "etc/"}
|
||||
.AddElement(new Document() { Title = "jp.json"}),
|
||||
new Folder() { Title = "etc2"})))
|
||||
.PrintInfo();
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<RootNamespace>Pattern_5_Заместитель_Proxy_</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
130
Patterns/Pattern_5-Заместитель(Proxy)/Program.cs
Normal file
130
Patterns/Pattern_5-Заместитель(Proxy)/Program.cs
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* СТРУКТУРНЫЕ ПАТТЕРНЫ
|
||||
*
|
||||
* Глава_16: Заместитель (Proxy)
|
||||
*
|
||||
* - является суррогатом другого объекта и контролирует доступ к нему.
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Абстрактная сущность о беге
|
||||
/// </summary>
|
||||
public abstract class ActionObject
|
||||
{
|
||||
public abstract void Run();
|
||||
}
|
||||
|
||||
public class Human : ActionObject
|
||||
{
|
||||
public int Age { get; set; }
|
||||
public Human ()
|
||||
{
|
||||
Age = new Random().Next(14, 70);
|
||||
}
|
||||
public override void Run() => Console.WriteLine("RUN!");
|
||||
public Human Clone()
|
||||
{
|
||||
Human temp = new Human() { Age = this.Age };
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
|
||||
public class AvatarV1 : ActionObject
|
||||
{
|
||||
Human human;
|
||||
public AvatarV1(Human human)
|
||||
{
|
||||
this.human = human.Clone();
|
||||
//или
|
||||
//this.human = human;
|
||||
//если есть(нужен) доступ к исходному объекту
|
||||
}
|
||||
|
||||
public int AvatarAge => human.Age;
|
||||
public override void Run()
|
||||
{
|
||||
Console.WriteLine("AvatarV1 Run");
|
||||
human.Run();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Proxy сервер
|
||||
/// </summary>
|
||||
class Client
|
||||
{
|
||||
private string id;
|
||||
public string Id { get => id; set => id = value; }
|
||||
public Client(string id = "#2022") => this.id = id;
|
||||
}
|
||||
|
||||
interface IServer
|
||||
{
|
||||
void AccessGranted(Client user);
|
||||
void AccessClosed(Client user);
|
||||
}
|
||||
|
||||
class Server : IServer
|
||||
{
|
||||
public Server() => Console.WriteLine("Сервер создан");
|
||||
public void AccessClosed(Client user)
|
||||
{
|
||||
Console.WriteLine("Closed");
|
||||
}
|
||||
|
||||
public void AccessGranted(Client user)
|
||||
{
|
||||
Console.WriteLine("Granted");
|
||||
}
|
||||
}
|
||||
|
||||
class ServerProxy : IServer
|
||||
{
|
||||
private Lazy<Server> server;
|
||||
public ServerProxy() { }
|
||||
|
||||
public void AccessClosed(Client client)
|
||||
{
|
||||
if (server == null)
|
||||
{
|
||||
Console.WriteLine("Unknown user");
|
||||
}
|
||||
else
|
||||
{
|
||||
server.Value.AccessGranted(user: client);
|
||||
}
|
||||
}
|
||||
|
||||
public void Autentification(Client client)
|
||||
{
|
||||
if (client.Id != "#2022") return;
|
||||
Console.WriteLine("OK");
|
||||
server = new();
|
||||
AccessGranted(client);
|
||||
}
|
||||
|
||||
public void AccessGranted(Client client)
|
||||
{
|
||||
if(server == null)
|
||||
{
|
||||
Console.WriteLine("Access Close");
|
||||
return;
|
||||
}
|
||||
server.Value.AccessClosed(user: client);
|
||||
}
|
||||
}
|
||||
|
||||
class Program
|
||||
{
|
||||
public static void Main(string[] argv)
|
||||
{
|
||||
Human human = new Human();
|
||||
human.Run();
|
||||
AvatarV1 avatar = new AvatarV1(human);
|
||||
avatar.Run();
|
||||
ServerProxy proxy = new(); //proxy прослойка между сервером
|
||||
proxy.Autentification(new Client() { });
|
||||
proxy.AccessGranted(new Client() { });
|
||||
proxy.AccessClosed(new Client() { });
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<RootNamespace>Pattern_5_Наблюдатель_Observer_</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
328
Patterns/Pattern_5-Наблюдатель(Observer)/Program.cs
Normal file
328
Patterns/Pattern_5-Наблюдатель(Observer)/Program.cs
Normal file
@ -0,0 +1,328 @@
|
||||
using System.Collections;
|
||||
/*
|
||||
* ПАТТЕРНЫ ПОВЕДЕНИЯ
|
||||
*
|
||||
* Глава_5: Наблюдатель
|
||||
*
|
||||
* - определяет зависимость типа «один ко многим»» (один издатель ко многим подписчикам) между объектами
|
||||
* таким образом, что при изменении состояния одного объекта все зависящие от него
|
||||
* оповещаются об этом и автоматически обновляются
|
||||
*
|
||||
* -описывает правильные способы организации процесса подписки на определенные события
|
||||
*/
|
||||
|
||||
/*
|
||||
* Модель вытягивания (Pull model)
|
||||
*/
|
||||
/// <summary>
|
||||
/// Обозреватели газеты
|
||||
/// </summary>
|
||||
abstract class Observer
|
||||
{
|
||||
public abstract void Update();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Издатели газеты
|
||||
/// </summary>
|
||||
abstract class Subject
|
||||
{
|
||||
ArrayList observers = new ArrayList();
|
||||
|
||||
public void Attach(Observer observer)
|
||||
{
|
||||
observers.Add(observer);
|
||||
}
|
||||
|
||||
public void Detach(Observer observer)
|
||||
{
|
||||
observers.Remove(observer);
|
||||
}
|
||||
|
||||
public void Notify()
|
||||
{
|
||||
foreach (Observer observer in observers)
|
||||
observer.Update();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Конкретный издатель(издатель газеты) (наблюдаемый)
|
||||
/// </summary>
|
||||
class ConcreteSubject
|
||||
: Subject
|
||||
{
|
||||
public string State { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Конкретный обозреватель (наблюдатель)
|
||||
/// </summary>
|
||||
class ConcreteObserver
|
||||
: Observer
|
||||
{
|
||||
string observerState;
|
||||
ConcreteSubject subject;
|
||||
|
||||
public ConcreteObserver(ConcreteSubject subject)
|
||||
{
|
||||
this.subject = subject;
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
observerState = subject.State;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Модель проталкивания (Push model)
|
||||
*/
|
||||
/// <summary>
|
||||
/// Обозреватели газеты
|
||||
/// </summary>
|
||||
abstract class Observer_Push
|
||||
{
|
||||
public abstract void Update(string state); // получает уведомление о новостях
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Издатели газеты
|
||||
/// </summary>
|
||||
abstract class Subject_Push
|
||||
{
|
||||
ArrayList observers = new ArrayList();
|
||||
|
||||
public abstract string State { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Добавить новость в газету
|
||||
/// </summary>
|
||||
/// <param name="observer">обозреватель газеты</param>
|
||||
public void Attach(Observer_Push observer)
|
||||
{
|
||||
observers.Add(observer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Удалить новость из газеты
|
||||
/// </summary>
|
||||
/// <param name="observer">обозреватель газеты</param>
|
||||
public void Detach(Observer_Push observer)
|
||||
{
|
||||
observers.Remove(observer);
|
||||
}
|
||||
|
||||
public void Notify()
|
||||
{
|
||||
foreach (Observer_Push observer in observers)
|
||||
observer.Update(State);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Конкретный издатель(издатель газеты)
|
||||
/// </summary>
|
||||
class ConcreteSubject_Push
|
||||
: Subject_Push
|
||||
{
|
||||
public override string State { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Конкретный обозреватель
|
||||
/// </summary>
|
||||
class ConcreteObserver_Push
|
||||
: Observer_Push
|
||||
{
|
||||
string observerState;
|
||||
ConcreteSubject_Push subject;
|
||||
|
||||
public ConcreteObserver_Push(ConcreteSubject_Push subject)
|
||||
{
|
||||
this.subject = subject;
|
||||
}
|
||||
|
||||
public override void Update(string state)
|
||||
{
|
||||
observerState = subject.State;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Пример №2
|
||||
/// </summary>
|
||||
class Event { }
|
||||
class LoggerEvent : Event { }
|
||||
class AlertEvent : Event { }
|
||||
|
||||
/// <summary>
|
||||
/// Класс, за которым можно наблюдать
|
||||
/// получая оповещения о происходящих в нем событиях
|
||||
/// </summary>
|
||||
class TicTokUser : IObservable<Event>
|
||||
{
|
||||
public List<Subscription> Subscriptions { get; init; }
|
||||
|
||||
public TicTokUser() => Subscriptions = new List<Subscription>();
|
||||
|
||||
public void Alert()
|
||||
{
|
||||
Random r = new Random();
|
||||
foreach (var sub in Subscriptions)
|
||||
{
|
||||
Event e = r.Next(2) switch
|
||||
{
|
||||
0 => new LoggerEvent(),
|
||||
_ => new AlertEvent()
|
||||
};
|
||||
sub.observer.OnNext(e);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
- IObserver - тот, кто хочет получать
|
||||
уведомления от наблюдающего класса
|
||||
- IDisposable - как правило реализуют
|
||||
с целью возможной отписки
|
||||
*/
|
||||
public IDisposable Subscribe(IObserver<Event> observer)
|
||||
{
|
||||
var sub = new Subscription(this, observer);
|
||||
Subscriptions.Add(sub);
|
||||
return sub;
|
||||
}
|
||||
}
|
||||
|
||||
class Subscription : IDisposable
|
||||
{
|
||||
private TicTokUser user;
|
||||
public IObserver<Event> observer;
|
||||
public Subscription(TicTokUser user, IObserver<Event> observer)
|
||||
{
|
||||
this.user = user;
|
||||
this.observer = observer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Удаление наблюдаемого класса из перечня подписавшихся
|
||||
/// </summary>
|
||||
public void Dispose() => user.Subscriptions.Remove(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Конкретный подписчик
|
||||
/// </summary>
|
||||
class Observers : IObserver<Event>
|
||||
{
|
||||
public Observers()
|
||||
{
|
||||
var user = new TicTokUser();
|
||||
var sub = user.Subscribe(this);
|
||||
user.Alert();
|
||||
user.Alert();
|
||||
sub.Dispose();
|
||||
user.Alert();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Наблюдение окончено - больше ничего
|
||||
/// происходить не будет
|
||||
/// </summary>
|
||||
public void OnCompleted() { }
|
||||
|
||||
/// <summary>
|
||||
/// Обработка ошибки, явное оповещение
|
||||
/// </summary>
|
||||
/// <param name="error"></param>
|
||||
public void OnError(Exception error) { }
|
||||
|
||||
/// <summary>
|
||||
/// Событие при получении данных
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public void OnNext(Event value)
|
||||
{
|
||||
if (value is LoggerEvent) Console.WriteLine("Произошло событие OnNext value is LoggerEvent");
|
||||
if (value is AlertEvent) Console.WriteLine("Произошло событие OnNext value is AlertEvent");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Логика социальной сети (делегаты)
|
||||
/// </summary>
|
||||
class MediaFile
|
||||
{
|
||||
public MediaFile (string fileName) => FileName = fileName;
|
||||
public string FileName { get; set; }
|
||||
}
|
||||
|
||||
class Video : MediaFile
|
||||
{
|
||||
public Video(string fileName) : base(fileName) { }
|
||||
}
|
||||
|
||||
class Accaunt
|
||||
{
|
||||
public string Nick { get; set; }
|
||||
}
|
||||
|
||||
class TicTokUsers : Accaunt
|
||||
{
|
||||
protected event Action<TicTokUsers, string> followers;
|
||||
public void Subscribe(TicTokUsers user)
|
||||
{
|
||||
Console.WriteLine($"{user.Nick} подписался на {Nick}");
|
||||
followers += user.Alert;
|
||||
}
|
||||
|
||||
public void UnSubscribe(TicTokUsers user)
|
||||
{
|
||||
Console.WriteLine($"{user.Nick} отдписался на {Nick}");
|
||||
followers -= user.Alert;
|
||||
}
|
||||
|
||||
public void Alert(TicTokUsers sender, string info)
|
||||
{
|
||||
if (sender != this) Console.WriteLine($"Лента {Nick}: У {sender.Nick} {info}");
|
||||
else Console.WriteLine($"У меня ({Nick}) {info}");
|
||||
}
|
||||
|
||||
public void VideoPublishing(MediaFile media)
|
||||
{
|
||||
var fn = $"вышло видео '{media.FileName}'";
|
||||
Alert(this, fn);
|
||||
followers?.Invoke(this, fn);
|
||||
}
|
||||
}
|
||||
|
||||
class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
Console.WriteLine("Pull model");
|
||||
ConcreteSubject subject_pull = new ConcreteSubject(); //инициализируем издателя газеты
|
||||
subject_pull.Attach(new ConcreteObserver(subject_pull)); //публикуем новость для читателя
|
||||
subject_pull.Attach(new ConcreteObserver(subject_pull)); //публикуем новость для читателя
|
||||
subject_pull.State = "Some state ...";
|
||||
subject_pull.Notify();
|
||||
Console.WriteLine("Push model");
|
||||
ConcreteSubject subject_push = new ConcreteSubject();
|
||||
subject_push.Attach(new ConcreteObserver(subject_push)); //публикуем новость для читателя
|
||||
subject_push.Attach(new ConcreteObserver(subject_push)); //публикуем новость для читателя
|
||||
subject_push.State = "Some state ...";
|
||||
subject_push.Notify();
|
||||
|
||||
_ = new Observers(); //Пример 2 на TicTok
|
||||
TicTokUsers user1 = new() { Nick = "user_1" };
|
||||
TicTokUsers user2 = new() { Nick = "user_2" };
|
||||
user1.VideoPublishing(new MediaFile("Misl 1"));
|
||||
user1.Subscribe(user2);
|
||||
user1.VideoPublishing(new MediaFile("Misl 2"));
|
||||
user1.VideoPublishing(new MediaFile("Misl 3"));
|
||||
Console.WriteLine();
|
||||
user2.Subscribe(user1);
|
||||
user2.VideoPublishing(new MediaFile("History 1"));
|
||||
Console.ReadLine();
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using static System.Console;
|
||||
|
||||
namespace Pattern_5_Наблюдатель_Observer_
|
||||
{
|
||||
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<RootNamespace>Pattern_6_Посетитель_Visitor_</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
121
Patterns/Pattern_6-Посетитель(Visitor)/Program.cs
Normal file
121
Patterns/Pattern_6-Посетитель(Visitor)/Program.cs
Normal file
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* ПАТТЕРНЫ ПОВЕДЕНИЯ
|
||||
*
|
||||
* Глава_6: Посетитель
|
||||
*
|
||||
* - добавление поведения в иерархию объектов, не изменяя их классы
|
||||
*/
|
||||
|
||||
/*
|
||||
* При добавлении нового поведения в IAnimal нарушаются SOLID принципы,
|
||||
* для этого и существует подход Visitor чтобы внедрять поведение в конкретные классы наследники
|
||||
*/
|
||||
interface IAnimal
|
||||
{
|
||||
void Move();
|
||||
}
|
||||
|
||||
class Cat : IAnimal
|
||||
{
|
||||
public void Move() => Console.WriteLine("Kradetsy besshumno");
|
||||
}
|
||||
|
||||
class Dog : IAnimal
|
||||
{
|
||||
public void Move() => Console.WriteLine("beshit");
|
||||
}
|
||||
|
||||
class Bird : IAnimal
|
||||
{
|
||||
public void Move() => Console.WriteLine("fly");
|
||||
}
|
||||
|
||||
interface IVisitor
|
||||
{
|
||||
void Make(Cats cat);
|
||||
void Make(Dogs cat);
|
||||
void Make(Birds cat);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Реализация Visitor №1
|
||||
/// </summary>
|
||||
abstract class Animals
|
||||
{
|
||||
public abstract void Accept(IVisitor visitor);
|
||||
}
|
||||
|
||||
class Cats : Animals
|
||||
{
|
||||
public override void Accept(IVisitor visitor) => visitor.Make(this);
|
||||
}
|
||||
|
||||
class Dogs : Animals
|
||||
{
|
||||
public override void Accept(IVisitor visitor) => visitor.Make(this);
|
||||
}
|
||||
|
||||
class Birds : Animals
|
||||
{
|
||||
public override void Accept(IVisitor visitor) => visitor.Make(this);
|
||||
}
|
||||
|
||||
class Kiwi : Birds
|
||||
{
|
||||
public override void Accept(IVisitor visitor) => visitor.Make(this);
|
||||
}
|
||||
|
||||
class VoiceVisitor : IVisitor
|
||||
{
|
||||
public virtual void Make(Dogs dogs) => Console.WriteLine("Gav");
|
||||
public virtual void Make(Cats cat) => Console.WriteLine("My");
|
||||
public virtual void Make(Birds cat) => Console.WriteLine("Chirik");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Visitor для птички Киви
|
||||
/// </summary>
|
||||
class UpdateVoiceVisitor : VoiceVisitor
|
||||
{
|
||||
public override void Make(Birds bird)
|
||||
{
|
||||
if (bird is Kiwi) Console.WriteLine("Киви что-то там...");
|
||||
else base.Make(bird);
|
||||
}
|
||||
}
|
||||
|
||||
class MoveVisitor : IVisitor
|
||||
{
|
||||
public void Make(Cats cat) => Console.WriteLine("Kradet");
|
||||
public void Make(Dogs cat) => Console.WriteLine("Beg");
|
||||
public void Make(Birds cat) => Console.WriteLine("Fly");
|
||||
}
|
||||
|
||||
class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
Dogs dogs = new Dogs();
|
||||
Cats cats = new Cats();
|
||||
Birds birds = new Birds();
|
||||
|
||||
var voice = new VoiceVisitor();
|
||||
var move = new MoveVisitor();
|
||||
|
||||
dogs.Accept(voice);
|
||||
cats.Accept(voice);
|
||||
birds.Accept(voice);
|
||||
|
||||
dogs.Accept(move);
|
||||
cats.Accept(move);
|
||||
birds.Accept(move);
|
||||
|
||||
var updateVoiceVisitor = new UpdateVoiceVisitor();
|
||||
var kiwi = new Kiwi();
|
||||
|
||||
kiwi.Accept(updateVoiceVisitor);
|
||||
dogs.Accept(updateVoiceVisitor);
|
||||
cats.Accept(updateVoiceVisitor);
|
||||
birds.Accept(updateVoiceVisitor);
|
||||
}
|
||||
}
|
11
Patterns/Pattern_7-Команда/Pattern_7-Команда(Command).csproj
Normal file
11
Patterns/Pattern_7-Команда/Pattern_7-Команда(Command).csproj
Normal file
@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<RootNamespace>Pattern_7_Команда</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
129
Patterns/Pattern_7-Команда/Program.cs
Normal file
129
Patterns/Pattern_7-Команда/Program.cs
Normal file
@ -0,0 +1,129 @@
|
||||
/*
|
||||
* ПАТТЕРНЫ ПОВЕДЕНИЯ
|
||||
*
|
||||
* Глава_7_1: Команда
|
||||
*
|
||||
* - конкретное действие представить в виде конкретного объекта
|
||||
*/
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
class Accaunt
|
||||
{
|
||||
public string AccauntOwner { get; set; }
|
||||
public int Balance { get; set; }
|
||||
|
||||
public Accaunt(string accauntOwner, int balance)
|
||||
{
|
||||
Balance = balance;
|
||||
AccauntOwner = accauntOwner;
|
||||
}
|
||||
|
||||
public void Info()
|
||||
{
|
||||
Console.WriteLine($"{AccauntOwner}: ${Balance}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Проверить факт выполнения операции
|
||||
/// IOperation - единственный ответственный за действие
|
||||
/// </summary>
|
||||
interface IOperation
|
||||
{
|
||||
void Execute();
|
||||
public bool IsComplete { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Шаблон команды пополнения кошелька
|
||||
/// </summary>
|
||||
class Deposit : IOperation
|
||||
{
|
||||
private readonly Accaunt accaunt;
|
||||
private readonly int money;
|
||||
private bool isComplete;
|
||||
public bool IsComplete { get => isComplete; }
|
||||
public Deposit(Accaunt accaunt, int money)
|
||||
{
|
||||
this.accaunt = accaunt;
|
||||
this.money = money;
|
||||
isComplete = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Обработка выполения команды
|
||||
/// </summary>
|
||||
public void Execute()
|
||||
{
|
||||
accaunt.Balance += money;
|
||||
isComplete = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Команда снятия с кошелька
|
||||
/// </summary>
|
||||
class Withdraw : IOperation
|
||||
{
|
||||
private readonly Accaunt accaunt;
|
||||
private readonly int money;
|
||||
private bool isComplete;
|
||||
public bool IsComplete { get => isComplete; }
|
||||
public Withdraw(Accaunt accaunt, int money)
|
||||
{
|
||||
this.accaunt = accaunt;
|
||||
this.money = money;
|
||||
isComplete = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Обработка выполения команды
|
||||
/// </summary>
|
||||
public void Execute()
|
||||
{
|
||||
if (accaunt.Balance - money < 0) return;
|
||||
accaunt.Balance -= money;
|
||||
isComplete = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// коллекция команд
|
||||
/// </summary>
|
||||
class Operations : Collection<IOperation> { }
|
||||
|
||||
class OperationManager
|
||||
{
|
||||
static public OperationManager Instance;
|
||||
static OperationManager() => Instance = new OperationManager();
|
||||
private Operations transactions;
|
||||
private OperationManager() => transactions = new Operations();
|
||||
|
||||
public void AddOperation(IOperation operation) => transactions.Add(operation);
|
||||
|
||||
public void ProcessOperations()
|
||||
{
|
||||
transactions.Where(op => !op.IsComplete)
|
||||
.ToList()
|
||||
.ForEach(op => op.Execute());
|
||||
}
|
||||
}
|
||||
|
||||
class Program
|
||||
{
|
||||
public static void Main()
|
||||
{
|
||||
Accaunt accaunt = new Accaunt("nik", 1000);
|
||||
accaunt.Info();
|
||||
new Deposit(accaunt, 1000).Execute();
|
||||
accaunt.Info();
|
||||
|
||||
var manager = OperationManager.Instance;
|
||||
manager.AddOperation(new Deposit(accaunt, 1000));
|
||||
manager.AddOperation(new Deposit(accaunt, 1000));
|
||||
manager.AddOperation(new Withdraw(accaunt, 100));
|
||||
accaunt.Info();
|
||||
manager.ProcessOperations();
|
||||
accaunt.Info();
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<RootNamespace>Pattern_8_Состояние</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
165
Patterns/Pattern_8-Состояние/Program.cs
Normal file
165
Patterns/Pattern_8-Состояние/Program.cs
Normal file
@ -0,0 +1,165 @@
|
||||
/*
|
||||
* ПАТТЕРНЫ ПОВЕДЕНИЯ
|
||||
*
|
||||
* Глава_7_2: Состояние
|
||||
*
|
||||
* - позволяет объекту поменять свое поведение в зависимости от состояния
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Объектное представление логического состояния
|
||||
/// </summary>
|
||||
interface IState
|
||||
{
|
||||
void SetStateTrue(Variable v);
|
||||
void SetStateFalse(Variable v);
|
||||
}
|
||||
|
||||
class Variable
|
||||
{
|
||||
IState value;
|
||||
public Variable()
|
||||
{
|
||||
value = new StateFalse();
|
||||
}
|
||||
public void SetState(IState state) => value = state;
|
||||
public void False() => value.SetStateFalse(this);
|
||||
public void True() => value.SetStateTrue(this);
|
||||
public override string ToString() => value.ToString();
|
||||
}
|
||||
|
||||
class StateFalse : IState
|
||||
{
|
||||
public void SetStateFalse(Variable v) { Console.WriteLine("Итак в лжи [False]"); }
|
||||
public void SetStateTrue(Variable v) => v.SetState(new StateTrue());
|
||||
public override string ToString() => "Current state: False";
|
||||
}
|
||||
|
||||
class StateTrue : IState
|
||||
{
|
||||
public void SetStateFalse(Variable v) => v.SetState(new StateFalse());
|
||||
public void SetStateTrue(Variable v) { Console.WriteLine("Итак в истине [True]"); }
|
||||
public override string ToString() => "Current state: True";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// пример из реалной жизни
|
||||
/// </summary>
|
||||
class Camera : ICameraState
|
||||
{
|
||||
ICameraState state;
|
||||
public Camera() => state = new OffState();
|
||||
public void SetState(ICameraState state) => this.state = state;
|
||||
public void RecordVideo(Camera camera) => state.RecordVideo(camera);
|
||||
public void TakePictures(Camera camera) => state.TakePictures(camera);
|
||||
public void TurnOff(Camera camera) => state.TurnOff(camera);
|
||||
public void TurnOn(Camera camera) => state.TurnOn(camera);
|
||||
}
|
||||
|
||||
interface ICameraState
|
||||
{
|
||||
void TurnOn(Camera camera);
|
||||
void TurnOff(Camera camera);
|
||||
void TakePictures(Camera camera);
|
||||
void RecordVideo(Camera camera);
|
||||
}
|
||||
|
||||
class FotoState : ICameraState
|
||||
{
|
||||
public void RecordVideo(Camera camera)
|
||||
{
|
||||
Console.WriteLine("Переходим в режим видео");
|
||||
camera.RecordVideo(camera);
|
||||
}
|
||||
|
||||
public void TakePictures(Camera camera) => Console.WriteLine("Камера уже в режиме фото");
|
||||
|
||||
/// <summary>
|
||||
/// Выключить камеру
|
||||
/// </summary>
|
||||
/// <param name="camera">камера</param>
|
||||
public void TurnOff(Camera camera)
|
||||
{
|
||||
Console.WriteLine("Нажата кнопка выключения");
|
||||
camera.SetState(new OffState());
|
||||
}
|
||||
|
||||
public void TurnOn(Camera camera) => Console.WriteLine("Камера уже включена");
|
||||
}
|
||||
|
||||
class VideoState : ICameraState
|
||||
{
|
||||
public void RecordVideo(Camera camera) => Console.WriteLine("Камера уже в режиме видео");
|
||||
|
||||
public void TakePictures(Camera camera)
|
||||
{
|
||||
Console.WriteLine("Переходим в режим фото");
|
||||
camera.TakePictures(camera);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Выключить камеру
|
||||
/// </summary>
|
||||
/// <param name="camera">камера</param>
|
||||
public void TurnOff(Camera camera)
|
||||
{
|
||||
Console.WriteLine("Нажата кнопка выключения");
|
||||
camera.SetState(new OffState());
|
||||
}
|
||||
|
||||
public void TurnOn(Camera camera) => Console.WriteLine("Камера уже включена");
|
||||
}
|
||||
|
||||
class OnState : ICameraState
|
||||
{
|
||||
public void RecordVideo(Camera camera)
|
||||
{
|
||||
Console.WriteLine("Переходим в режим видео");
|
||||
camera.RecordVideo(camera);
|
||||
}
|
||||
|
||||
public void TakePictures(Camera camera)
|
||||
{
|
||||
Console.WriteLine("Переходим в режим фото");
|
||||
camera.TakePictures(camera);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Выключить камеру
|
||||
/// </summary>
|
||||
/// <param name="camera">камера</param>
|
||||
public void TurnOff(Camera camera)
|
||||
{
|
||||
Console.WriteLine("Нажата кнопка выключения");
|
||||
camera.SetState(new OffState());
|
||||
}
|
||||
|
||||
public void TurnOn(Camera camera) => Console.WriteLine("Камера уже включена");
|
||||
}
|
||||
|
||||
class OffState : ICameraState
|
||||
{
|
||||
public void RecordVideo(Camera camera) => Console.WriteLine("Камера ещё вылючена");
|
||||
public void TakePictures(Camera camera) => Console.WriteLine("Камера ещё вылючена");
|
||||
public void TurnOff(Camera camera) => Console.WriteLine("Камера уже вылючена");
|
||||
public void TurnOn(Camera camera)
|
||||
{
|
||||
Console.WriteLine("Нажата кнопка включения");
|
||||
camera.SetState(new OnState());
|
||||
}
|
||||
}
|
||||
|
||||
class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
Console.WriteLine("SimpleState.Something");
|
||||
var sv = new Variable();
|
||||
sv.True();
|
||||
Console.WriteLine(sv);
|
||||
sv.False(); Console.WriteLine(sv);
|
||||
sv.False(); Console.WriteLine(sv);
|
||||
sv.False(); Console.WriteLine(sv);
|
||||
sv.True(); Console.WriteLine(sv);
|
||||
}
|
||||
}
|
11
Patterns/Pattern_9-Цепочка обязанностей/Pattern_9-Цепочка обязанностей(ChainOfResponsobility).csproj
Normal file
11
Patterns/Pattern_9-Цепочка обязанностей/Pattern_9-Цепочка обязанностей(ChainOfResponsobility).csproj
Normal file
@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<RootNamespace>Pattern_9_Цепочка_обязанностей</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
289
Patterns/Pattern_9-Цепочка обязанностей/Program.cs
Normal file
289
Patterns/Pattern_9-Цепочка обязанностей/Program.cs
Normal file
@ -0,0 +1,289 @@
|
||||
/*
|
||||
* ПАТТЕРНЫ ПОВЕДЕНИЯ
|
||||
*
|
||||
* Глава_7_3: Цепочка обязанностей
|
||||
*
|
||||
* - позволяет избежать привязки отправителя запроса к его получателю,
|
||||
* давая шанс обработать запрос нескольким объектам
|
||||
*
|
||||
* - позволяет пробрасывать действия от одной компоненты к другой
|
||||
*/
|
||||
|
||||
class Roshan
|
||||
{
|
||||
public Roshan(int hp = 30) => Hp = hp;
|
||||
public int Hp { get; init; }
|
||||
}
|
||||
|
||||
interface IHero
|
||||
{
|
||||
int Hp { get; set; }
|
||||
Hero Next { get; set; }
|
||||
void MustWin(Roshan enemy);
|
||||
}
|
||||
|
||||
class Hero : IHero
|
||||
{
|
||||
public int Hp { get; set; }
|
||||
public Hero Next { get; set; }
|
||||
public string Name => GetType().Name;
|
||||
public Hero(int hp, Hero hero) { }
|
||||
public void MustWin(Roshan enemy)
|
||||
{
|
||||
if (Hp > enemy.Hp) { Console.WriteLine($"{Name} smog"); }
|
||||
else
|
||||
{
|
||||
if(Next != null)
|
||||
{
|
||||
Console.WriteLine($"{Name} ne smog. Poprobyet {Next.GetType().Name}");
|
||||
Next.MustWin(enemy);
|
||||
return;
|
||||
}
|
||||
Console.WriteLine($"{Name} ne smog. Brag pobedil.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Ursa : Hero
|
||||
{
|
||||
public Ursa(int hp = 50, Hero hero = null) : base(hp, hero) { }
|
||||
}
|
||||
|
||||
class Timbersaw : Hero
|
||||
{
|
||||
public Timbersaw(int hp = 70, Hero hero = null) : base(hp, hero) { }
|
||||
}
|
||||
|
||||
class Axe : Hero
|
||||
{
|
||||
public Axe(int hp = 110, Hero hero = null) : base(hp, hero) { }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Пример №2
|
||||
/// </summary>
|
||||
public class Heros
|
||||
{
|
||||
public string Name;
|
||||
public int Attack { get; set; }
|
||||
public int Armor { get; set; }
|
||||
|
||||
public Heros(string name, int attak, int armor)
|
||||
{
|
||||
Name = name;
|
||||
Attack = attak;
|
||||
Armor = armor;
|
||||
}
|
||||
|
||||
public override string ToString() => $"{Name}: [{Attack}, {Armor}]\n";
|
||||
}
|
||||
|
||||
public class Effect
|
||||
{
|
||||
protected Heros heros;
|
||||
protected Effect next;
|
||||
|
||||
public Effect(Heros heros) => this.heros = heros;
|
||||
public void Add(Effect effect)
|
||||
{
|
||||
if (next != null) next.Add(effect);
|
||||
else next = effect;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Выполнение действия
|
||||
/// </summary>
|
||||
public virtual void Handle() => next?.Handle();
|
||||
}
|
||||
|
||||
public class DoubleDamageRune : Effect
|
||||
{
|
||||
public DoubleDamageRune(Heros heros)
|
||||
: base(heros) { }
|
||||
|
||||
public override void Handle()
|
||||
{
|
||||
Console.WriteLine($"{heros.Name} активировал руну двойного урона");
|
||||
heros.Attack *= 2;
|
||||
base.Handle();
|
||||
}
|
||||
}
|
||||
|
||||
public class Halberd : Effect
|
||||
{
|
||||
public Halberd(Heros heros)
|
||||
: base(heros) { }
|
||||
|
||||
public override void Handle()
|
||||
{
|
||||
Console.WriteLine("Существо лишено сил, от чего оно не может атаковать");
|
||||
heros.Attack = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// К какому игровому персонажу какой эффект нужно применить
|
||||
/// * Самый сложный пример - с брокером событий
|
||||
/// </summary>
|
||||
public class Query
|
||||
{
|
||||
public string HeroName { get; set; }
|
||||
public GameEffect TypeEffect { get; set; }
|
||||
public Characteristic Args { get; set; }
|
||||
|
||||
public Query(string heroName, GameEffect typeEffect, Characteristic values)
|
||||
{
|
||||
HeroName = heroName;
|
||||
TypeEffect = typeEffect;
|
||||
Args = values;
|
||||
}
|
||||
}
|
||||
|
||||
public enum GameEffect
|
||||
{
|
||||
DubleDamageRunes = 1,
|
||||
ArmorBonus = 2,
|
||||
HalbertEffects = 3,
|
||||
ArcaneRune = 4
|
||||
}
|
||||
|
||||
public struct Characteristic
|
||||
{
|
||||
public int Attack { get; set; }
|
||||
public int Armor { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Брокер который отвечает за эффекты применяемые к персонажу
|
||||
/// </summary>
|
||||
public class Game
|
||||
{
|
||||
public event EventHandler<Query> Queries;
|
||||
public void CallQuery(object s, Query q) => Queries?.Invoke(s, q);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// В какой игре к какому персонажу применить какую характеристику
|
||||
/// </summary>
|
||||
public class Effects : IDisposable
|
||||
{
|
||||
protected Heross heross;
|
||||
protected Game game;
|
||||
public Effects(Heross heross, Game game)
|
||||
{
|
||||
this.heross = heross;
|
||||
this.game = game;
|
||||
game.Queries += Handlle;
|
||||
}
|
||||
|
||||
public virtual void Handlle(object sender, Query e) => Console.WriteLine("Basic Effect");
|
||||
public void Dispose() => game.Queries -= Handlle;
|
||||
}
|
||||
|
||||
public class DoubleDamageRunes : Effects
|
||||
{
|
||||
public DoubleDamageRunes(Heross heross, Game game) : base(heross, game) { }
|
||||
public override void Handlle(object sender, Query e)
|
||||
{
|
||||
if(e.HeroName == heross.Name
|
||||
&& e.TypeEffect == (GameEffect.DubleDamageRunes | GameEffect.HalbertEffects))
|
||||
{
|
||||
e.Args = new Characteristic
|
||||
{
|
||||
Armor = e.Args.Armor,
|
||||
Attack = 2 * e.Args.Attack
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Halberds : Effects
|
||||
{
|
||||
public Halberds(Heross heross, Game game) : base(heross, game) { }
|
||||
public override void Handlle(object sender, Query e)
|
||||
{
|
||||
if (e.HeroName == heross.Name
|
||||
&& e.TypeEffect == GameEffect.HalbertEffects)
|
||||
{
|
||||
e.Args = new Characteristic
|
||||
{
|
||||
Armor = 1000,
|
||||
Attack = 0
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Heross
|
||||
{
|
||||
private readonly Game game;
|
||||
public string Name;
|
||||
Characteristic characteristic;
|
||||
public int Attack
|
||||
{
|
||||
get
|
||||
{
|
||||
Query query = new (Name, GameEffect.DubleDamageRunes | GameEffect.ArmorBonus, characteristic);
|
||||
game.CallQuery(this, query);
|
||||
return query.Args.Attack;
|
||||
}
|
||||
}
|
||||
public int Armor
|
||||
{
|
||||
get
|
||||
{
|
||||
Query query = new (Name, GameEffect.DubleDamageRunes | GameEffect.ArmorBonus, characteristic);
|
||||
game.CallQuery(this, query);
|
||||
return query.Args.Armor;
|
||||
}
|
||||
}
|
||||
|
||||
public Heross(string name, int attack, int armor, Game game)
|
||||
{
|
||||
Console.WriteLine($"Создан герой {name}");
|
||||
Name = name;
|
||||
characteristic.Attack = attack;
|
||||
characteristic.Armor = armor;
|
||||
this.game = game;
|
||||
}
|
||||
|
||||
public override string ToString() => $"{Name} : [{Attack}, {Armor}]\n";
|
||||
}
|
||||
|
||||
|
||||
class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var enemy = new Roshan(109);
|
||||
|
||||
var ursa = new Ursa();
|
||||
var timber = new Timbersaw();
|
||||
var axe = new Axe();
|
||||
|
||||
ursa.Next = timber;
|
||||
timber.Next = axe;
|
||||
|
||||
ursa.MustWin(enemy);
|
||||
|
||||
var heros = new Heros("Queen Of Pain", armor: 4, attak: 80);
|
||||
Console.WriteLine(heros);
|
||||
|
||||
var game = new Effect(heros);
|
||||
game.Add(new DoubleDamageRune(heros)); game.Handle();
|
||||
Console.WriteLine(heros);
|
||||
|
||||
game.Add(new Halberd(heros)); game.Handle(); Console.WriteLine(heros);
|
||||
|
||||
var dota = new Game();
|
||||
var heross = new Heross("Queen Of Pain", attack: 80, armor: 4, dota);
|
||||
Console.WriteLine(heross);
|
||||
var dd = new DoubleDamageRunes(heross, dota);
|
||||
Console.WriteLine(heross);
|
||||
dd.Dispose(); Console.WriteLine(heross);
|
||||
var hb = new Halberds(heross, dota);
|
||||
Console.WriteLine(heross);
|
||||
hb.Dispose(); Console.WriteLine(heross);
|
||||
}
|
||||
}
|
146
Patterns/PatternsExtra.sln
Normal file
146
Patterns/PatternsExtra.sln
Normal file
@ -0,0 +1,146 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.1.32210.238
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pattern_1-Стратегия(Strategy)", "Pattern_1-Стратегия\Pattern_1-Стратегия(Strategy).csproj", "{9976C22F-4293-40CE-8E2E-F6C56D096164}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pattern_3-Фабричный метод", "Pattern_2-Шаблонный метод\Pattern_3-Фабричный метод.csproj", "{BC45C9FC-E037-4066-B3EB-A5EA98D4E7BF}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pattern_3-Посредник(Mediator)", "Pattern_3-Посредник(Mediator)\Pattern_3-Посредник(Mediator).csproj", "{F2E4BD9E-E31E-4C5B-A7BA-6D14B4332388}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pattern_4-Итератор(Iterator)", "Pattern_4-Итератор(Iterator)\Pattern_4-Итератор(Iterator).csproj", "{2A2134F4-9496-49A3-9F94-79EBC25F8E03}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pattern_5-Наблюдатель(Observer)", "Pattern_5-Наблюдатель(Observer)\Pattern_5-Наблюдатель(Observer).csproj", "{71D4783A-71C3-4E88-9F18-D75A8D347824}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pattern_6-Посетитель(Visitor)", "Pattern_6-Посетитель(Visitor)\Pattern_6-Посетитель(Visitor).csproj", "{6CF1383D-B4F4-485E-B294-827F919F28FA}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pattern_7-Команда(Command)", "Pattern_7-Команда\Pattern_7-Команда(Command).csproj", "{988AD18B-096A-4F25-947F-07B4A68497D0}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pattern_8-Состояние(State)", "Pattern_8-Состояние\Pattern_8-Состояние(State).csproj", "{BB702708-54E5-4831-8B3A-30B92B226DAE}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pattern_9-Цепочка обязанностей(ChainOfResponsobility)", "Pattern_9-Цепочка обязанностей\Pattern_9-Цепочка обязанностей(ChainOfResponsobility).csproj", "{F8109BBB-C1B9-44CC-982B-AE13ADF27E13}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Паттерны поведения", "Паттерны поведения", "{81D10339-197A-4101-B195-6866DE85ED80}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Порождающие паттерны", "Порождающие паттерны", "{772B724B-1643-417A-BC3B-F732C739F628}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pattern_1-Синглтон(Singleton)", "Pattern_1-Синглтон(Singleton)\Pattern_1-Синглтон(Singleton).csproj", "{55927094-11C3-4F21-94AF-58A831A9A550}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pattern_2-Абстрактная фабрика(Abstract Factory)", "Pattern_2-Абстрактная фабрика(Abstract Factory)\Pattern_2-Абстрактная фабрика(Abstract Factory).csproj", "{9BB70525-29BD-43BB-9F32-D2E3387CFE92}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pattern_4-Строитель(Builder)", "Pattern_3-Строитель(Builder)\Pattern_4-Строитель(Builder).csproj", "{A2498812-2B35-4EAA-B8DD-1E2860BEA995}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Структурные паттерны", "Структурные паттерны", "{CFD4A239-FAAB-4C2B-A55C-1051E994069A}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pattern_1-Адаптер(Adapter)", "Pattern_1-Адаптер(Adapter)\Pattern_1-Адаптер(Adapter).csproj", "{5DEAE4CF-D089-42C5-9FCF-2D3C4B7AB385}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pattern_2-Фасад(Facade)", "Pattern_2-Фасад(Facade)\Pattern_2-Фасад(Facade).csproj", "{B00B3EA6-B1E0-48E0-A42A-FE52C73BDAB3}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pattern_3-Декоратор(Decorator)", "Pattern_3-Декоратор(Decorator)\Pattern_3-Декоратор(Decorator).csproj", "{0234C795-F6EB-4CF0-BCC0-B4B97C789B12}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pattern_4-Компоновщик(Composite)", "Pattern_4-Компоновщик(Composite)\Pattern_4-Компоновщик(Composite).csproj", "{0B5DCEE7-F54E-49AB-A63F-DFE0CBFF6AC9}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pattern_5-Заместитель(Proxy)", "Pattern_5-Заместитель(Proxy)\Pattern_5-Заместитель(Proxy).csproj", "{8288DD61-F2B0-4B95-B8CE-04E920B8CAD0}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{9976C22F-4293-40CE-8E2E-F6C56D096164}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9976C22F-4293-40CE-8E2E-F6C56D096164}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9976C22F-4293-40CE-8E2E-F6C56D096164}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9976C22F-4293-40CE-8E2E-F6C56D096164}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BC45C9FC-E037-4066-B3EB-A5EA98D4E7BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BC45C9FC-E037-4066-B3EB-A5EA98D4E7BF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BC45C9FC-E037-4066-B3EB-A5EA98D4E7BF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BC45C9FC-E037-4066-B3EB-A5EA98D4E7BF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F2E4BD9E-E31E-4C5B-A7BA-6D14B4332388}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F2E4BD9E-E31E-4C5B-A7BA-6D14B4332388}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F2E4BD9E-E31E-4C5B-A7BA-6D14B4332388}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F2E4BD9E-E31E-4C5B-A7BA-6D14B4332388}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2A2134F4-9496-49A3-9F94-79EBC25F8E03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2A2134F4-9496-49A3-9F94-79EBC25F8E03}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2A2134F4-9496-49A3-9F94-79EBC25F8E03}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2A2134F4-9496-49A3-9F94-79EBC25F8E03}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{71D4783A-71C3-4E88-9F18-D75A8D347824}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{71D4783A-71C3-4E88-9F18-D75A8D347824}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{71D4783A-71C3-4E88-9F18-D75A8D347824}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{71D4783A-71C3-4E88-9F18-D75A8D347824}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6CF1383D-B4F4-485E-B294-827F919F28FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6CF1383D-B4F4-485E-B294-827F919F28FA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6CF1383D-B4F4-485E-B294-827F919F28FA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6CF1383D-B4F4-485E-B294-827F919F28FA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{988AD18B-096A-4F25-947F-07B4A68497D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{988AD18B-096A-4F25-947F-07B4A68497D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{988AD18B-096A-4F25-947F-07B4A68497D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{988AD18B-096A-4F25-947F-07B4A68497D0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BB702708-54E5-4831-8B3A-30B92B226DAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BB702708-54E5-4831-8B3A-30B92B226DAE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BB702708-54E5-4831-8B3A-30B92B226DAE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BB702708-54E5-4831-8B3A-30B92B226DAE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F8109BBB-C1B9-44CC-982B-AE13ADF27E13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F8109BBB-C1B9-44CC-982B-AE13ADF27E13}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F8109BBB-C1B9-44CC-982B-AE13ADF27E13}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F8109BBB-C1B9-44CC-982B-AE13ADF27E13}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{55927094-11C3-4F21-94AF-58A831A9A550}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{55927094-11C3-4F21-94AF-58A831A9A550}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{55927094-11C3-4F21-94AF-58A831A9A550}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{55927094-11C3-4F21-94AF-58A831A9A550}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9BB70525-29BD-43BB-9F32-D2E3387CFE92}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9BB70525-29BD-43BB-9F32-D2E3387CFE92}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9BB70525-29BD-43BB-9F32-D2E3387CFE92}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9BB70525-29BD-43BB-9F32-D2E3387CFE92}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A2498812-2B35-4EAA-B8DD-1E2860BEA995}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A2498812-2B35-4EAA-B8DD-1E2860BEA995}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A2498812-2B35-4EAA-B8DD-1E2860BEA995}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A2498812-2B35-4EAA-B8DD-1E2860BEA995}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5DEAE4CF-D089-42C5-9FCF-2D3C4B7AB385}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5DEAE4CF-D089-42C5-9FCF-2D3C4B7AB385}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5DEAE4CF-D089-42C5-9FCF-2D3C4B7AB385}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5DEAE4CF-D089-42C5-9FCF-2D3C4B7AB385}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B00B3EA6-B1E0-48E0-A42A-FE52C73BDAB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B00B3EA6-B1E0-48E0-A42A-FE52C73BDAB3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B00B3EA6-B1E0-48E0-A42A-FE52C73BDAB3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B00B3EA6-B1E0-48E0-A42A-FE52C73BDAB3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0234C795-F6EB-4CF0-BCC0-B4B97C789B12}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0234C795-F6EB-4CF0-BCC0-B4B97C789B12}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0234C795-F6EB-4CF0-BCC0-B4B97C789B12}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0234C795-F6EB-4CF0-BCC0-B4B97C789B12}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0B5DCEE7-F54E-49AB-A63F-DFE0CBFF6AC9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0B5DCEE7-F54E-49AB-A63F-DFE0CBFF6AC9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0B5DCEE7-F54E-49AB-A63F-DFE0CBFF6AC9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0B5DCEE7-F54E-49AB-A63F-DFE0CBFF6AC9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8288DD61-F2B0-4B95-B8CE-04E920B8CAD0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8288DD61-F2B0-4B95-B8CE-04E920B8CAD0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8288DD61-F2B0-4B95-B8CE-04E920B8CAD0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8288DD61-F2B0-4B95-B8CE-04E920B8CAD0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{9976C22F-4293-40CE-8E2E-F6C56D096164} = {81D10339-197A-4101-B195-6866DE85ED80}
|
||||
{BC45C9FC-E037-4066-B3EB-A5EA98D4E7BF} = {772B724B-1643-417A-BC3B-F732C739F628}
|
||||
{F2E4BD9E-E31E-4C5B-A7BA-6D14B4332388} = {81D10339-197A-4101-B195-6866DE85ED80}
|
||||
{2A2134F4-9496-49A3-9F94-79EBC25F8E03} = {81D10339-197A-4101-B195-6866DE85ED80}
|
||||
{71D4783A-71C3-4E88-9F18-D75A8D347824} = {81D10339-197A-4101-B195-6866DE85ED80}
|
||||
{6CF1383D-B4F4-485E-B294-827F919F28FA} = {81D10339-197A-4101-B195-6866DE85ED80}
|
||||
{988AD18B-096A-4F25-947F-07B4A68497D0} = {81D10339-197A-4101-B195-6866DE85ED80}
|
||||
{BB702708-54E5-4831-8B3A-30B92B226DAE} = {81D10339-197A-4101-B195-6866DE85ED80}
|
||||
{F8109BBB-C1B9-44CC-982B-AE13ADF27E13} = {81D10339-197A-4101-B195-6866DE85ED80}
|
||||
{55927094-11C3-4F21-94AF-58A831A9A550} = {772B724B-1643-417A-BC3B-F732C739F628}
|
||||
{9BB70525-29BD-43BB-9F32-D2E3387CFE92} = {772B724B-1643-417A-BC3B-F732C739F628}
|
||||
{A2498812-2B35-4EAA-B8DD-1E2860BEA995} = {772B724B-1643-417A-BC3B-F732C739F628}
|
||||
{5DEAE4CF-D089-42C5-9FCF-2D3C4B7AB385} = {CFD4A239-FAAB-4C2B-A55C-1051E994069A}
|
||||
{B00B3EA6-B1E0-48E0-A42A-FE52C73BDAB3} = {CFD4A239-FAAB-4C2B-A55C-1051E994069A}
|
||||
{0234C795-F6EB-4CF0-BCC0-B4B97C789B12} = {CFD4A239-FAAB-4C2B-A55C-1051E994069A}
|
||||
{0B5DCEE7-F54E-49AB-A63F-DFE0CBFF6AC9} = {CFD4A239-FAAB-4C2B-A55C-1051E994069A}
|
||||
{8288DD61-F2B0-4B95-B8CE-04E920B8CAD0} = {CFD4A239-FAAB-4C2B-A55C-1051E994069A}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {7EAC518E-F875-4F24-AB38-B1F72CB23C93}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
17
README.md
Normal file
17
README.md
Normal file
@ -0,0 +1,17 @@
|
||||
<p align="center">
|
||||
<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>
|
||||
|
||||
# C# паттерны - дополнение 📚
|
||||
|
||||
**Создано в качестве дополнения к 🌟 [моему существующему репозиторию](https://github.com/Dvurechensky/Patterns-Programming)** 🌟
|
||||
|
||||
Содержит: **паттерны** и [примеры создания сниппетов](Patterns/Pattern_1-Синглтон(Singleton)/MySnippet.snippet)
|
||||
|
||||
Данная информация по C# проработанна мной с плейлиста грамотного человека 👊 [Сергея Камянецкого](https://www.youtube.com/playlist?list=PLsV7KW4r_oBAxqpJ0IyfJw16GBZXJvLKg) 👊
|
Loading…
Reference in New Issue
Block a user