From 3a28caed27ed57654133dfdecedf3f2c4bf7341b Mon Sep 17 00:00:00 2001 From: Dvurechensky <46356631+Dvurechensky@users.noreply.github.com> Date: Sat, 5 Oct 2024 09:15:54 +0300 Subject: [PATCH] 1.0 Main --- .gitattributes | 63 +++ .gitignore | 3 + LICENSE | 121 ++++++ .../1_Принцип единственной обязанности.csproj | 11 + .../Program.cs | 71 +++ .../2_Принцип открытости, закрытости.csproj | 11 + .../Program.cs | 55 +++ .../3_Принцип подстановки Барбары Лисков.csproj | 11 + .../Program.cs | 127 ++++++ .../4_Принцип разделения интерфейсов.csproj | 11 + .../Program.cs | 48 ++ .../5_Принцип инверсии зависимостей.csproj | 11 + .../Program.cs | 107 +++++ .../AbstractFactory/AbstractFactory.csproj | 10 + Patterns/AbstractFactory/Program.cs | 148 +++++++ Patterns/Adapter/Adapter.csproj | 10 + Patterns/Adapter/Program.cs | 78 ++++ .../Base.UserLibrary.Tests.csproj | 19 + Patterns/Base.UserLibrary.Tests/TestData.xml | 6 + Patterns/Base.UserLibrary.Tests/UnitTest1.cs | 31 ++ Patterns/Base.UserLibrary.Tests/Usings.cs | 1 + Patterns/Base.cs | 28 ++ Patterns/Base/AssertMsTest.cs | 26 ++ Patterns/Base/BaseInfo.csproj | 14 + Patterns/Base/Extension.cs | 17 + Patterns/Base/Program.cs | 410 ++++++++++++++++++ Patterns/BaseTests/000_TestsMain.cs | 31 ++ Patterns/BaseTests/001_TestInitAndCleanUp.cs | 38 ++ Patterns/BaseTests/002_ClassInitAndCleanUp.cs | 41 ++ Patterns/BaseTests/003_AssemblyInit.cs | 26 ++ Patterns/BaseTests/004_AssertMethods.cs | 65 +++ .../BaseTests/005_CollectionAssertMethods.cs | 65 +++ Patterns/BaseTests/006_StringAssetMethods.cs | 44 ++ Patterns/BaseTests/007_ExpectingExceptions.cs | 27 ++ Patterns/BaseTests/Base.Tests.csproj | 22 + Patterns/BaseTests/Usings.cs | 1 + Patterns/Bridge/Bridge.csproj | 10 + Patterns/Bridge/Program.cs | 96 ++++ Patterns/Builder/Builder.csproj | 10 + Patterns/Builder/Program.cs | 120 +++++ .../ChainOfResponsibility.csproj | 10 + Patterns/ChainOfResponsibility/Program.cs | 165 +++++++ Patterns/Command/Command.csproj | 10 + Patterns/Command/Program.cs | 225 ++++++++++ Patterns/Composite/Composite.csproj | 10 + Patterns/Composite/Program.cs | 129 ++++++ Patterns/Decorator/Decorator.csproj | 10 + Patterns/Decorator/Program.cs | 62 +++ Patterns/Dict/DictionaryInfo.csproj | 10 + Patterns/Dict/Program.cs | 116 +++++ Patterns/Facade/Facade.csproj | 10 + Patterns/Facade/Program.cs | 55 +++ Patterns/FactoryMethod/FactoryMethod.csproj | 10 + Patterns/FactoryMethod/Program.cs | 120 +++++ Patterns/FluentBuilder/FluentBuilder.csproj | 10 + Patterns/FluentBuilder/Program.cs | 68 +++ Patterns/Flyweight/Flyweight.csproj | 10 + Patterns/Flyweight/Program.cs | 97 +++++ Patterns/Interpreter/Interpreter.csproj | 10 + Patterns/Interpreter/Program.cs | 148 +++++++ Patterns/Iterator/Iterator.csproj | 10 + Patterns/Iterator/Program.cs | 263 +++++++++++ Patterns/LetCode.Tests/LetCode.Tests.csproj | 23 + Patterns/LetCode.Tests/Tests.cs | 65 +++ Patterns/LetCode.Tests/Usings.cs | 1 + Patterns/LetCode/LetCode.csproj | 10 + Patterns/LetCode/Program.cs | 160 +++++++ Patterns/Mediator/Mediator.csproj | 10 + Patterns/Mediator/Program.cs | 112 +++++ Patterns/Memento/Memento.csproj | 10 + Patterns/Memento/Program.cs | 119 +++++ Patterns/Observer/Observer.csproj | 10 + Patterns/Observer/Program.cs | 103 +++++ Patterns/Patterns Programming.sln | 269 ++++++++++++ Patterns/Prototype/Program.cs | 132 ++++++ Patterns/Prototype/Prototype.csproj | 10 + Patterns/Proxy/Program.cs | 94 ++++ Patterns/Proxy/Proxy.csproj | 14 + Patterns/Singleton/Program.cs | 44 ++ Patterns/Singleton/Singleton.csproj | 10 + Patterns/State/Program.cs | 76 ++++ Patterns/State/State.csproj | 10 + Patterns/Strategy/ILogReader.cs | 6 + Patterns/Strategy/LogEntry.cs | 15 + Patterns/Strategy/LogFileReader.cs | 17 + Patterns/Strategy/LogProcessor.cs | 21 + Patterns/Strategy/Program.cs | 218 ++++++++++ Patterns/Strategy/Strategy.csproj | 10 + Patterns/Strategy/WindowsEventLogReader.cs | 17 + Patterns/TemplateMethod/Program.cs | 115 +++++ Patterns/TemplateMethod/TemplateMethod.csproj | 10 + Patterns/Visitor/Program.cs | 138 ++++++ Patterns/Visitor/Visitor.csproj | 10 + README.md | 156 +++++++ 94 files changed, 5617 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 Patterns/1_Принцип единственной обязанности/1_Принцип единственной обязанности.csproj create mode 100644 Patterns/1_Принцип единственной обязанности/Program.cs create mode 100644 Patterns/2_Принцип открытости, закрытости/2_Принцип открытости, закрытости.csproj create mode 100644 Patterns/2_Принцип открытости, закрытости/Program.cs create mode 100644 Patterns/3_Принцип подстановки Барбары Лисков/3_Принцип подстановки Барбары Лисков.csproj create mode 100644 Patterns/3_Принцип подстановки Барбары Лисков/Program.cs create mode 100644 Patterns/4_Принцип разделения интерфейсов/4_Принцип разделения интерфейсов.csproj create mode 100644 Patterns/4_Принцип разделения интерфейсов/Program.cs create mode 100644 Patterns/5_Принцип инверсии зависимостей/5_Принцип инверсии зависимостей.csproj create mode 100644 Patterns/5_Принцип инверсии зависимостей/Program.cs create mode 100644 Patterns/AbstractFactory/AbstractFactory.csproj create mode 100644 Patterns/AbstractFactory/Program.cs create mode 100644 Patterns/Adapter/Adapter.csproj create mode 100644 Patterns/Adapter/Program.cs create mode 100644 Patterns/Base.UserLibrary.Tests/Base.UserLibrary.Tests.csproj create mode 100644 Patterns/Base.UserLibrary.Tests/TestData.xml create mode 100644 Patterns/Base.UserLibrary.Tests/UnitTest1.cs create mode 100644 Patterns/Base.UserLibrary.Tests/Usings.cs create mode 100644 Patterns/Base.cs create mode 100644 Patterns/Base/AssertMsTest.cs create mode 100644 Patterns/Base/BaseInfo.csproj create mode 100644 Patterns/Base/Extension.cs create mode 100644 Patterns/Base/Program.cs create mode 100644 Patterns/BaseTests/000_TestsMain.cs create mode 100644 Patterns/BaseTests/001_TestInitAndCleanUp.cs create mode 100644 Patterns/BaseTests/002_ClassInitAndCleanUp.cs create mode 100644 Patterns/BaseTests/003_AssemblyInit.cs create mode 100644 Patterns/BaseTests/004_AssertMethods.cs create mode 100644 Patterns/BaseTests/005_CollectionAssertMethods.cs create mode 100644 Patterns/BaseTests/006_StringAssetMethods.cs create mode 100644 Patterns/BaseTests/007_ExpectingExceptions.cs create mode 100644 Patterns/BaseTests/Base.Tests.csproj create mode 100644 Patterns/BaseTests/Usings.cs create mode 100644 Patterns/Bridge/Bridge.csproj create mode 100644 Patterns/Bridge/Program.cs create mode 100644 Patterns/Builder/Builder.csproj create mode 100644 Patterns/Builder/Program.cs create mode 100644 Patterns/ChainOfResponsibility/ChainOfResponsibility.csproj create mode 100644 Patterns/ChainOfResponsibility/Program.cs create mode 100644 Patterns/Command/Command.csproj create mode 100644 Patterns/Command/Program.cs create mode 100644 Patterns/Composite/Composite.csproj create mode 100644 Patterns/Composite/Program.cs create mode 100644 Patterns/Decorator/Decorator.csproj create mode 100644 Patterns/Decorator/Program.cs create mode 100644 Patterns/Dict/DictionaryInfo.csproj create mode 100644 Patterns/Dict/Program.cs create mode 100644 Patterns/Facade/Facade.csproj create mode 100644 Patterns/Facade/Program.cs create mode 100644 Patterns/FactoryMethod/FactoryMethod.csproj create mode 100644 Patterns/FactoryMethod/Program.cs create mode 100644 Patterns/FluentBuilder/FluentBuilder.csproj create mode 100644 Patterns/FluentBuilder/Program.cs create mode 100644 Patterns/Flyweight/Flyweight.csproj create mode 100644 Patterns/Flyweight/Program.cs create mode 100644 Patterns/Interpreter/Interpreter.csproj create mode 100644 Patterns/Interpreter/Program.cs create mode 100644 Patterns/Iterator/Iterator.csproj create mode 100644 Patterns/Iterator/Program.cs create mode 100644 Patterns/LetCode.Tests/LetCode.Tests.csproj create mode 100644 Patterns/LetCode.Tests/Tests.cs create mode 100644 Patterns/LetCode.Tests/Usings.cs create mode 100644 Patterns/LetCode/LetCode.csproj create mode 100644 Patterns/LetCode/Program.cs create mode 100644 Patterns/Mediator/Mediator.csproj create mode 100644 Patterns/Mediator/Program.cs create mode 100644 Patterns/Memento/Memento.csproj create mode 100644 Patterns/Memento/Program.cs create mode 100644 Patterns/Observer/Observer.csproj create mode 100644 Patterns/Observer/Program.cs create mode 100644 Patterns/Patterns Programming.sln create mode 100644 Patterns/Prototype/Program.cs create mode 100644 Patterns/Prototype/Prototype.csproj create mode 100644 Patterns/Proxy/Program.cs create mode 100644 Patterns/Proxy/Proxy.csproj create mode 100644 Patterns/Singleton/Program.cs create mode 100644 Patterns/Singleton/Singleton.csproj create mode 100644 Patterns/State/Program.cs create mode 100644 Patterns/State/State.csproj create mode 100644 Patterns/Strategy/ILogReader.cs create mode 100644 Patterns/Strategy/LogEntry.cs create mode 100644 Patterns/Strategy/LogFileReader.cs create mode 100644 Patterns/Strategy/LogProcessor.cs create mode 100644 Patterns/Strategy/Program.cs create mode 100644 Patterns/Strategy/Strategy.csproj create mode 100644 Patterns/Strategy/WindowsEventLogReader.cs create mode 100644 Patterns/TemplateMethod/Program.cs create mode 100644 Patterns/TemplateMethod/TemplateMethod.csproj create mode 100644 Patterns/Visitor/Program.cs create mode 100644 Patterns/Visitor/Visitor.csproj create mode 100644 README.md diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c8b1dde --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.vs +Patterns/bin +Patterns/obj \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0e259d4 --- /dev/null +++ b/LICENSE @@ -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. diff --git a/Patterns/1_Принцип единственной обязанности/1_Принцип единственной обязанности.csproj b/Patterns/1_Принцип единственной обязанности/1_Принцип единственной обязанности.csproj new file mode 100644 index 0000000..af348a6 --- /dev/null +++ b/Patterns/1_Принцип единственной обязанности/1_Принцип единственной обязанности.csproj @@ -0,0 +1,11 @@ + + + + Exe + net6.0 + _1_Принцип_единственной_обязанности + enable + enable + + + diff --git a/Patterns/1_Принцип единственной обязанности/Program.cs b/Patterns/1_Принцип единственной обязанности/Program.cs new file mode 100644 index 0000000..5d3351f --- /dev/null +++ b/Patterns/1_Принцип единственной обязанности/Program.cs @@ -0,0 +1,71 @@ +/* + * Глава 17: Принцип единственной обязанности (SOLID SRP) + * + * - инкапсуляция сущности с целью организации архитектуры + * приложения, которую будет легко поддерживать и расширять в + * течении всего промежутка эксплуатации + * + * Автор: Роберт Мартин (Дядя Боб) + * + * Принципы: + * 1. Single responsibility - принцип единственной ответственности + * 2. Open-closed - принцип открытости/закрытости + * 3. Liskov substitution - принцип подстановки Барбары Лисков (самый сложный) + * 4. Interface Segregation - принцип разделения интерфейса + * 5. Dependency inversion - принцип инверсии зависисмостей + */ + + +/* + * Принцип единственной ответственности (англ. single-responsibility principle, SPR) - + * принцип ООП, обозначающий, что каждый объект должен иметь одну ответственность и эта + * ответственность должна быть полностью инкапсулирована в класс. + * Все его поведения должны быть направлены исключительно на обеспечение этой отвественности. + */ +/// +/// К примеру: Разработать класс который будет работать с изображениями +/// +abstract class Attach +{ + +} + +class Image : Attach +{ + private int width; + private int height; + public int Width => width; + public int Height => height; + private Image(int width, int height) { } + //Добавление других методов предполагающих иной функционал не рационально + //Следуем принципу - декомпозировать - делать максимально минимальные классы под свою ответственность + public static Image CreateImage(int width, int height) { return new Image(width, height); } +} + +/// +/// EMail сервис +/// Если отваливается модуль отправки Email +/// мы чиним только его, нам не требуется разбирать класс Image +/// +class EmailService +{ + private string email; + private string text; + private string subject; + private Attach[] attach; + public EmailService(string email, + string text = "", + string subject = "", + params Attach[] args) + { } + public void SendTo(string email, string text, string subject) { } +} + + +class Program +{ + public static void Main(string[] argv) + { + + } +} \ No newline at end of file diff --git a/Patterns/2_Принцип открытости, закрытости/2_Принцип открытости, закрытости.csproj b/Patterns/2_Принцип открытости, закрытости/2_Принцип открытости, закрытости.csproj new file mode 100644 index 0000000..88bb7f1 --- /dev/null +++ b/Patterns/2_Принцип открытости, закрытости/2_Принцип открытости, закрытости.csproj @@ -0,0 +1,11 @@ + + + + Exe + net6.0 + _2_Принцип_открытости__закрытости + enable + enable + + + diff --git a/Patterns/2_Принцип открытости, закрытости/Program.cs b/Patterns/2_Принцип открытости, закрытости/Program.cs new file mode 100644 index 0000000..2473e68 --- /dev/null +++ b/Patterns/2_Принцип открытости, закрытости/Program.cs @@ -0,0 +1,55 @@ +/* + * Глава 18: Принцип открытости/закрытости (SOLID SRP) + * + * Автор: Роберт Мартин (Дядя Боб) + * + * Постулаты: + * - если какая-то сущность описана, то она уже + * полностью закрыта для каких либо изменений; + * - сущность открыта для модификаций; + * + * Принципы: + * 1. Single responsibility - принцип единственной ответственности + * 2. Open-closed - принцип открытости/закрытости + * 3. Liskov substitution - принцип подстановки Барбары Лисков (самый сложный) + * 4. Interface Segregation - принцип разделения интерфейса + * 5. Dependency inversion - принцип инверсии зависисмостей + */ +public abstract class Attach +{ + +} + +public class Image : Attach +{ + private int width; + private int height; + public int Width => width; + public int Height => height; + private Image(int width, int height) { } + private Image(int width, int height, ISave save) { } + public static Image CreateImage(int width, int height) { return new Image(width, height); } + public static Image CreateImage(int width, int height, ISave save) { return new Image(width, height, save); } + public void SaveToFile(string path) { } +} + +public interface ISave +{ + ISave SaveTo(string path); +} + +public class SaveToBmp : ISave +{ + public ISave SaveTo(string path) + { + return this; + } +} + +public class Program +{ + public static void Main(string[] argv) + { + Image.CreateImage(100, 100, new SaveToBmp().SaveTo("")); + } +} \ No newline at end of file diff --git a/Patterns/3_Принцип подстановки Барбары Лисков/3_Принцип подстановки Барбары Лисков.csproj b/Patterns/3_Принцип подстановки Барбары Лисков/3_Принцип подстановки Барбары Лисков.csproj new file mode 100644 index 0000000..38b1041 --- /dev/null +++ b/Patterns/3_Принцип подстановки Барбары Лисков/3_Принцип подстановки Барбары Лисков.csproj @@ -0,0 +1,11 @@ + + + + Exe + net6.0 + _3_Принцип_подстановки_Барбары_Лисков + enable + enable + + + diff --git a/Patterns/3_Принцип подстановки Барбары Лисков/Program.cs b/Patterns/3_Принцип подстановки Барбары Лисков/Program.cs new file mode 100644 index 0000000..dc4c4b3 --- /dev/null +++ b/Patterns/3_Принцип подстановки Барбары Лисков/Program.cs @@ -0,0 +1,127 @@ +/* + * Глава 19: Принцип подстановки Барбары Лисков (SOLID SRP) + * + * Автор: Роберт Мартин (Дядя Боб) + * + * Сам принцип: + * - Пусть Q(x) является свойством, верным относительно объектов x некоторого + * типа T. Тогда Q(y) также должно быть верным для объектов y типа S, где S является подтипом T. + * + * или + * + * - Функции, которые используют базовый тип, должны иметь возможность использовать подтипы базового типа, не зная об этом. + * Поведение классов-наследников не должно противоречить поведению, заданному базовым классом + * + * Принципы: + * 1. Single responsibility - принцип единственной ответственности + * 2. Open-closed - принцип открытости/закрытости + * 3. Liskov substitution - принцип подстановки Барбары Лисков (самый сложный) + * 4. Interface Segregation - принцип разделения интерфейса + * 5. Dependency inversion - принцип инверсии зависисмостей + */ + +public class Coordinates +{ + public int Longtitude { get; set; } + public int Latitude { get; set; } + public override string ToString() + { + return $"Широта: {Longtitude} Долгота: {Latitude}"; + } +} + +/// +/// Шаблон летающей птицы +/// +public class Bird +{ + protected Random rand; + public Coordinates Position { get; set; } + protected int speed, spacing; + public int Spacing { get => spacing; } + + public Bird() + { + Position = new Coordinates(); + rand = new Random(); + } + + protected void Mark(int x, int y) { } + + /// + /// Полёт птицы + /// + private void Fly() + { + speed = 1; + switch (rand.Next(2)) + { + case 0: Position.Latitude += speed; break; + default: Position.Longtitude += speed; break; + } + spacing++; + Console.SetCursorPosition(Position.Latitude, Position.Longtitude); + Console.WriteLine("B"); + } + + /// + /// Движение птицы + /// + public virtual void Move() + { + Fly(); + } +} + +/// +/// Шаблон бегущей птицы +/// +public class Kiwi : Bird +{ + private void Run() + { + speed = 1; + switch (rand.Next(2, 6)) + { + case 3: Position.Latitude += speed; break; + default: Position.Longtitude += speed; break; + } + spacing++; + Console.SetCursorPosition(Position.Latitude, Position.Longtitude); + Console.WriteLine("K"); + } + + public override void Move() + { + Run(); + } +} + +/// +/// Шаблон отображеня движения +/// +class CalculatingDistance +{ + private int time; + public CalculatingDistance(int time) { this.time = time; } + public void Calculate(Bird bird) + { + for (int i = 0; i < time; i++) + { + bird.Move(); + } + Console.Title = ($"\n\n\nРасстояние: {bird.Spacing} {bird.Position}"); + } +} + +public class Program +{ + public static void Main(string[] argv) + { + var bird = new Bird(); + new CalculatingDistance(10).Calculate(bird); + var kiwi = new Kiwi(); + new CalculatingDistance(10).Calculate(kiwi); + Console.ReadLine(); + } +} \ No newline at end of file diff --git a/Patterns/4_Принцип разделения интерфейсов/4_Принцип разделения интерфейсов.csproj b/Patterns/4_Принцип разделения интерфейсов/4_Принцип разделения интерфейсов.csproj new file mode 100644 index 0000000..b76962e --- /dev/null +++ b/Patterns/4_Принцип разделения интерфейсов/4_Принцип разделения интерфейсов.csproj @@ -0,0 +1,11 @@ + + + + Exe + net6.0 + _4_Принцип_разделения_интерфейсов + enable + enable + + + diff --git a/Patterns/4_Принцип разделения интерфейсов/Program.cs b/Patterns/4_Принцип разделения интерфейсов/Program.cs new file mode 100644 index 0000000..5197c56 --- /dev/null +++ b/Patterns/4_Принцип разделения интерфейсов/Program.cs @@ -0,0 +1,48 @@ +/* + * Глава 20: Принцип разделения интерфейсов (SOLID SRP) + * + * Автор: Роберт Мартин (Дядя Боб) + * + * Сам принцип: + * - клиенты не должны зависеть от методов которые они не используют + * + * или + * + * - если какая-то сущность заявляет о своем функционале, то он должен работать + * + * или + * + * - от реализации исбыточных интерфейсов следует отказаться в пользу специфичных + * + * Принципы: + * 1. Single responsibility - принцип единственной ответственности + * 2. Open-closed - принцип открытости/закрытости + * 3. Liskov substitution - принцип подстановки Барбары Лисков (самый сложный) + * 4. Interface Segregation - принцип разделения интерфейса + * 5. Dependency inversion - принцип инверсии зависисмостей + */ +public abstract class Car +{ + public string Model { get; set; } + public string Brand { get; set; } + + public Car(string model, string name) + { + Model = model; + Brand = name; + } +} + +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +//!!! вместо огромного набора функций в одном интерфейсе !!! +//!!! в случае если при наследовании от него множество функций не реализуется !!! +//!!! нужно перейти в сторону множественного наследования интерфейсов под каждую из функций !!! +//!!! или под каждый набор функций !!! +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +public class Program +{ + public static void Main(string[] argv) + { + + } +} \ No newline at end of file diff --git a/Patterns/5_Принцип инверсии зависимостей/5_Принцип инверсии зависимостей.csproj b/Patterns/5_Принцип инверсии зависимостей/5_Принцип инверсии зависимостей.csproj new file mode 100644 index 0000000..a1b8871 --- /dev/null +++ b/Patterns/5_Принцип инверсии зависимостей/5_Принцип инверсии зависимостей.csproj @@ -0,0 +1,11 @@ + + + + Exe + net6.0 + _5_Принцип_инверсии_зависимостей + enable + enable + + + diff --git a/Patterns/5_Принцип инверсии зависимостей/Program.cs b/Patterns/5_Принцип инверсии зависимостей/Program.cs new file mode 100644 index 0000000..637bb36 --- /dev/null +++ b/Patterns/5_Принцип инверсии зависимостей/Program.cs @@ -0,0 +1,107 @@ +/* + * Глава 21: Принцип инверсии зависимостей (SOLID SRP) + * + * Автор: Роберт Мартин (Дядя Боб) + * + * Сам принцип: + * + * - Модули верхних уровней не должны зависеть от модулей нижних уровней + * (Оба типа должны зависеть от абстракций) + * + * - Абстракции не должны зависеть от деталей + * (Детали должны зависеть от абстракций) + * + * Принципы: + * 1. Single responsibility - принцип единственной ответственности + * 2. Open-closed - принцип открытости/закрытости + * 3. Liskov substitution - принцип подстановки Барбары Лисков (самый сложный) + * 4. Interface Segregation - принцип разделения интерфейса + * 5. Dependency inversion - принцип инверсии зависисмостей + */ +public class Person +{ + public string FirstName { get; set; } + public string LastName { get; set; } + public int Age { get; set; } +} + +/// +/// Поведение поиска в хранилищах информации +/// +public interface IFindStorage +{ + List FindAll(Predicate predicate); +} + +/// +/// Шаблон списка пользователей +/// +public class ListStorage : IFindStorage +{ + private List storage; + public ListStorage() + { + storage = new List(); + } + + public List GetPersons() => storage; + + public void Add(Person p) => storage.Add(p); + + public List FindAll(Predicate predicate) + { + return storage.Where(e => predicate(e)).ToList(); + } +} + +/// +/// Шаблон словаря пользователей +/// +public class DictionaryStorage : IFindStorage +{ + private Dictionary storage; + public DictionaryStorage() + { + storage = new Dictionary(); + } + + public Dictionary GetPersons() => storage; + + public void Add(string key, Person p) => storage.Add(key, p); + + public List FindAll(Predicate predicate) + { + return storage.Where(e => predicate(e.Value)).Select(e => e.Value).ToList(); + } +} + +/// +/// Щаблон поисковика +/// +public class SearchByAge +{ + IFindStorage storage; + public SearchByAge(IFindStorage storage) => this.storage = storage; + public void Search() + { + foreach (var p in storage.FindAll(e => e.Age > 45)) + { + Console.WriteLine($"{p.FirstName} {p.Age}"); + } + } +} + +public class Program +{ + public static void Main(string[] argv) + { + Console.WriteLine("DictionaryStorage: "); + var storageDict = new DictionaryStorage(); + storageDict.Add("1", new Person() { Age = 90 }); + new SearchByAge(storageDict).Search(); + Console.WriteLine("ListStorage: "); + var storageList = new ListStorage(); + storageList.Add(new Person() { Age = 43 }); + new SearchByAge(storageList).Search(); + } +} \ No newline at end of file diff --git a/Patterns/AbstractFactory/AbstractFactory.csproj b/Patterns/AbstractFactory/AbstractFactory.csproj new file mode 100644 index 0000000..74abf5c --- /dev/null +++ b/Patterns/AbstractFactory/AbstractFactory.csproj @@ -0,0 +1,10 @@ + + + + Exe + net6.0 + enable + enable + + + diff --git a/Patterns/AbstractFactory/Program.cs b/Patterns/AbstractFactory/Program.cs new file mode 100644 index 0000000..88ff2a2 --- /dev/null +++ b/Patterns/AbstractFactory/Program.cs @@ -0,0 +1,148 @@ +/* Абстрактная фабрика + Предоставляет интерфейс для создания + групп связанных или зависимых объектов, + не указывая их конкретный класс + */ +class Program +{ + static void Main() + { + #region Пример №1 - базовое + var soldier = new Hero(new SoldierFactory()); + soldier.Run(); + soldier.Hit(); + + var elf = new Hero(new ElfFactory()); + elf.Run(); + elf.Hit(); + + Console.ReadKey(); + #endregion + } +} + +/// +/// Оружие базовая логика +/// +abstract class Weapon +{ + public abstract void Hit(); +} + +/// +/// Движение базовая логика +/// +abstract class Movement +{ + public abstract void Move(); +} + +/// +/// Огнестрел +/// +class Gun : Weapon +{ + public override void Hit() + { + Console.WriteLine("Hit Gun"); + } +} + +/// +/// Арбалет +/// +class Arbalet : Weapon +{ + public override void Hit() + { + Console.WriteLine("Hit Arbalet"); + } +} + +/// +/// Герой летает +/// +class Fly : Movement +{ + public override void Move() + { + Console.WriteLine("Hero Fly"); + } +} + +/// +/// Герой бежит +/// +class Run : Movement +{ + public override void Move() + { + Console.WriteLine("Hero Run"); + } +} + +/// +/// Супергерой +/// +class Hero +{ + private Weapon Weapon { get; set; } + private Movement Movement { get; set; } + + public Hero(HeroFactory factory) + { + Weapon = factory.CreateWeapon(); + Movement = factory.CreateMovement(); + } + + public void Run() + { + Movement.Move(); + } + + public void Hit() + { + Weapon.Hit(); + } +} + +/// +/// Абстракция фабрика героев +/// +abstract class HeroFactory +{ + public abstract Weapon CreateWeapon(); + public abstract Movement CreateMovement(); +} + +/// +/// Эльфы +/// +class ElfFactory : HeroFactory +{ + public override Movement CreateMovement() + { + return new Fly(); + } + + public override Weapon CreateWeapon() + { + return new Arbalet(); + } +} + +/// +/// Солдаты +/// +class SoldierFactory : HeroFactory +{ + public override Movement CreateMovement() + { + return new Run(); + } + + public override Weapon CreateWeapon() + { + return new Gun(); + } +} diff --git a/Patterns/Adapter/Adapter.csproj b/Patterns/Adapter/Adapter.csproj new file mode 100644 index 0000000..74abf5c --- /dev/null +++ b/Patterns/Adapter/Adapter.csproj @@ -0,0 +1,10 @@ + + + + Exe + net6.0 + enable + enable + + + diff --git a/Patterns/Adapter/Program.cs b/Patterns/Adapter/Program.cs new file mode 100644 index 0000000..08e48d1 --- /dev/null +++ b/Patterns/Adapter/Program.cs @@ -0,0 +1,78 @@ +/* Адаптер + Конвенртирует интерфейс класса в другой интерфейс, + ожидаемый клиентом. Позволяет классам + с разными интерфейсами работать вместе. + */ +class Program +{ + static void Main() + { + #region Пример №1 - базовое + var man = new Driver(); + var car = new Auto(); //машина она едет также как мотоцикл, всё отлично + var camelTransport = //но мы хотим добраться на пешем транспорте (на верблюде) + new CamelToTransport(new Camel()); + + man.Travel(camelTransport); + man.Travel(car); + + Console.ReadKey(); + #endregion + } +} + +interface ITransport +{ + void Drive(); +} + +/// +/// Шаблон автомобиля +/// +class Auto : ITransport +{ + public void Drive() + { + Console.WriteLine(GetType().Name + " Move"); + } +} + +/// +/// Шаблон верблюда +/// +class Camel +{ + public void Move() + { + Console.WriteLine(GetType().Name + " Move"); + } +} + +/// +/// Шаблон движения верблюда +/// +class CamelToTransport : ITransport +{ + Camel camel; + + public CamelToTransport(Camel camel) + { + this.camel = camel; + } + + public void Drive() + { + camel.Move(); + } +} + +/// +/// Шаблон путешественника +/// +class Driver +{ + public void Travel(ITransport transport) + { + transport.Drive(); + } +} \ No newline at end of file diff --git a/Patterns/Base.UserLibrary.Tests/Base.UserLibrary.Tests.csproj b/Patterns/Base.UserLibrary.Tests/Base.UserLibrary.Tests.csproj new file mode 100644 index 0000000..ed22915 --- /dev/null +++ b/Patterns/Base.UserLibrary.Tests/Base.UserLibrary.Tests.csproj @@ -0,0 +1,19 @@ + + + + net6.0 + enable + enable + + false + true + + + + + + + + + + diff --git a/Patterns/Base.UserLibrary.Tests/TestData.xml b/Patterns/Base.UserLibrary.Tests/TestData.xml new file mode 100644 index 0000000..7d39bc1 --- /dev/null +++ b/Patterns/Base.UserLibrary.Tests/TestData.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/Patterns/Base.UserLibrary.Tests/UnitTest1.cs b/Patterns/Base.UserLibrary.Tests/UnitTest1.cs new file mode 100644 index 0000000..2b61bf2 --- /dev/null +++ b/Patterns/Base.UserLibrary.Tests/UnitTest1.cs @@ -0,0 +1,31 @@ +namespace Base.UserLibrary.Tests +{ + [TestClass] + public class UnitTest1 + { + private TestContext testContextInstance; + public TestContext TestContextInstance + { + get { return testContextInstance; } + set { testContextInstance = value; } + } + private UserManagerMsTest manager = new UserManagerMsTest(); + + /// + /// DataSource - + /// 1 - + /// 2 - + /// 3 - XML + /// 4 - + /// + [DataSource("Microsoft.VisualStudio.TestTools.DataSource.XML", + "TestData.xml", + "User", + DataAccessMethod.Sequential)] + [TestMethod] + public void AddDataTest() + { + string userId = Convert.ToString(TestContextInstance.DataRow["Row1"]); + } + } +} \ No newline at end of file diff --git a/Patterns/Base.UserLibrary.Tests/Usings.cs b/Patterns/Base.UserLibrary.Tests/Usings.cs new file mode 100644 index 0000000..ab67c7e --- /dev/null +++ b/Patterns/Base.UserLibrary.Tests/Usings.cs @@ -0,0 +1 @@ +global using Microsoft.VisualStudio.TestTools.UnitTesting; \ No newline at end of file diff --git a/Patterns/Base.cs b/Patterns/Base.cs new file mode 100644 index 0000000..d39fe33 --- /dev/null +++ b/Patterns/Base.cs @@ -0,0 +1,28 @@ +using System; + +public class Base + + +//абстрактный класс +abstract class AbstrTest +{ + void Move() + { + + } + + //реализация по умолчанию + public virtual void Resize() + { + + } + void Declare(); +} + +public class Class_Main : AbstrTest +{ + public Class_Main() + { + Declare(); + } +} diff --git a/Patterns/Base/AssertMsTest.cs b/Patterns/Base/AssertMsTest.cs new file mode 100644 index 0000000..2d7c2dc --- /dev/null +++ b/Patterns/Base/AssertMsTest.cs @@ -0,0 +1,26 @@ +namespace Base; + +public class AssertMsTest +{ + /// + /// Получить квадратный корень + /// + /// Значение + /// double + public static double GetSqrt(double value) + { + return Math.Sqrt(value); + } + + /// + /// Получить приветствие + /// + /// Имя + /// + /// пустое имя + public string SayHello(string name) + { + if (name == null) throw new ArgumentNullException("Parameter name can not be null"); + return "Hi! " + name; + } +} diff --git a/Patterns/Base/BaseInfo.csproj b/Patterns/Base/BaseInfo.csproj new file mode 100644 index 0000000..7d211a9 --- /dev/null +++ b/Patterns/Base/BaseInfo.csproj @@ -0,0 +1,14 @@ + + + + Exe + net6.0 + enable + enable + + + + + + + diff --git a/Patterns/Base/Extension.cs b/Patterns/Base/Extension.cs new file mode 100644 index 0000000..5dabef8 --- /dev/null +++ b/Patterns/Base/Extension.cs @@ -0,0 +1,17 @@ +namespace Base +{ + /// + /// Тестовый класс статических реализаций + /// + internal static class Extension + { + /// + /// Тестовый статический метод + /// + /// Представитель определённого поведения + public static void ResizeExt(this IInterTest classMain) + { + Console.WriteLine("Resize Class Extension"); + } + } +} diff --git a/Patterns/Base/Program.cs b/Patterns/Base/Program.cs new file mode 100644 index 0000000..32aba57 --- /dev/null +++ b/Patterns/Base/Program.cs @@ -0,0 +1,410 @@ +using Newtonsoft.Json; +using static Base.Records; + +namespace Base; + +/// +/// Важно: ссылочные типы лежат в куче, значимые - ссылка в куче, значение в стеке +/// *** +/// Шаблон, по которому определяется форма объекта +/// Определение: +/// Класс - это ссылочный тип данных, шаблон по которому определяется объект, информацию о себе хранит в куче. +/// +class Program +{ + static void Main() + { + var person = new Person() //реализация record сборки разборки + { + Id = 1, + Name = "john" + }; + Console.WriteLine(person.ToString()); + var job = new Job() + { + Ida = 786897980, + Names = "Address" + }; + Console.WriteLine(job.ToString()); + var gl = new GlobalInfo(); + person.Deconstruct(out gl.Name, out gl.Id); + job.Deconstruct(out gl.Names, out gl.Ida); + Console.WriteLine($"{gl.Name}/{gl.Names}/{gl.Id}/{gl.Ida}"); + + IInterTest interTest = new ClassMain(); + interTest.ResizeExt(); //методы static + interTest.Relocate(); //метод объявлен и реализован в самом интерфейсе + var Records = new Records(1, "rec1"); //экзмепляр Records (аналог class) + var (NameS, idS) = Records; //можно разложить record на переменные + var RecNew = Records with { Name = "rec2" };//можно инициализировать другой класс на основе данных первого + Console.WriteLine($"{NameS} {idS}"); + var (NameS2, idS2) = RecNew; //можно разложить record на переменные + Console.WriteLine($"{NameS2} {idS2}"); + Console.WriteLine(Records == RecNew); //можно сравнить record обычными операторами сравнения + Console.WriteLine(); + Console.WriteLine(RecNew); //можно напечать JSON представление содержимого record по умолчанию + Console.WriteLine(Records); //можно напечать JSON представление содержимого record по умолчанию + var json = JsonConvert.SerializeObject(Records, Formatting.Indented); + Console.WriteLine(json); + var otherSideRecord = JsonConvert.DeserializeObject(json); + Console.WriteLine(otherSideRecord); + Records = Records with { Id = 10 }; + Console.WriteLine(Records); + Console.ReadKey(); + } +} + + +/// +/// Абстракция которая отвечает за контракт взаимодействия для различных типов +/// Определение: +/// Интерфейс - это ссылочный тип данных, представляющий контракт взаимодействия (поведение). +/// Этот контракт гласит о том что должен содержать class или struct. +/// Формирует общий признак для разнородных объектов +/// +public interface IInterTest +{ + /// + /// Декларация - метод без реализации по умолчанию + /// + /// + void Build(int build = 0); + /// + /// После C# 8.0 можно указывать реализацию метода в интерфейсе + /// + void Relocate() + { + Console.WriteLine("-> IInterTest: Relocate"); + } + /// + /// Cигнатура - операция без реализации - абстрактный метод + /// + abstract void Reload(); + /// + /// Делегат - ссылочный тип + /// + delegate void Destiny(); + /// + /// Cвойство - ссылочный тип + /// + string Name { get; set; } + /// + /// Cвойство - ссылочный тип + /// + object ID { get; set; } + +} + +/// +/// Абстрактный класс +/// Определение: +/// Абстрактный класс - это ссылочный тип данных, для описания общности сущностей, которые не имеют конкретного воплощения +/// +public abstract class AbstrTest +{ + /// + /// Поле + /// + public int key = 100; + /// + /// Свойство + /// + public string Name { get; set; } + + /// + /// Конструктор без параметров + /// + public AbstrTest() + { + key = 110; + Name = "Fire"; + Console.WriteLine($"->AbstrTest {Name} {key}"); + } + + /// + /// Конструктор с параметрами + /// + /// ключ + public AbstrTest(int key) + { + this.key = key; + Name = "Fire"; + Console.WriteLine($"->AbstrTest {Name} {key}"); + } + + /// + /// Метод - это фиксированная операция с реализацией по умолчанию + /// + public void Move() + { + Console.WriteLine("Move Abstr"); + } + + /// + /// Виртуальный метод - операция с реализацией по умолчанию + /// + public virtual void Resize() + { + Console.WriteLine("Resize Abstr"); + } + + /// + /// Абстрактный метод - сигнатура - операция без реализации + /// + public abstract void Open(); +} + +/// +/// Определение: +/// Структура - это значимый тип данных, ссылка на структуру хранится в куче, значение в стеке +/// Тот же класс, меняется тип данных +/// +public struct TestStruct : IInterTest +{ + /// + /// Свойство имени + /// + public string Name { get; set; } + /// + /// Свойство идентификатора + /// + public object ID { get; set; } + + /// + /// Конструктор без параметров + /// + public TestStruct() + { + Name = "Base"; + ID = (object)0; + } + + /// + /// Метод с реализацией с параметрами + /// + /// # + public void Build(int build = 0) + { + Console.WriteLine($"Build TestStruct {build}"); + } + + /// + /// Метод с реализацией без параметров + /// + public void Reload() + { + Console.WriteLine("Reload TestStruct"); + } +} + +/// +/// Реализация поведения класса +/// +public class ClassMain : AbstrTest, IInterTest +{ + /// + /// Свойство + /// + public int countBuild { get; set; } + /// + /// Свойство от интерфейса + /// + public string Name { get; set; } + /// + /// Свойство от интерфейса + /// + public object ID { get; set; } + + /// + /// Конструтор + реализация поведения конструктора абстрактного класса + /// + public ClassMain() : base (0) + { + TestStruct testStruct = new TestStruct(); + Console.WriteLine($"TestStruct: {testStruct.Name}, {testStruct.ID}"); + Name = "Base"; + ID = (object)0; + Move(); + Build(); + Reload(); + Resize(); + Open(); + } + + /// + /// Конструтор c параметрами + реализация поведения конструктора абстрактного класса + /// + /// # + /// # + /// # + public ClassMain(int build, string name, object id) : base(build) + { + countBuild = build; + Name = name; + ID = id; + Move(); + Build(build); + Reload(); + Resize(); + Open(); + } + + /// + /// Виртуальный метод + /// + public virtual void GG() + { + Console.WriteLine("GG Virtual Method Class"); + } + + /// + /// Метод с параметрами + /// + /// # + public void Build(int build = 0) + { + Console.WriteLine($"Build Interface Class {build}"); + } + + /// + /// Метод без параметров обязательный к реализации от интерфейса + /// + public void Reload() + { + Console.WriteLine("Reload Interface Abstract Method Class"); + } + + /// + /// Реализация virtual метода абстрактного класса + /// + public override void Resize() + { + base.Resize(); + countBuild--; + Console.WriteLine("Resize Class"); + } + + /// + /// Переопределение сигнатуры абстрактного класса + /// + public override void Open() + { + Console.WriteLine("Open Abstract Method Class"); + } + + /// + /// Реализация деструктора класса + /// + ~ClassMain() + { + Console.WriteLine("###Destroy ClassMain"); + } +} + +/// +/// Реализация наследования (3 принцип ООП) +/// Определение: +/// Наследование - это возможность создания новых абстракций на основе существующих. +/// Наследование является ключевой функцией объектно-ориентированных языков программирования. +/// Оно позволяет определить базовый класс для определенных функций (доступа к данным или действий), +/// а затем создавать производные классы, которые наследуют или переопределяют функции базового класса. +/// +public class Nasled : ClassMain +{ + /// + /// Необязательное перепределение виртуального метода главного класса + /// + public override void GG() + { + base.GG(); + } +} + + +/// +/// Определение: +/// Records - это ссылочный тип, некая модификация возможностей классов +/// Ключевая особенность - может представлять неизменяемый тип данных (immutable) +/// Также имеет особенность в виде встроенного JSON представления при выводе в строку +/// Имеет возможность управлять своим деконструктором +/// +public record class Records +{ + /// + /// Свойство идентификатора + /// + public int Id { get; init; } + + /// + /// Свойство имени + /// + public string Name { get; init; } + + /// + /// Конструктор с параметрами + /// + /// идентификатор + /// имя + public Records(int id, string name) + { + Id = id; + Name = name; + Console.WriteLine("Construct"); + } + + public class GlobalInfo + { + public int Id; + public string Name; + public int Ida; + public string Names; + } + + /// + /// Деконструктор + /// + /// имя + /// идентификатор + public void Deconstruct(out string name, out int id) + { + name = Name; + id = Id; + Console.WriteLine("Destruct"); + } +} + +public record class Person +{ + public int Id { get; init; } + public string Name { get; init; } + + /// + /// Деконструктор + /// + /// имя + /// идентификатор + public void Deconstruct(out string name, out int id) + { + name = Name; + id = Id; + Console.WriteLine("Destruct Person"); + } +} + +public record class Job +{ + public int Ida { get; init; } + public string Names { get; init; } + + /// + /// Деконструктор + /// + /// имя + /// идентификатор + public void Deconstruct(out string name, out int id) + { + name = Names; + id = Ida; + Console.WriteLine("Destruct Job"); + } +} \ No newline at end of file diff --git a/Patterns/BaseTests/000_TestsMain.cs b/Patterns/BaseTests/000_TestsMain.cs new file mode 100644 index 0000000..0f420c7 --- /dev/null +++ b/Patterns/BaseTests/000_TestsMain.cs @@ -0,0 +1,31 @@ +using Base; + +namespace BaseTests; + +/// +/// +/// : +/// - +/// +/// - +/// +[TestClass] +public class TestsMain +{ + /// + /// + /// + [TestMethod] + public void TestMethod1() + { + // arrange + int expected = 3; + + // act + var classMain = new ClassMain(4, "Unit", 10); + int actual = classMain.countBuild; + + // assert + Assert.AreEqual(expected, actual, 0.001, "BuildCount not correctly"); // + } +} \ No newline at end of file diff --git a/Patterns/BaseTests/001_TestInitAndCleanUp.cs b/Patterns/BaseTests/001_TestInitAndCleanUp.cs new file mode 100644 index 0000000..4920420 --- /dev/null +++ b/Patterns/BaseTests/001_TestInitAndCleanUp.cs @@ -0,0 +1,38 @@ +using System.Diagnostics; + +namespace Base.Tests; + +[TestClass] +public class TestInitAndCleanUp +{ + private ClassMain main; + private string Name; + + /// + /// Запускается перед каждым тестируемым методом + /// + [TestInitialize] + public void TestInitialize() + { + Debug.WriteLine("Test Initialize"); + main = new ClassMain(); + main.Name = "Nikolay"; + } + + /// + /// Запускается после каждого завершения тестирования метода + /// + [TestCleanup] + public void MainCleanUp() + { + Debug.WriteLine("Test CleanUp"); + Name = string.Empty; + } + + [TestMethod] + public void AddName() + { + Name = "Nikolay"; + Assert.AreEqual(Name, main.Name); + } +} diff --git a/Patterns/BaseTests/002_ClassInitAndCleanUp.cs b/Patterns/BaseTests/002_ClassInitAndCleanUp.cs new file mode 100644 index 0000000..345d72e --- /dev/null +++ b/Patterns/BaseTests/002_ClassInitAndCleanUp.cs @@ -0,0 +1,41 @@ + +using System.Diagnostics; +using System.Xml.Linq; + +namespace Base.Tests; + +[TestClass] +public class ClassInitAndCleanUp +{ + private static ClassMain main; + + /// + /// Запускается один раз перед тем как запустится один Unit Test + /// Метод должен быть открытым, статическим и принимать параметр типа контекста + /// + /// + [ClassInitialize] + public static void ClassInitialize(TestContext context) + { + main = new ClassMain(); + main.Name = "Test"; + } + + /// + /// Запускается после последнего тестируемого метода + /// Метод должен быть открытым, статическим и возвращать void + /// + [ClassCleanup] + public static void MainCleanUp() + { + Debug.WriteLine("Test CleanUp"); + main.Name = string.Empty; + } + + [TestMethod] + public void AddName() + { + var Name = "Test"; + Assert.AreEqual(Name, main.Name); + } +} diff --git a/Patterns/BaseTests/003_AssemblyInit.cs b/Patterns/BaseTests/003_AssemblyInit.cs new file mode 100644 index 0000000..6714a99 --- /dev/null +++ b/Patterns/BaseTests/003_AssemblyInit.cs @@ -0,0 +1,26 @@ +namespace Base.Tests; + +[TestClass] +public class AssemblyInit +{ + /// + /// Код выполняется один раз на всю сборку + /// Используется во всех Unit тестах во всех тестовых вкладках + /// + /// + [AssemblyInitialize] + public static void TestMethodInit(TestContext testContext) + { + Console.WriteLine("Test AssemblyInitialize: " + testContext.TestName); + } + + /// + /// Код выполняется один раз на всю сборку + /// Используется во всех Unit тестах во всех тестовых вкладках + /// + [AssemblyCleanup] + public static void TestMethodGlobalCleanUp() + { + Console.WriteLine("Test AssemblyCleanup"); + } +} diff --git a/Patterns/BaseTests/004_AssertMethods.cs b/Patterns/BaseTests/004_AssertMethods.cs new file mode 100644 index 0000000..0e499f6 --- /dev/null +++ b/Patterns/BaseTests/004_AssertMethods.cs @@ -0,0 +1,65 @@ +namespace Base.Tests; + +[TestClass] +public class AssertMethods +{ + [TestMethod] + public void IsSqrtTest() + { + // arrange + const double input = 4; + const double expected = 2; + + // act + var actual = AssertMsTest.GetSqrt(input); + + // assert - сравнивает два значения + Assert.AreEqual(expected, actual, $"Sqrt of {input} should have been {expected}"); + } + + [TestMethod] + public void DeltaTest() + { + const double expected = 3.1; + const double delta = 0.07; + + // 3.1622776601683795 + // 0.062.. + double actual = AssertMsTest.GetSqrt(10); + + // Проверка значений на равенство с учётом прогрешлоости delta + Assert.AreEqual(expected, actual, delta, $"Sqrt of {actual} should have been {expected}"); + } + + [TestMethod] + public void StringAreEqualTest() + { + // arrange + const string expected = "hello"; + const string input = "HELLO"; + + // act and assert + // третий параметр игнорирование регистра + Assert.AreEqual(expected, input, true); + } + + [TestMethod] + public void StringAreSameTest() + { + string a = "Hello"; + string b = "Hello"; + + // проверка равенства ссылок + Assert.AreSame(a, b); + } + + [TestMethod] + public void IntegerAreSameTest() + { + int a = 10; + int b = 10; + + // проверка равенства ссылок + Assert.AreSame(a, b); + } +} diff --git a/Patterns/BaseTests/005_CollectionAssertMethods.cs b/Patterns/BaseTests/005_CollectionAssertMethods.cs new file mode 100644 index 0000000..50988f5 --- /dev/null +++ b/Patterns/BaseTests/005_CollectionAssertMethods.cs @@ -0,0 +1,65 @@ +namespace Base.Tests; + +/// +/// Проверяет результат работы с коллекциями +/// +[TestClass] +public class CollectionAssertMethods +{ + public static List employees; + + [ClassInitialize] + public static void InitializeCurrentTest(TestContext context) + { + employees = new List(); + + employees.Add("Nikolay"); + employees.Add("Oleg"); + } + + /// + /// Проверка значений коллекции на наличие в ней + /// + [TestMethod] + public void AllItemAreNotNullTest() + { + CollectionAssert.AllItemsAreNotNull(employees, "Not null failed"); + } + + /// + /// Проверка значения коллекции на уникальность + /// + [TestMethod] + public void AllItemsAreUniqueTest() + { + CollectionAssert.AllItemsAreUnique(employees, "Uniqueness failed"); + } + + /// + /// Проверяет каждый элемент списка на равенство с входящим списком + /// + [TestMethod] + public void AreEqualTest() + { + var currList = new List(); + + currList.Add("Nikolay"); + currList.Add("Oleg"); + + CollectionAssert.AreEqual(currList, employees); + } + + /// + /// Проверяем наличии одного List в другом + /// + [TestMethod] + public void SubsetTest() + { + var subsetList = new List(); + + subsetList.Add(employees[1]); + //subsetList.Add("Mig"); //ошибка так как этот элемент не входит в employees + + CollectionAssert.IsSubsetOf(subsetList, employees, "not elements subsetList to employees"); + } +} diff --git a/Patterns/BaseTests/006_StringAssetMethods.cs b/Patterns/BaseTests/006_StringAssetMethods.cs new file mode 100644 index 0000000..b1006a8 --- /dev/null +++ b/Patterns/BaseTests/006_StringAssetMethods.cs @@ -0,0 +1,44 @@ +using System.Text.RegularExpressions; + +namespace Base.Tests; + +[TestClass] +public class StringAssetMethods +{ + /// + /// Проверка подстроки в строке + /// + [TestMethod] + public void StringContainsTest() + { + StringAssert.Contains("Assert samples", "sam"); + } + + /// + /// ПРоверка с использованием регулярного выражения + /// + [TestMethod] + public void StringMathesTest() + { + // проверяет наличие трёх цифр подряд + StringAssert.Matches("123", new Regex(@"\d{3}")); + } + + /// + /// Проверка начала строки на соответствие условию + /// + [TestMethod] + public void StringStartsWithTest() + { + StringAssert.StartsWith("Hello London", "H"); + } + + /// + /// Проверка конца строки на соответствие условию + /// + [TestMethod] + public void StringEndWithTest() + { + StringAssert.EndsWith("Hello Moscow", "w"); + } +} diff --git a/Patterns/BaseTests/007_ExpectingExceptions.cs b/Patterns/BaseTests/007_ExpectingExceptions.cs new file mode 100644 index 0000000..67c1d88 --- /dev/null +++ b/Patterns/BaseTests/007_ExpectingExceptions.cs @@ -0,0 +1,27 @@ +namespace Base.Tests; + +[TestClass] +public class ExpectingExceptions +{ + /// + /// Проверка метода на возврат исключения + /// + [ExpectedException(typeof(ArgumentNullException), "Exception was not throw")] + [TestMethod] + public void AssertMsTestExceptionTest() + { + var ms = new AssertMsTest(); + ms.SayHello(null); + } + + [TestMethod] + public void AssertMsTestReturnTest() + { + var name = "Hi! Nikolay"; + + var ms = new AssertMsTest(); + var actual = ms.SayHello("Nikolay"); + + Assert.AreEqual(name, actual, $"name: {name} act: {actual}"); + } +} diff --git a/Patterns/BaseTests/Base.Tests.csproj b/Patterns/BaseTests/Base.Tests.csproj new file mode 100644 index 0000000..76e1ecd --- /dev/null +++ b/Patterns/BaseTests/Base.Tests.csproj @@ -0,0 +1,22 @@ + + + + net6.0 + enable + enable + + false + + + + + + + + + + + + + + diff --git a/Patterns/BaseTests/Usings.cs b/Patterns/BaseTests/Usings.cs new file mode 100644 index 0000000..ab67c7e --- /dev/null +++ b/Patterns/BaseTests/Usings.cs @@ -0,0 +1 @@ +global using Microsoft.VisualStudio.TestTools.UnitTesting; \ No newline at end of file diff --git a/Patterns/Bridge/Bridge.csproj b/Patterns/Bridge/Bridge.csproj new file mode 100644 index 0000000..74abf5c --- /dev/null +++ b/Patterns/Bridge/Bridge.csproj @@ -0,0 +1,10 @@ + + + + Exe + net6.0 + enable + enable + + + diff --git a/Patterns/Bridge/Program.cs b/Patterns/Bridge/Program.cs new file mode 100644 index 0000000..a4de93c --- /dev/null +++ b/Patterns/Bridge/Program.cs @@ -0,0 +1,96 @@ +/* Мост + Разделяет абстракцию и реализацию так, + чтобы они могли изменяться независимо друг от друга + */ +class Program +{ + static void Main() + { + #region Пример №1 - базовое + var programmer_1 = new FreelancerProgger(new CPPLang()); + programmer_1.DoWork(); + programmer_1.EarnMoney(); + var programmer_2 = new FreelancerProgger(new CSharpLang()); + programmer_2.DoWork(); + programmer_2.EarnMoney(); + Console.ReadKey(); + #endregion + } +} + +/// +/// Поведение языка +/// +interface ILanguage +{ + void Build(); + void Execute(); +} + +class CPPLang : ILanguage +{ + public void Build() + { + Console.WriteLine("C++ compile"); + } + + public void Execute() + { + Console.WriteLine("C++ Start"); + } +} + +class CSharpLang : ILanguage +{ + public void Build() + { + Console.WriteLine("C# compile"); + } + + public void Execute() + { + Console.WriteLine("C# Start"); + } +} + +abstract class Programmer +{ + protected ILanguage language; + public ILanguage Language + { + set { language = value; } + } + + public Programmer(ILanguage language) + { + Language = language; + } + + public virtual void DoWork() + { + language.Build(); + language.Execute(); + } + + public abstract void EarnMoney(); +} + +class FreelancerProgger : Programmer +{ + public FreelancerProgger(ILanguage language) : base(language) { } + + public override void EarnMoney() + { + Console.WriteLine("Получаем оплату за заказ"); + } +} + +class CorporateProgger : Programmer +{ + public CorporateProgger(ILanguage language) : base(language) { } + + public override void EarnMoney() + { + Console.WriteLine("Получаем оплату в конце месяца"); + } +} \ No newline at end of file diff --git a/Patterns/Builder/Builder.csproj b/Patterns/Builder/Builder.csproj new file mode 100644 index 0000000..74abf5c --- /dev/null +++ b/Patterns/Builder/Builder.csproj @@ -0,0 +1,10 @@ + + + + Exe + net6.0 + enable + enable + + + diff --git a/Patterns/Builder/Program.cs b/Patterns/Builder/Program.cs new file mode 100644 index 0000000..2b61f7a --- /dev/null +++ b/Patterns/Builder/Program.cs @@ -0,0 +1,120 @@ +/* Строитель + Разделяет создание сложного объекта + и его инициализацию так, что одинаковый + процесс построения может может создавать + объекты с разным состоянием + */ +class Program +{ + static void Main() + { + #region Пример №1 - базовое + var rx = new Baker(); + var bread = rx.Bake(new RBuilderBread()); + + Console.WriteLine(bread.ToString()); + Console.ReadKey(); + #endregion + } +} + +/// +/// Мука +/// +class Floor +{ + /// + /// Сорт муки + /// + public string Sort { get; set; } +} + +/// +/// Соль +/// +class Salt +{ + /// + /// Масса + /// + public double Mass { get; set; } +} + +/// +/// Пищевые добавки +/// +class Additives +{ + /// + /// Список пищевых добавок + /// + public string[] Names { get; set; } +} + +/// +/// Xлеб +/// +class Bread +{ + public Floor Floor { get; set; } + public Salt Salt { get; set; } + public Additives Additives { get; set; } + + public override string ToString() + { + return $"[F: {Floor.Sort}]---[S: {Salt.Mass}]---[A: {Additives.Names[0]}]"; + } +} + +/// +/// Строитель хлеба +/// +abstract class BreadBuilder +{ + public Bread Bread { get; set; } + public void CreateBread() + { + Bread = new Bread(); + } + + public abstract void SetFloor(); + public abstract void SetSalt(); + public abstract void SetAdditives(); +} + +/// +/// Пекарь +/// +class Baker +{ + public Bread Bake(BreadBuilder breadBuilder) + { + breadBuilder.CreateBread(); + breadBuilder.SetFloor(); + breadBuilder.SetSalt(); + breadBuilder.SetAdditives(); + return breadBuilder.Bread; + } +} + + +/// +/// Для ржаного хлеба строитель +/// +class RBuilderBread : BreadBuilder +{ + public override void SetAdditives() + { + Bread.Additives = new Additives() { Names = new[] { "E222", "E297" } }; + } + + public override void SetFloor() + { + Bread.Floor = new Floor() { Sort = "R class" }; + } + + public override void SetSalt() + { + Bread.Salt = new Salt() { Mass = 3.44 }; + } +} diff --git a/Patterns/ChainOfResponsibility/ChainOfResponsibility.csproj b/Patterns/ChainOfResponsibility/ChainOfResponsibility.csproj new file mode 100644 index 0000000..74abf5c --- /dev/null +++ b/Patterns/ChainOfResponsibility/ChainOfResponsibility.csproj @@ -0,0 +1,10 @@ + + + + Exe + net6.0 + enable + enable + + + diff --git a/Patterns/ChainOfResponsibility/Program.cs b/Patterns/ChainOfResponsibility/Program.cs new file mode 100644 index 0000000..1eb7422 --- /dev/null +++ b/Patterns/ChainOfResponsibility/Program.cs @@ -0,0 +1,165 @@ +/* Цепочка обязанностей + Избегает связывание отправителя запроса + с его получателем, давая возможность обработать + запрос более чем одному объекту. Связывает + объекты-получатели и передаёт запрос по цепочке + пока объект не обработает его. + */ +class Program +{ + public static void GiveCommand(IWorker worker, string command) + { + var str = worker.Execute(command); + if(string.IsNullOrEmpty(str)) Console.WriteLine(command + " - никто не выполнил команду"); + else Console.WriteLine(str); + } + + static void Main() + { + #region Пример №1 - базовое + Handler h1 = new ConcreateHandler1(); + Handler h2 = new ConcreateHandler2(); + h1.Successor = h2; + h1.HandleRequest(2); //От первого до второго объекта обработка + Console.WriteLine("Please press Enter..."); + Console.ReadKey(); + #endregion + #region Пример №2 - этапы строительства дома + var designer = new Designer(); + var programmer = new Programmer(); + var finishworker = new FinishWorker(); + designer.SetNetWorker(finishworker).SetNetWorker(programmer); + + GiveCommand(designer, "Спроектировать веранду"); + GiveCommand(designer, "Сделать машину времени"); + GiveCommand(designer, "Уволить работников"); + GiveCommand(designer, "Курить"); + #endregion + } +} + +/// +/// Передатчик +/// +abstract class Handler +{ + public Handler Successor { get; set; } + public abstract void HandleRequest(int condition); +} + +/// +/// Обработчик запроса №1 +/// +class ConcreateHandler1 : Handler +{ + /// + /// Обработка запроса + /// + /// состояние + public override void HandleRequest(int condition) + { + Console.WriteLine("1"); + if(condition == 1) return; //завершаем выполнение + else if(Successor != null) + Successor.HandleRequest(condition); //передача запроса дальше по цепи + } +} + +/// +/// Обработчик запроса №2 +/// +class ConcreateHandler2 : Handler +{ + /// + /// Обработка запроса + /// + /// состояние + public override void HandleRequest(int condition) + { + Console.WriteLine("2"); + if (condition == 2) return; //завершаем выполнение + else if (Successor != null) //передача запроса дальше по цепи + Successor.HandleRequest(condition); + } +} + +/// +/// Поведение рабочего +/// +interface IWorker +{ + /// + /// Передача обязанностей следующему рабочему + /// + /// следующий рабочий + IWorker SetNetWorker(IWorker worker); + + /// + /// Рабочий принимает команду на исполнение + /// + /// команда + /// Резульат принятия + string Execute(string command); +} + +/// +/// Абстрактный рабочий, базовое описание структуры каждого +/// +abstract class AbsWorker : IWorker +{ + private IWorker nextWorker; + public AbsWorker() => nextWorker = null; + + /// + /// Изменяемый процесс обработки команды в классах наследниках + /// У каждого рабочего свой процесс выполнени + /// + /// команда + /// Результат + public virtual string Execute(string command) + { + if (nextWorker == null) return string.Empty; + return nextWorker.Execute(command); + } + + /// + /// Передача обязанностей другому рабочему + /// + /// Другой рабочий + /// Другой рабочий + public IWorker SetNetWorker(IWorker worker) + { + nextWorker = worker; + return worker; + } +} + +class Designer : AbsWorker +{ + public override string Execute(string command) + { + if (command == "Спроектировать веранду") + return "Проектировщик выполнил команду: " + command; + else return base.Execute(command); //если не может выполнить передаёт следующему в цепочке + } +} + +class Programmer: AbsWorker +{ + public override string Execute(string command) + { + if(command == "Сделать машину времени") + return "Программист выполнил команду: " + command; + else return base.Execute(command); + } +} + +class FinishWorker : AbsWorker +{ + public override string Execute(string command) + { + if (command == "Уволить работников") + return "Начальник выполнил команду: " + command; + else return base.Execute(command); + } +} \ No newline at end of file diff --git a/Patterns/Command/Command.csproj b/Patterns/Command/Command.csproj new file mode 100644 index 0000000..74abf5c --- /dev/null +++ b/Patterns/Command/Command.csproj @@ -0,0 +1,10 @@ + + + + Exe + net6.0 + enable + enable + + + diff --git a/Patterns/Command/Program.cs b/Patterns/Command/Program.cs new file mode 100644 index 0000000..9ee07e3 --- /dev/null +++ b/Patterns/Command/Program.cs @@ -0,0 +1,225 @@ +/* Команда + Инкапсулирует запрос в виде объекта + позволяя передавать их клиентам в + качестве параметров, ставить в очередь, + логировать, а также поддерживать отмену + операций + */ +class Program +{ + static void Main() + { + #region Пример №1 - базовое + var initCommand = new Invoker(new ConcreteCommand(new Receiver())); + initCommand.Run(); + initCommand.Cancel(); + Console.WriteLine("Please press Enter..."); + Console.ReadKey(); + #endregion + #region Пример №2 - пульт управления конвеерной установкой + var conveyor = new Conveyor(); // создаём конвеер + var multipult = new Multipult(); // создаём пульт управления конвеером + multipult.SetCommand(0, new ConveyorWorkCommand(conveyor)); + multipult.SetCommand(1, new ConveyorAjustCommand(conveyor)); + + multipult.PressOn(0); + multipult.PressOn(1); + multipult.PressCansel(); + multipult.PressCansel(); + #endregion + } +} + +/// +/// Описания общего поведения объекта +/// +abstract class Command +{ + public abstract void Execute(); + public abstract void Undo(); +} + +/// +/// Описание процесса создания команды +/// +class ConcreteCommand : Command +{ + Receiver receiver; + + public ConcreteCommand(Receiver receiver) + { + this.receiver = receiver; + } + + /// + /// Инициализация команды + /// *вызывает его получателя + /// + public override void Execute() + { + receiver.Operation(); + } + + /// + /// Остановка команды + /// + public override void Undo() + { + Console.WriteLine("Stop"); + } +} + +/// +/// Описание возможностей получателя команды +/// +class Receiver +{ + /// + /// Обработка получателем команды + /// + public void Operation() + { + Console.WriteLine("Processing..."); + } +} + +/// +/// Описание инициатора команды +/// +class Invoker +{ + Command command; + + /// + /// Принимает в себя команду + /// + /// # + public Invoker(Command command) + { + this.command = command; + } + + /// + /// Запускает команду + /// + public void Run() + { + command.Execute(); + } + + /// + /// Отменяет выполнение команды + /// + public void Cancel() + { + command.Undo(); + } +} + +/// +/// Поведение команды +/// +interface ICommand +{ + void Positive(); + void Negative(); +} + +/// +/// Класс конвеера +/// +class Conveyor +{ + public void On() => Console.WriteLine("Включение конвеера"); + + public void Off() => Console.WriteLine("Выключение конвеера"); + + public void SpeedIncrease() => Console.WriteLine("Скорость конвеера увеличена"); + + public void SpeedDecrease() => Console.WriteLine("Скорость конвеера снижена"); +} + +/// +/// Класс управления работой конвеера +/// +class ConveyorWorkCommand : ICommand +{ + public Conveyor conveer; + + /// + /// Передача типа конвеера в конструторе + /// + /// тип + public ConveyorWorkCommand(Conveyor conveer) => this.conveer = conveer; + + public void Negative() => conveer.Off(); + + public void Positive() => conveer.On(); +} + +/// +/// Класс регулировки конвеера +/// +class ConveyorAjustCommand : ICommand +{ + public Conveyor conveer; + + /// + /// Передача типа конвеера в конструторе + /// + /// тип + public ConveyorAjustCommand(Conveyor conveer) => this.conveer = conveer; + + public void Negative() => conveer.SpeedDecrease(); + + public void Positive() => conveer.SpeedIncrease(); +} + + +/// +/// Пульт управления конвеером +/// +class Multipult +{ + /// + /// Все возможные команды + /// + private List commands; + + /// + /// История выполненных команд для возможной их отмены + /// + private Stack history; + + public Multipult() + { + commands = new List() { null, null }; + history = new Stack(); + } + + /// + /// Устанавлием список команд по индексу кнопки + /// + public void SetCommand(int btn, ICommand command) => commands[btn] = command; + + /// + /// Вызывает команду из списка по указанному индексу + /// и запишет в историю команд выполненную команду + /// + /// идекс кнопки + public void PressOn(int btn) + { + commands[btn].Positive(); + history.Push(commands[btn]); + } + + /// + /// Извлекает команду из истории и отменяет её + /// + public void PressCansel() + { + if(history.Count == 0) return; + var oldC = history.Pop(); + oldC.Negative(); + } +} \ No newline at end of file diff --git a/Patterns/Composite/Composite.csproj b/Patterns/Composite/Composite.csproj new file mode 100644 index 0000000..74abf5c --- /dev/null +++ b/Patterns/Composite/Composite.csproj @@ -0,0 +1,10 @@ + + + + Exe + net6.0 + enable + enable + + + diff --git a/Patterns/Composite/Program.cs b/Patterns/Composite/Program.cs new file mode 100644 index 0000000..6d65b38 --- /dev/null +++ b/Patterns/Composite/Program.cs @@ -0,0 +1,129 @@ +/* Компоновщик + Компонует объекты в древовидную структуру по принципу "часть-целое", + представляя их в виде иерархии. Позволяет + клиенту одинаково обращаться как к отдельному, + так и к целому поддереву + */ +class Program +{ + static void Main() + { + #region Пример №1 - базовое + var paths = new Paths(new Dictionary()); + paths.components.Add(1, new Directory("C")); + paths.components[1].Add(new Folder("SYSTEM")); + paths.components[1].Add(new Folder("DATA")); + paths.components[1].Add(new File("test.txt")); + paths.components.Add(0, new Directory("F")); + paths.components[0].Add(new File("resize.cs")); + paths.Print(); + Console.ReadKey(); + #endregion + } +} + +/// +/// Абстракция компонента файловой системы (дерева) - пути до файла +/// +abstract class Component +{ + protected string name; + + public Component(string name) + { + this.name = name; + } + + public virtual void Add(Component component) { } + public abstract void Remove(Component component); + public abstract void Print(); +} + +class Paths : Component +{ + public Dictionary components; + + public Paths(Dictionary components) : base ("") + { + this.components = components; + } + + public override void Print() + { + foreach (var component in components) + { + component.Value.Print(); + Console.WriteLine(); + } + } + + public override void Remove(Component component) + { + Console.WriteLine("Delete Path" + this.name); + } +} + +class Directory : Component +{ + public List components = new(); + + public Directory(string name) + : base(name) + { + } + + public override void Add(Component component) + { + components.Add(component); + } + + public override void Print() + { + Console.Write(this.name + ":"); + foreach (var component in components) + { + component.Print(); + } + } + + public override void Remove(Component component) + { + component.Remove(component); + } +} + +class Folder : Component +{ + public Folder(string name) + : base(name) + { + } + + public override void Print() + { + Console.Write("\\" + this.name); + } + + public override void Remove(Component component) + { + Console.WriteLine(this.name + " Delete"); + } +} + +class File : Component +{ + public File(string name) + : base(name) + { + } + + public override void Print() + { + Console.Write("\\" + this.name); + } + + public override void Remove(Component component) + { + Console.WriteLine(this.name + " Delete"); + } +} diff --git a/Patterns/Decorator/Decorator.csproj b/Patterns/Decorator/Decorator.csproj new file mode 100644 index 0000000..74abf5c --- /dev/null +++ b/Patterns/Decorator/Decorator.csproj @@ -0,0 +1,10 @@ + + + + Exe + net6.0 + enable + enable + + + diff --git a/Patterns/Decorator/Program.cs b/Patterns/Decorator/Program.cs new file mode 100644 index 0000000..a0b1f82 --- /dev/null +++ b/Patterns/Decorator/Program.cs @@ -0,0 +1,62 @@ +/* Декоратор + Динамически предоставляет объекту + дополнительные возможности. Представляет + собой гибкую альтернативу наследованию + для расширения функциональности. + */ +class Program +{ + static void Main() + { + #region Пример №1 - базовое + Pizza r = new RussianPizza(); + Console.WriteLine(r.GetCost()); + Pizza i = new TomatoPizza(r); + Console.WriteLine(i.GetCost()); + Console.ReadKey(); + #endregion + } +} + +abstract class Pizza +{ + public string Name { get; set; } + public Pizza(string name) + { + Name = name; + } + public abstract int GetCost(); +} + +class RussianPizza : Pizza +{ + public RussianPizza() : base("Russian Pizza") + { + } + + public override int GetCost() + { + return 1000; + } +} + +abstract class PizzaDecorator : Pizza +{ + protected Pizza pizza; + protected PizzaDecorator(string name, Pizza pizza) : base(name) + { + this.pizza = pizza; + } +} + +class TomatoPizza : PizzaDecorator +{ + public TomatoPizza(Pizza pizza) : base(pizza.Name + ", tomato", pizza) + { + } + + public override int GetCost() + { + return pizza.GetCost() + 100; + } +} diff --git a/Patterns/Dict/DictionaryInfo.csproj b/Patterns/Dict/DictionaryInfo.csproj new file mode 100644 index 0000000..5eb1e84 --- /dev/null +++ b/Patterns/Dict/DictionaryInfo.csproj @@ -0,0 +1,10 @@ + + + + Exe + net6.0 + enable + disable + + + diff --git a/Patterns/Dict/Program.cs b/Patterns/Dict/Program.cs new file mode 100644 index 0000000..aca679b --- /dev/null +++ b/Patterns/Dict/Program.cs @@ -0,0 +1,116 @@ +using System.Collections; +using System.Collections.Concurrent; +using System.Collections.Specialized; +using System.Diagnostics; + +class Program +{ + /// + /// Стандартный Dictionary + /// Быстрый поиск с помощью ключей, можно добавлять и удалять элементы + /// + private static readonly Dictionary Dictionary = new(); + + /// + /// ListDictionary + /// Он меньше и быстрее, чем Hashtable если количество элементов равно 10 или меньше + /// + private static readonly ListDictionary LDictionary = new() + { + { "key", "value"} + }; + + /// + /// HybridDictionary + /// Рекомендуется для случаев, когда количество элементов в словаре неизвестно. + /// Он использует улучшенную производительность ListDictionary с небольшими коллекциями + /// и предлагает гибкость переключения на Hashtable , которая обрабатывает большие коллекции лучше + /// + private static readonly HybridDictionary HDictionary = new() + { + { "key", "value"} + }; + + /// + /// OrderedDictionary + /// Он всегда упорядочен при выводе foreach + /// Ключ не может быть нулевым , но значение может быть. + /// Каждый элемент представляет собой пару ключ/значение, хранящуюся в объекте DictionaryEntry + /// Доступ к элементам возможен либо по ключу, либо по индексу. + /// [!] + /// если элементов больше 20-ти быстрее при цикле for + /// если элементов меньше 15-20 быстрее в foreach чем for + /// + private static readonly OrderedDictionary ODictionary = new() + { + {"01", "odin"}, + {"02", "dva"}, + {"03", "tri"}, + {"04", "chetiri"}, + {"06", "pyat"}, + {"07", "pyat"}, + {"08", "pyat"}, + {"09", "pyat"}, + {"10", "pyat"}, + {"11", "pyat"}, + {"12", "pyat"}, + {"13", "pyat"}, + {"14", "pyat"}, + {"15", "pyat"}, + {"16", "pyat"}, + {"17", "pyat"}, + {"18", "pyat"}, + {"19", "pyat"}, + {"20", "pyat"}, + {"21", "pyat"}, + {"22", "pyat"}, + {"23", "pyat"}, + {"24", "pyat"}, + {"25", "pyat"}, + {"26", "pyat"}, + {"27", "pyat"}, + {"28", "pyat"}, + {"29", "pyat"}, + {"30", "pyat"}, + {"31", "pyat"} + }; + + + /// + /// SortedDictionary + /// Дерево бинарного поиска, в котором все элементы отсортированы на основе ключа + /// Быстрее вставляет и удаляет элементы + /// + private static readonly SortedDictionary SDictionary = new(); + + /// + /// ConcurrentDictionary + /// Потокобезопасная коллекция пар "ключ-значение", доступ к которой могут одновременно получать несколько потоков. + /// по умолчанию 4 потока на запись concurrencyLevel = 4 + /// первоначальное число элементов 31 сapacity = 31 + /// В отличие от обычного Dictionary, можно производить вставку в ConcurrentDictionary или удаление из него прямо во время перечисления + /// + private static readonly ConcurrentDictionary СoncurrentDictionary = new(); + + static void Main() + { + Stopwatch stopwatch = new Stopwatch(); + stopwatch.Start(); + for(int i = 0; i < ODictionary.Count; i++) + { + string val = (string)ODictionary[i]; + Console.WriteLine(val); + } + stopwatch.Stop(); + Console.WriteLine("[for][el > 20]: " + stopwatch.Elapsed); + stopwatch.Reset(); + stopwatch.Start(); + foreach (DictionaryEntry item in ODictionary) + { + Console.WriteLine(item.Value); + } + stopwatch.Stop(); + Console.WriteLine("[foreach][el > 20]: " + stopwatch.Elapsed); + Console.ReadKey(); + } +} \ No newline at end of file diff --git a/Patterns/Facade/Facade.csproj b/Patterns/Facade/Facade.csproj new file mode 100644 index 0000000..74abf5c --- /dev/null +++ b/Patterns/Facade/Facade.csproj @@ -0,0 +1,10 @@ + + + + Exe + net6.0 + enable + enable + + + diff --git a/Patterns/Facade/Program.cs b/Patterns/Facade/Program.cs new file mode 100644 index 0000000..11cad77 --- /dev/null +++ b/Patterns/Facade/Program.cs @@ -0,0 +1,55 @@ +/* Фасад + Предоставляет единый интерфейс к группе + интерфейсов подсистемы. Определяет высокоуровневый + интерфейс, делая систему проще для использования. + */ +class Program +{ + static void Main() + { + #region Пример №1 - базовое + var facade = new Facade(new A(), new B()); + facade.Start(); + Console.ReadKey(); + #endregion + } +} + +class Facade +{ + ILogic logic1; + ILogic logic2; + public Facade(ILogic logic1, ILogic logic2) + { + this.logic1 = logic1; + this.logic2 = logic2; + } + + public void Start() + { + logic1.Process(); + logic2.Process(); + } +} + +interface ILogic +{ + void Process(); +} + + +class A : ILogic +{ + public void Process() + { + Console.WriteLine("Some Process " + GetType().Name); + } +} + +class B : ILogic +{ + public void Process() + { + Console.WriteLine("Some Process " + GetType().Name); + } +} \ No newline at end of file diff --git a/Patterns/FactoryMethod/FactoryMethod.csproj b/Patterns/FactoryMethod/FactoryMethod.csproj new file mode 100644 index 0000000..74abf5c --- /dev/null +++ b/Patterns/FactoryMethod/FactoryMethod.csproj @@ -0,0 +1,10 @@ + + + + Exe + net6.0 + enable + enable + + + diff --git a/Patterns/FactoryMethod/Program.cs b/Patterns/FactoryMethod/Program.cs new file mode 100644 index 0000000..7c42e32 --- /dev/null +++ b/Patterns/FactoryMethod/Program.cs @@ -0,0 +1,120 @@ +/* Фабричный метод + Определяет интерфейс для создания объекта, + но позволяет подклассам решать, какой класс создавать. + Позволяет делегировать создание класса + объектам класса. + */ +class Program +{ + static void Main() + { + #region Пример №1 - базовое + var ltd = new WoodDeveloper(); + ltd.Create(); + + var rss = new OfficeDeveloper(); + rss.Create(); + + Creator ltdEx = new Creator(); + var a1 = ltdEx.FactoryMethod(); + a1.Create(); + Creator rssEx = new Creator(); + var a2 = rssEx.FactoryMethod(); + a2.Create(); + + Console.ReadKey(); + #endregion + } +} + +/// +/// *** представления через обобщения (нельзя инициализировать через параметризированный конструктор) +/// +/// обобщающий тип +class Creator where T : Developer, new() +{ + public T FactoryMethod() { return new T(); } +} + +/// +/// Cтроительная компания - базовая логика +/// +abstract class Developer +{ + protected string Name { get; set; } + + public Developer(string name) + { + Name = name; + } + + /// + /// Фабричный метод + /// + /// House + public abstract House Create(); +} + +class WoodDeveloper : Developer +{ + public WoodDeveloper() : base("Wood Develop LTD") + { + } + + public override House Create() + { + return new PanelHouse(); + } +} + +class OfficeDeveloper : Developer +{ + public OfficeDeveloper() : base("Office Develop RSS") + { + } + + public override House Create() + { + return new OfficeHouse(); + } +} + +/// +/// Общая логика операций над строением +/// +abstract class House +{ + public abstract void Build(); +} + +/// +/// Панельный дом +/// +class PanelHouse : House +{ + public PanelHouse() + { + Build(); + } + + public override void Build() + { + Console.WriteLine("Build Panel House"); + } +} + +/// +/// Офисное здание +/// +class OfficeHouse : House +{ + public OfficeHouse() + { + Build(); + } + + public override void Build() + { + Console.WriteLine("Build Office House"); + } +} \ No newline at end of file diff --git a/Patterns/FluentBuilder/FluentBuilder.csproj b/Patterns/FluentBuilder/FluentBuilder.csproj new file mode 100644 index 0000000..74abf5c --- /dev/null +++ b/Patterns/FluentBuilder/FluentBuilder.csproj @@ -0,0 +1,10 @@ + + + + Exe + net6.0 + enable + enable + + + diff --git a/Patterns/FluentBuilder/Program.cs b/Patterns/FluentBuilder/Program.cs new file mode 100644 index 0000000..a8c2c69 --- /dev/null +++ b/Patterns/FluentBuilder/Program.cs @@ -0,0 +1,68 @@ +/* Гибкий(плавный, текучий) строитель (интерфейс) + Позволяет упростить процесс создания сложных + объектов с помощью методов-цепочек, которые + наделяют объект каким-то определенным качеством + */ +class Program +{ + static void Main() + { + #region Пример №1 - базовое + User user = new User().Create().SetName("Alex").SetPassword("admin"); + Console.WriteLine(user); + Console.ReadKey(); + #endregion + } +} + +/// +/// Шаблон пользователя +/// +class User +{ + public string Name { get; set; } + public string Password { get; set; } + + public UserBuilder Create() + { + return new UserBuilder(); + } + + public override string ToString() + { + return $"Name {Name}, Password {Password}"; + } +} + +/// +/// Шаблон гибкого строителя конфигурации пользователя +/// +class UserBuilder +{ + private User CurrentUser { get; set; } + public UserBuilder() + { + CurrentUser = new User(); + } + + public UserBuilder SetName(string name) + { + CurrentUser.Name = name; + return this; + } + + public UserBuilder SetPassword(string password) + { + CurrentUser.Password = password; + return this; + } + + /// + /// преобразуем тип Builder в тип User для которого он использовался + /// + /// строитель + public static implicit operator User(UserBuilder builder) + { + return builder.CurrentUser; + } +} \ No newline at end of file diff --git a/Patterns/Flyweight/Flyweight.csproj b/Patterns/Flyweight/Flyweight.csproj new file mode 100644 index 0000000..74abf5c --- /dev/null +++ b/Patterns/Flyweight/Flyweight.csproj @@ -0,0 +1,10 @@ + + + + Exe + net6.0 + enable + enable + + + diff --git a/Patterns/Flyweight/Program.cs b/Patterns/Flyweight/Program.cs new file mode 100644 index 0000000..b9ab274 --- /dev/null +++ b/Patterns/Flyweight/Program.cs @@ -0,0 +1,97 @@ +/* Приспособленец + Благодаря совместному использованию, + поддерживает эффективную работу + с большим количеством объектов. + (для оптимизации работы с памятью) + */ +class Program +{ + static void Main() + { + #region Пример №1 - базовое + double longtitude = 22.33; + double latitude = 55.11; + + HouseFactory houseFactory = new HouseFactory(); + for (int i = 0; i < 10; i++) + { + House panelH = houseFactory.GetHouse("Panel"); + if(panelH != null) + panelH.Build(longtitude, latitude); + longtitude += 0.1; + latitude += 0.1; + } + + for (int i = 0; i < 10; i++) + { + House officeH = houseFactory.GetHouse("Office"); + if (officeH != null) + officeH.Build(longtitude, latitude); + longtitude += 0.1; + latitude += 0.1; + } + + Console.ReadKey(); + #endregion + } +} + +abstract class House +{ + /// + /// Кол-во этажей - внутреннее состояние + /// + protected int stages; + + /// + /// Внешнее состояние действия + /// + /// + /// + public abstract void Build(double latitude, double longitude); +} + +class PanelHouse : House +{ + public PanelHouse() + { + stages = 5; + } + + public override void Build(double latitude, double longitude) + { + Console.WriteLine($"PanelHouse Build stages-{stages} {latitude}, {longitude}"); + } +} + +class OfficeHouse : House +{ + public OfficeHouse() + { + stages = 50; + } + + public override void Build(double latitude, double longitude) + { + Console.WriteLine($"OfficeHouse Build stages-{stages} {latitude}, {longitude}"); + } +} + +class HouseFactory +{ + Dictionary houses = new Dictionary(); + + public HouseFactory() + { + houses.Add("Panel", new PanelHouse()); + houses.Add("Office", new OfficeHouse()); + } + + public House GetHouse(string key) + { + if (houses.ContainsKey(key)) + return houses[key]; + else + return null; + } +} \ No newline at end of file diff --git a/Patterns/Interpreter/Interpreter.csproj b/Patterns/Interpreter/Interpreter.csproj new file mode 100644 index 0000000..74abf5c --- /dev/null +++ b/Patterns/Interpreter/Interpreter.csproj @@ -0,0 +1,10 @@ + + + + Exe + net6.0 + enable + enable + + + diff --git a/Patterns/Interpreter/Program.cs b/Patterns/Interpreter/Program.cs new file mode 100644 index 0000000..67abd0a --- /dev/null +++ b/Patterns/Interpreter/Program.cs @@ -0,0 +1,148 @@ +/* Интерпретатор + Получая формальный язык, определяет + представление его грамматики и интерпретатор, + использующий это представление для обработки + выражений языка (Применяется для часто повторяющихся операций) + */ +class Program +{ + public static void Main(string[] args) + { + #region Пример №1 - базовое + var context = new Context(); + //создаём переменные + int x = 5; + int y = 8; + int z = 2; + int k = 10; + //задаём переменные в контекст + context.SetVariable("x", x); + context.SetVariable("y", y); + context.SetVariable("z", z); + context.SetVariable("k", k); + //(x + y - z) * k + var expressionAdd = new AddExpression(new NumberExpression("x"), + new NumberExpression("y")); + var expressionSub = new SubstructExpression(expressionAdd, + new NumberExpression("z")); + var expressionPow = new PowExpression(expressionSub, new NumberExpression("k")); + Console.WriteLine(expressionPow.Interpret(context)); + Console.WriteLine("Please press Enter..."); + Console.ReadKey(); + #endregion + } +} + +/// +/// Агрегатор выражений +/// +class Context +{ + Dictionary variables; + + public Context() + { + variables = new Dictionary(); + } + + public int GetVariable(string name) + { + if(variables.ContainsKey(name)) + return variables[name]; + else + return -1; + } + + public void SetVariable(string name, int value) + { + if(variables.ContainsKey(name)) + variables[name] = value; + else + variables.Add(name, value); + } +} + +/// +/// Поведение интерпретатора +/// +interface IExpression +{ + int Interpret(Context context); +} + +/// +/// Терминальное выражение +/// +class NumberExpression : IExpression +{ + string Name { get; set; } + public NumberExpression(string name) + { + Name = name; + } + + public int Interpret(Context context) + { + return context.GetVariable(Name); + } +} + +/// +/// Нетерминальное выражение для сложения +/// +class AddExpression : IExpression +{ + IExpression LeftExpression { get; set; } + IExpression RightExpression { get; set; } + + public AddExpression(IExpression left, IExpression right) + { + LeftExpression = left; + RightExpression = right; + } + + public int Interpret(Context context) + { + return LeftExpression.Interpret(context) + RightExpression.Interpret(context); + } +} + +/// +/// Нетерминальное выражение для умножения +/// +class PowExpression : IExpression +{ + IExpression LeftExpression { get; set; } + IExpression RightExpression { get; set; } + + public PowExpression(IExpression left, IExpression right) + { + LeftExpression = left; + RightExpression = right; + } + + public int Interpret(Context context) + { + return LeftExpression.Interpret(context) * RightExpression.Interpret(context); + } +} + +/// +/// Нетерминальное выражение для вычитания +/// +class SubstructExpression : IExpression +{ + IExpression LeftExpression { get; set; } + IExpression RightExpression { get; set; } + + public SubstructExpression(IExpression left, IExpression right) + { + LeftExpression = left; + RightExpression = right; + } + + public int Interpret(Context context) + { + return LeftExpression.Interpret(context) - RightExpression.Interpret(context); + } +} \ No newline at end of file diff --git a/Patterns/Iterator/Iterator.csproj b/Patterns/Iterator/Iterator.csproj new file mode 100644 index 0000000..74abf5c --- /dev/null +++ b/Patterns/Iterator/Iterator.csproj @@ -0,0 +1,10 @@ + + + + Exe + net6.0 + enable + enable + + + diff --git a/Patterns/Iterator/Program.cs b/Patterns/Iterator/Program.cs new file mode 100644 index 0000000..9bfa1e8 --- /dev/null +++ b/Patterns/Iterator/Program.cs @@ -0,0 +1,263 @@ +/* Итератор + Предоставляет способ последовательного + доступа к множеству, независимо от его + внутреннего устройства + */ +class Program +{ + public static void Main(string[] args) + { + #region Пример №1 - базовое + Library library = new Library(); + Reader reader = new Reader(); + reader.SetBooks(library); + Console.ReadKey(); + #endregion + #region Пример №2 - пример работы стека + DataStack stack = new DataStack(); + for (int i = 0; i < 5; i++) + stack.Push(i); + + DataStack stackCopy = new DataStack(stack); + + Console.WriteLine(stack == stackCopy); //true + + stackCopy.Push(10); + + Console.WriteLine(stack == stackCopy); //false + #endregion + } +} + +/// +/// Читатель +/// +class Reader +{ + public void SetBooks(Library library) + { + IBookIterator iterator = library.CreateNumerator(); + while(iterator.HasNext()) + { + Book book = iterator.Next(); + Console.WriteLine(book.Name); + } + } +} + +/// +/// Поведение поиска библиотеки +/// +interface IBookIterator +{ + bool HasNext(); + Book Next(); +} + +/// +/// Поведение библиотеки +/// +interface IBookNumerable +{ + IBookIterator CreateNumerator(); + int Count { get; } + Book this[int index] { get; } +} + +/// +/// Класс книги +/// +class Book +{ + public string Name { get; set; } +} + +/// +/// Класс библиотеки книг +/// +class Library : IBookNumerable +{ + private Book[] Books { get; set; } + + public Library() + { + Books = new Book[] + { + new Book(){ Name = "James"}, + new Book(){ Name = "Karl"}, + new Book(){ Name = "Rogan"} + }; + } + + /// + /// Вызов книги + /// + /// индекс в библиотеке + /// Book + public Book this[int index] => Books[index]; + + /// + /// Количество книг в библиотеке + /// + public int Count => Books.Length; + + /// + /// Перейти к следующей библиотеке + /// + /// IBookIterator(LibraryNumenator) + public IBookIterator CreateNumerator() => new LibraryNumenator(this); +} + +class LibraryNumenator : IBookIterator +{ + IBookNumerable Aggregate { get; set; } + int index = 0; + + /// + /// Передача коллекции книг в Library + /// + /// + public LibraryNumenator(IBookNumerable bookNumerable) + { + Aggregate = bookNumerable; + } + + public bool HasNext() => index < Aggregate.Count; + + public Book Next() => Aggregate[index++]; +} + +/// +/// Класс стека данных +/// +public class DataStack +{ + private int[] items = new int[10]; + /// + /// Длинна массива данных в этом стеке + /// + private int lenght; + + public DataStack() => lenght = -1; + + /// + /// Для копирования экземпляра класса + /// + /// Экземпляр данного класса + public DataStack(DataStack myStack) + { + this.items = myStack.items; + this.lenght = myStack.lenght; + } + + /// + /// Свойство геттера для поля items + /// + public int[] Items { get => items; } + + /// + /// Свойство геттера для поля lenght + /// + public int Lenght { get => lenght; } + + /// + /// Добавление элементов в массив + /// + /// значение + public void Push(int value) => items[++lenght] = value; + + /// + /// Получение последнего элемента + /// + /// значение + public int Pop() => items[lenght--]; + + /// + /// Переопределение оператора сравнения двух экземпляров данного класса + /// + /// + /// + /// bool + public static bool operator ==(DataStack left, DataStack right) + { + StackIterator it1 = new StackIterator(left), + it2 = new StackIterator(right); + + while (it1.IsEnd() || it2.IsEnd()) + { + if (it1.Get() != it2.Get()) break; + it1++; + it2++; + } + + return !it1.IsEnd() && !it2.IsEnd(); + } + + /// + /// Переопределение оператора сравнения двух экземпляров данного класса + /// + /// + /// + /// bool + public static bool operator !=(DataStack left, DataStack right) + { + StackIterator it1 = new StackIterator(left), + it2 = new StackIterator(right); + + while (it1.IsEnd() || it2.IsEnd()) + { + if (it1.Get() != it2.Get()) break; + it1++; + it2++; + } + + return !it1.IsEnd() && !it2.IsEnd(); + } +} + +/// +/// Перечислитель +/// +class StackIterator +{ + private DataStack stack; + private int index; + + /// + /// Инициализируем поля перечислителя + /// + /// данные + public StackIterator(DataStack dataStack) + { + this.stack = dataStack; + this.index = 0; + } + + /// + /// Переопределение опреатора инкрементирования + /// + /// новый переданный экземпляр класса + /// экземпляр класса с инкрементированым значением index + public static StackIterator operator ++(StackIterator s) + { + s.index++; + return s; + } + + /// + /// Возвращает значение элемента поля стека + /// через его свойство по текущему индексу + /// + /// + public int Get() + { + if(index < stack.Lenght) return stack.Items[index]; + return 0; + } + + /// + /// Возвращет true при достижении предельного размера стека + /// + /// bool + public bool IsEnd() => index != stack.Lenght + 1; +} \ No newline at end of file diff --git a/Patterns/LetCode.Tests/LetCode.Tests.csproj b/Patterns/LetCode.Tests/LetCode.Tests.csproj new file mode 100644 index 0000000..a54203b --- /dev/null +++ b/Patterns/LetCode.Tests/LetCode.Tests.csproj @@ -0,0 +1,23 @@ + + + + net6.0 + enable + enable + + false + true + + + + + + + + + + + + + + diff --git a/Patterns/LetCode.Tests/Tests.cs b/Patterns/LetCode.Tests/Tests.cs new file mode 100644 index 0000000..7277e03 --- /dev/null +++ b/Patterns/LetCode.Tests/Tests.cs @@ -0,0 +1,65 @@ +namespace LetCode.Tests +{ + [TestClass] + public class Tests + { + /// + /// target + /// + [TestMethod] + public void TwoSumTest() + { + // arrange + int[] input = { 1, 2, 3 }; + int[] expected = { 0, 2 }; + + // act + var actual = LetCodeTasks.TwoSum(input, 4); + + // arrange + CollectionAssert.AreEqual(expected, actual, $"actual: {string.Join(',', actual)}, expected: {string.Join(',', expected)}"); + } + + [TestMethod] + public void IsPalindromeTest() + { + // arrange + int input = 99; + bool expected = true; + + // act + var actual = LetCodeTasks.IsPalindrome(input); + + // arrange + Assert.AreEqual(expected, actual, $"actual: {actual}, expected: {expected}"); + } + + [TestMethod] + public void RomanToIntTest() + { + // arrange + string input = "MCMXCIV"; + int expected = 1994; + + // act + var actual = LetCodeTasks.RomanToInt(input); + + // arrange + Assert.AreEqual(expected, actual, $"actual: {actual}, expected: {expected}"); + } + + [TestMethod] + public void LongestCommonPrefixTest() + { + // arrange + string[] input = { "XXVIII", "XX", "XXII" }; + string expected = "XX"; + + // act + var actual = LetCodeTasks.LongestCommonPrefix(input); + + // arrange + Assert.AreEqual(expected, actual, $"actual: {actual}, expected: {expected}"); + } + } +} \ No newline at end of file diff --git a/Patterns/LetCode.Tests/Usings.cs b/Patterns/LetCode.Tests/Usings.cs new file mode 100644 index 0000000..ab67c7e --- /dev/null +++ b/Patterns/LetCode.Tests/Usings.cs @@ -0,0 +1 @@ +global using Microsoft.VisualStudio.TestTools.UnitTesting; \ No newline at end of file diff --git a/Patterns/LetCode/LetCode.csproj b/Patterns/LetCode/LetCode.csproj new file mode 100644 index 0000000..74abf5c --- /dev/null +++ b/Patterns/LetCode/LetCode.csproj @@ -0,0 +1,10 @@ + + + + Exe + net6.0 + enable + enable + + + diff --git a/Patterns/LetCode/Program.cs b/Patterns/LetCode/Program.cs new file mode 100644 index 0000000..80ad718 --- /dev/null +++ b/Patterns/LetCode/Program.cs @@ -0,0 +1,160 @@ +public static class LetCodeTasks +{ + /// + /// Какие числа массива дают в сумме указанное число + /// + /// Массив чисел + /// Искомая сумма + /// Массив индексов чисел + public static int[] TwoSum(int[] nums, int target) + { + int countNew = 0; + int[] weeks = { }; + for (int k = 0; k < nums.Length-1; k++) + { + for(int i = 1; i < nums.Length; i++) + { + int a1 = nums[k]; + int a2 = nums[i]; + if (a1 + a2 == target) + { + if(k != i && k < i) + { + countNew++; + Array.Resize(ref weeks, weeks.Length + 2); + weeks[weeks.Length - 2] = k; + weeks[weeks.Length - 1] = i; + } + } + } + } + return weeks; + } + + /// + /// Проверяет число на верность свойствам полиндрома + /// + /// Число + /// Полиндром или нет + public static bool IsPalindrome(int x) + { + if(x.ToString().Length > 3) + { + for (int i = 0; i < x.ToString().Length; i++) + { + if (x.ToString()[i] != x.ToString()[x.ToString().Length - (i + 1)]) + return false; + } + } + if(x >= 0 && x.ToString()[0] == x.ToString()[x.ToString().Length-1]) + return true; + return false; + } + + /// + /// Переводит римские цифры в реальное число + /// + /// Римский символ + /// Число + public static int RomanToInt(string s) + { + var mapNumbers = new Dictionary() + { + { 1, 'I' }, { 5, 'V' }, { 10, 'X' }, { 50, 'L' }, { 100, 'C' }, { 500, 'D' }, { 1000, 'M' } + }; + char symTmp = ' '; + int[] sumArray = { }; + for (int i = 0; i < s.Length; i++) + { + foreach (var number in mapNumbers.Values) + { + if(number == s[i]) + { + int numberRes = 0; + switch($"{symTmp}{number}") + { + case "IV": + numberRes = 4; + Array.Resize(ref sumArray, sumArray.Length - 1); + break; + case "IX": + numberRes = 9; + Array.Resize(ref sumArray, sumArray.Length - 1); + break; + case "XL": + numberRes = 40; + Array.Resize(ref sumArray, sumArray.Length - 1); + break; + case "XC": + numberRes = 90; + Array.Resize(ref sumArray, sumArray.Length - 1); + break; + case "CD": + numberRes = 400; + Array.Resize(ref sumArray, sumArray.Length - 1); + break; + case "CM": + numberRes = 900; + Array.Resize(ref sumArray, sumArray.Length - 1); + break; + } + if(numberRes == 0) + numberRes = mapNumbers.Where(x => x.Value == number).FirstOrDefault().Key; + Array.Resize(ref sumArray, sumArray.Length + 1); + sumArray[sumArray.Length - 1] = numberRes; + symTmp = number; + } + } + } + return sumArray.Sum(); + } + + /// + /// Вычисляет совпадение частей слов в массиве слов + /// + /// Массив слов + /// Подстрока обобщающая все слова + public static string LongestCommonPrefix(string[] strs) + { + if (strs.Length == 0) + return ""; + if(strs.Length == 1) + return strs[0]; + string prefix = string.Empty; + int[] leghts = { }; + int tmpIndex = 0; + for (int i = 1; i < strs.Length; i++) + { + char[] word1 = strs[i-1].ToCharArray(); + char[] word2 = strs[i].ToCharArray(); + tmpIndex = 0; + for (int j = 0; j < word1.Length; j++) + { + if (word2.Length >= j + 1 && word1[j] == word2[j]) + { + tmpIndex++; + if (prefix.Length < j + 1) + prefix += word1[j]; + } + else + { + if (tmpIndex == 0) + return ""; + break; + } + } + Array.Resize(ref leghts, leghts.Length + 1); + leghts[leghts.Length - 1] = tmpIndex; + } + if (prefix.Length > 0) + prefix = prefix.Substring(0, leghts.Min()); + else + return ""; + return prefix; + } + + static void Main() + { + Console.ReadKey(); + } +} \ No newline at end of file diff --git a/Patterns/Mediator/Mediator.csproj b/Patterns/Mediator/Mediator.csproj new file mode 100644 index 0000000..74abf5c --- /dev/null +++ b/Patterns/Mediator/Mediator.csproj @@ -0,0 +1,10 @@ + + + + Exe + net6.0 + enable + enable + + + diff --git a/Patterns/Mediator/Program.cs b/Patterns/Mediator/Program.cs new file mode 100644 index 0000000..1b443e8 --- /dev/null +++ b/Patterns/Mediator/Program.cs @@ -0,0 +1,112 @@ +/* Посредник + Определяет объект инкапсулирующий способ + взаимодействия объектов. Обеспечивает слабую связь, + избавляя их от необходимости ссылаться друг на друга + и даёт возможность независимо изменять их взаимодействие. + */ +class Program +{ + public static void Main(string[] args) + { + #region Пример №1 - базовое + ManagerMediator mediator = new ManagerMediator(); + Colleague customer = new CustomerCollegue(mediator); + Colleague programmer = new ProgrammerCollegue(mediator); + Colleague tester = new TesterCollegue(mediator); + mediator.Customer = customer; + mediator.Programmer = programmer; + mediator.Tester = tester; + customer.Send("Есть заказ! Нужно сделать REST API"); + programmer.Send("REST API готов, нужно протестировать swagger"); + tester.Send("Тест прошёл успешно, документация отличная!"); + Console.ReadKey(); + #endregion + } +} + +/// +/// Интерфейс для взаимодействия с посредником +/// +abstract class Mediator +{ + public abstract void Send(string message, Colleague colleague); +} + +/// +/// Интерфейс для взаимодействия с коллегами +/// +abstract class Colleague +{ + Mediator Mediator { get; set; } + + public Colleague(Mediator mediator) + { + Mediator = mediator; + } + + public virtual void Send(string message) + { + Mediator.Send(message, this); + } + + public abstract void Notify(string message); +} + +/// +/// Непосредственный заказчик +/// +class CustomerCollegue : Colleague +{ + public CustomerCollegue(Mediator mediator) : base(mediator) {} + + public override void Notify(string message) + { + Console.WriteLine($"Сообщение заказчику: {message}"); + } +} + +/// +/// Программист +/// +class ProgrammerCollegue : Colleague +{ + public ProgrammerCollegue(Mediator mediator) : base(mediator) { } + + public override void Notify(string message) + { + Console.WriteLine($"Сообщение программисту: {message}"); + } +} + +/// +/// Тестировщик +/// +class TesterCollegue : Colleague +{ + public TesterCollegue(Mediator mediator) : base(mediator) { } + + public override void Notify(string message) + { + Console.WriteLine($"Сообщение тестировщику: {message}"); + } +} + +/// +/// Посредник +/// +class ManagerMediator : Mediator +{ + public Colleague Customer { get; set; } + public Colleague Programmer { get; set; } + public Colleague Tester { get; set; } + + public override void Send(string message, Colleague colleague) + { + if(Customer == colleague) //если отправитель заказчик значит есть новый заказ + Programmer.Notify(message); //отправляем сообщение программисту - сделать заказ + else if(Programmer == colleague) //если отправитель программист + Tester.Notify(message); //отправляем сообщение тестировщику + else if(Tester == colleague) //если отправитель тестировщик + Customer.Notify(message); //значит оповещаем заказчика + } +} \ No newline at end of file diff --git a/Patterns/Memento/Memento.csproj b/Patterns/Memento/Memento.csproj new file mode 100644 index 0000000..5eb1e84 --- /dev/null +++ b/Patterns/Memento/Memento.csproj @@ -0,0 +1,10 @@ + + + + Exe + net6.0 + enable + disable + + + diff --git a/Patterns/Memento/Program.cs b/Patterns/Memento/Program.cs new file mode 100644 index 0000000..b2f6dcd --- /dev/null +++ b/Patterns/Memento/Program.cs @@ -0,0 +1,119 @@ +/* Хранитель + Одиночка + Не нарушая инкапсуляцию, определяет + и сохраняет внутреннее состояние объекта и + позволяет позже восстановить объект в этом + состоянии + */ +class Program +{ + public static void Main(string[] args) + { + #region Пример №1 - базовое + using (var hero = new Hero()) + { + hero.Shoot(); + } + using (var heroMan = new Hero()) + { + heroMan.RestoreState(GameHistory.Instance.History.Pop()); + heroMan.Shoot(); + } + Console.ReadKey(); + #endregion + } +} + +/// +/// Класс героя +/// +class Hero : IDisposable +{ + /// + /// Количество патронов + /// + private int patrons = 10; + + /// + /// Выстрел + /// + public void Shoot() + { + if(patrons > 0) + { + patrons--; + Console.WriteLine($"Осталось {patrons} патронов..."); + } + else + Console.WriteLine("Нет патронов"); + } + + /// + /// Сохранение состояния + /// + /// + public HeroMemento SaveState() + { + Console.WriteLine($"Сохранено - {patrons}"); + return new HeroMemento(patrons); + } + + /// + /// Восстановление состояния + /// + /// Хранитель состояния + public void RestoreState(HeroMemento memento) + { + patrons = memento.Patrons; + Console.WriteLine($"Загружено - {patrons}"); + } + + /// + /// Удаление из памяти + сохранение в истории последнего состояния + /// + public void Dispose() + { + GameHistory.Instance.History.Push(SaveState()); + } +} + +/// +/// Memento - Хранитель состояния +/// +class HeroMemento +{ + public int Patrons { get; private set; } + + public HeroMemento(int patrons) + { + Patrons = patrons; + } +} + +/// +/// Caretaker - смотритель состояния +/// +class GameHistory +{ + private static GameHistory instance; + public Stack History { get; set; } + + private GameHistory() + { + History = new Stack(); + } + + public static GameHistory Instance + { + get + { + if(instance == null) + instance = new GameHistory(); + return instance; + } + } + + public void Clear() + { + History.Clear(); + } +} \ No newline at end of file diff --git a/Patterns/Observer/Observer.csproj b/Patterns/Observer/Observer.csproj new file mode 100644 index 0000000..74abf5c --- /dev/null +++ b/Patterns/Observer/Observer.csproj @@ -0,0 +1,10 @@ + + + + Exe + net6.0 + enable + enable + + + diff --git a/Patterns/Observer/Program.cs b/Patterns/Observer/Program.cs new file mode 100644 index 0000000..d7c283d --- /dev/null +++ b/Patterns/Observer/Program.cs @@ -0,0 +1,103 @@ +/* Наблюдатель + Определяет зависимость один ко многим + между объектами так, что когда один меняет + своё состояние, все зависимые объекты оповещаются + и обновляются автоматически + */ +class Program +{ + static void Main() + { + #region Пример №1 - базовое + var concreteObservable = new ConcreteObservable(); + concreteObservable.AddObserver(new Observer("Job")); + concreteObservable.AddObserver(new Observer("Robin")); + concreteObservable.AddObserver(new Observer("Jaz")); + concreteObservable.AddObserver(new Observer("John")); + Console.ReadKey(); + #endregion + } +} + +/// +/// Поведение наблюдателя +/// +interface IObservable +{ + /// + /// Добавить наблюдаемого + /// + /// Наблюдаемый + void AddObserver(IObserver observer); + /// + /// Удалить наблюдаемого + /// + /// Наблюдаемый + void RemoveObserver(IObserver observer); + /// + /// Оповестить всех наблюдаемых + /// + void NotifyObservers(); +} + +/// +/// Реализация конкретного наблюдателя +/// +class ConcreteObservable : IObservable +{ + /// + /// Список наблюдаемых + /// + private List _observers; + + public ConcreteObservable() + { + _observers = new List(); + } + + public void AddObserver(IObserver observer) + { + Console.WriteLine("Event Add Observer"); + NotifyObservers(); + _observers.Add(observer); + } + + public void NotifyObservers() + { + if(_observers.Count == 0) Console.WriteLine("Не кого оповещать..."); + foreach (var observer in _observers) + observer.Update(); + } + + public void RemoveObserver(IObserver observer) + { + _observers.Remove(observer); + NotifyObservers(); + } +} + +/// +/// Поведение наблюдаемого +/// +interface IObserver +{ + void Update(); +} + +/// +/// Наблюдаемый +/// +class Observer : IObserver +{ + public string Name { get; set; } + + public Observer(string name) + { + Name = name; + } + + public void Update() + { + Console.WriteLine($"Update {Name}"); + } +} \ No newline at end of file diff --git a/Patterns/Patterns Programming.sln b/Patterns/Patterns Programming.sln new file mode 100644 index 0000000..74d697b --- /dev/null +++ b/Patterns/Patterns Programming.sln @@ -0,0 +1,269 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.2.32616.157 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Behavioral(Поведенческие)", "Behavioral(Поведенческие)", "{749199BB-F36F-4019-BFEB-B04475AB5140}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Structural(Структурные)", "Structural(Структурные)", "{3E3D01F2-BFF2-417A-BEAD-0E0AD3547A8D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Creational(Порождающие)", "Creational(Порождающие)", "{6B6B76CA-287A-4FA5-99FE-8098611020F9}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Memento", "Memento\Memento.csproj", "{B4BD097B-27B4-4AAE-AC40-E0CA633B2A32}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ChainOfResponsibility", "ChainOfResponsibility\ChainOfResponsibility.csproj", "{CFC9F6BF-FC2B-446E-8FB5-92A1E06CAE91}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Observer", "Observer\Observer.csproj", "{72179984-1F4B-4C89-8E29-49D8C8B18A94}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Command", "Command\Command.csproj", "{C4EBB3CE-6BBD-473E-8CAC-012015F8FEA1}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "State", "State\State.csproj", "{5EA8980C-B0B1-4C20-93C8-92EFE4B88708}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Interpreter", "Interpreter\Interpreter.csproj", "{E470CB5E-7369-44DB-8192-5A2567865A83}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Strategy", "Strategy\Strategy.csproj", "{6566D5A3-F886-4E66-9E98-7FA536D7B4D4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Iterator", "Iterator\Iterator.csproj", "{2BFCAE0E-EBBC-4673-AC56-AA007679A15F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TemplateMethod", "TemplateMethod\TemplateMethod.csproj", "{2411F3F1-D28B-4939-85D9-921847678065}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mediator", "Mediator\Mediator.csproj", "{09C6E1FA-6553-4C92-9D38-613A9A8D155B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Visitor", "Visitor\Visitor.csproj", "{737EB7A2-98B4-473A-81B9-9CAB3BEB69CF}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Base Logic(Базовые понятия)", "Base Logic(Базовые понятия)", "{4FF822AA-F380-4D92-86B0-50FE5CE6BCEE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BaseInfo", "Base\BaseInfo.csproj", "{3E397CB2-2AAF-4D66-855D-E2BA198C380E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Base.Tests", "BaseTests\Base.Tests.csproj", "{90CB9984-E9D1-4821-BA45-D2C668A81813}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DictionaryInfo", "Dict\DictionaryInfo.csproj", "{279CA287-2FCE-45C7-BBD8-4E3941B09028}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LetCode", "LetCode\LetCode.csproj", "{71DA93E5-2EB8-4C26-9537-3C1F18DFEC15}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Adapter", "Adapter\Adapter.csproj", "{467EF678-626C-4CBB-B608-234CA2DD8613}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Proxy", "Proxy\Proxy.csproj", "{6BED2E46-471C-484E-A7BA-EFD41A981EF3}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bridge", "Bridge\Bridge.csproj", "{47297A10-E472-454B-B333-5554789B8D21}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Composite", "Composite\Composite.csproj", "{34A7974D-A37A-4D79-AF2A-5EECC9295884}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Decorator", "Decorator\Decorator.csproj", "{751A645A-8E65-4556-A322-5170CC3CA905}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Facade", "Facade\Facade.csproj", "{770B90B9-DD17-4279-AE68-FCC6E3783D05}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flyweight", "Flyweight\Flyweight.csproj", "{A0DB1337-5532-49C3-99DD-BEBE27F9B382}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AbstractFactory", "AbstractFactory\AbstractFactory.csproj", "{28A8AFD1-7FDB-45E4-A349-1BDD1FEB53C2}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FactoryMethod", "FactoryMethod\FactoryMethod.csproj", "{206CBCB3-8D1F-47A7-B510-AC9D34C8CBD3}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Builder", "Builder\Builder.csproj", "{B4567CE3-9BEC-445E-8830-B4B206FA7641}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentBuilder", "FluentBuilder\FluentBuilder.csproj", "{BA3B2D0E-484B-4075-92F5-D84B10EFDE4D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Prototype", "Prototype\Prototype.csproj", "{F92E5A05-034A-43E4-A7DB-0073C3E322EC}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Singleton", "Singleton\Singleton.csproj", "{E17B2354-AD60-4083-BA38-6A9BD85F81B3}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LetCode.Tests", "LetCode.Tests\LetCode.Tests.csproj", "{34F0E125-BE37-42FF-A679-4EBA9F29D86D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Принципы проектирования", "Принципы проектирования", "{941BD935-75AD-4FEC-8D97-FD5D55905CF1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "1_Принцип единственной обязанности", "1_Принцип единственной обязанности\1_Принцип единственной обязанности.csproj", "{4CEA5C3D-9E87-4AF9-8683-905A46D7006C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "2_Принцип открытости, закрытости", "2_Принцип открытости, закрытости\2_Принцип открытости, закрытости.csproj", "{9CB78E60-6FFB-47C3-9BF3-F20FD7573C80}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "3_Принцип подстановки Барбары Лисков", "3_Принцип подстановки Барбары Лисков\3_Принцип подстановки Барбары Лисков.csproj", "{9A9FCDC5-8E2E-4CD1-9DCB-204A6A166732}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "4_Принцип разделения интерфейсов", "4_Принцип разделения интерфейсов\4_Принцип разделения интерфейсов.csproj", "{0268644C-135F-4217-AC55-B9139E2EA41B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "5_Принцип инверсии зависимостей", "5_Принцип инверсии зависимостей\5_Принцип инверсии зависимостей.csproj", "{C7CF08B8-7D0D-47D0-BA43-2488EF6E16E6}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B4BD097B-27B4-4AAE-AC40-E0CA633B2A32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B4BD097B-27B4-4AAE-AC40-E0CA633B2A32}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B4BD097B-27B4-4AAE-AC40-E0CA633B2A32}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B4BD097B-27B4-4AAE-AC40-E0CA633B2A32}.Release|Any CPU.Build.0 = Release|Any CPU + {CFC9F6BF-FC2B-446E-8FB5-92A1E06CAE91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CFC9F6BF-FC2B-446E-8FB5-92A1E06CAE91}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CFC9F6BF-FC2B-446E-8FB5-92A1E06CAE91}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CFC9F6BF-FC2B-446E-8FB5-92A1E06CAE91}.Release|Any CPU.Build.0 = Release|Any CPU + {72179984-1F4B-4C89-8E29-49D8C8B18A94}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {72179984-1F4B-4C89-8E29-49D8C8B18A94}.Debug|Any CPU.Build.0 = Debug|Any CPU + {72179984-1F4B-4C89-8E29-49D8C8B18A94}.Release|Any CPU.ActiveCfg = Release|Any CPU + {72179984-1F4B-4C89-8E29-49D8C8B18A94}.Release|Any CPU.Build.0 = Release|Any CPU + {C4EBB3CE-6BBD-473E-8CAC-012015F8FEA1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C4EBB3CE-6BBD-473E-8CAC-012015F8FEA1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C4EBB3CE-6BBD-473E-8CAC-012015F8FEA1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C4EBB3CE-6BBD-473E-8CAC-012015F8FEA1}.Release|Any CPU.Build.0 = Release|Any CPU + {5EA8980C-B0B1-4C20-93C8-92EFE4B88708}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5EA8980C-B0B1-4C20-93C8-92EFE4B88708}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5EA8980C-B0B1-4C20-93C8-92EFE4B88708}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5EA8980C-B0B1-4C20-93C8-92EFE4B88708}.Release|Any CPU.Build.0 = Release|Any CPU + {E470CB5E-7369-44DB-8192-5A2567865A83}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E470CB5E-7369-44DB-8192-5A2567865A83}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E470CB5E-7369-44DB-8192-5A2567865A83}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E470CB5E-7369-44DB-8192-5A2567865A83}.Release|Any CPU.Build.0 = Release|Any CPU + {6566D5A3-F886-4E66-9E98-7FA536D7B4D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6566D5A3-F886-4E66-9E98-7FA536D7B4D4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6566D5A3-F886-4E66-9E98-7FA536D7B4D4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6566D5A3-F886-4E66-9E98-7FA536D7B4D4}.Release|Any CPU.Build.0 = Release|Any CPU + {2BFCAE0E-EBBC-4673-AC56-AA007679A15F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2BFCAE0E-EBBC-4673-AC56-AA007679A15F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2BFCAE0E-EBBC-4673-AC56-AA007679A15F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2BFCAE0E-EBBC-4673-AC56-AA007679A15F}.Release|Any CPU.Build.0 = Release|Any CPU + {2411F3F1-D28B-4939-85D9-921847678065}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2411F3F1-D28B-4939-85D9-921847678065}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2411F3F1-D28B-4939-85D9-921847678065}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2411F3F1-D28B-4939-85D9-921847678065}.Release|Any CPU.Build.0 = Release|Any CPU + {09C6E1FA-6553-4C92-9D38-613A9A8D155B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {09C6E1FA-6553-4C92-9D38-613A9A8D155B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {09C6E1FA-6553-4C92-9D38-613A9A8D155B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {09C6E1FA-6553-4C92-9D38-613A9A8D155B}.Release|Any CPU.Build.0 = Release|Any CPU + {737EB7A2-98B4-473A-81B9-9CAB3BEB69CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {737EB7A2-98B4-473A-81B9-9CAB3BEB69CF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {737EB7A2-98B4-473A-81B9-9CAB3BEB69CF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {737EB7A2-98B4-473A-81B9-9CAB3BEB69CF}.Release|Any CPU.Build.0 = Release|Any CPU + {3E397CB2-2AAF-4D66-855D-E2BA198C380E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3E397CB2-2AAF-4D66-855D-E2BA198C380E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3E397CB2-2AAF-4D66-855D-E2BA198C380E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3E397CB2-2AAF-4D66-855D-E2BA198C380E}.Release|Any CPU.Build.0 = Release|Any CPU + {90CB9984-E9D1-4821-BA45-D2C668A81813}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {90CB9984-E9D1-4821-BA45-D2C668A81813}.Debug|Any CPU.Build.0 = Debug|Any CPU + {90CB9984-E9D1-4821-BA45-D2C668A81813}.Release|Any CPU.ActiveCfg = Release|Any CPU + {90CB9984-E9D1-4821-BA45-D2C668A81813}.Release|Any CPU.Build.0 = Release|Any CPU + {279CA287-2FCE-45C7-BBD8-4E3941B09028}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {279CA287-2FCE-45C7-BBD8-4E3941B09028}.Debug|Any CPU.Build.0 = Debug|Any CPU + {279CA287-2FCE-45C7-BBD8-4E3941B09028}.Release|Any CPU.ActiveCfg = Release|Any CPU + {279CA287-2FCE-45C7-BBD8-4E3941B09028}.Release|Any CPU.Build.0 = Release|Any CPU + {71DA93E5-2EB8-4C26-9537-3C1F18DFEC15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {71DA93E5-2EB8-4C26-9537-3C1F18DFEC15}.Debug|Any CPU.Build.0 = Debug|Any CPU + {71DA93E5-2EB8-4C26-9537-3C1F18DFEC15}.Release|Any CPU.ActiveCfg = Release|Any CPU + {71DA93E5-2EB8-4C26-9537-3C1F18DFEC15}.Release|Any CPU.Build.0 = Release|Any CPU + {467EF678-626C-4CBB-B608-234CA2DD8613}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {467EF678-626C-4CBB-B608-234CA2DD8613}.Debug|Any CPU.Build.0 = Debug|Any CPU + {467EF678-626C-4CBB-B608-234CA2DD8613}.Release|Any CPU.ActiveCfg = Release|Any CPU + {467EF678-626C-4CBB-B608-234CA2DD8613}.Release|Any CPU.Build.0 = Release|Any CPU + {6BED2E46-471C-484E-A7BA-EFD41A981EF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6BED2E46-471C-484E-A7BA-EFD41A981EF3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6BED2E46-471C-484E-A7BA-EFD41A981EF3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6BED2E46-471C-484E-A7BA-EFD41A981EF3}.Release|Any CPU.Build.0 = Release|Any CPU + {47297A10-E472-454B-B333-5554789B8D21}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {47297A10-E472-454B-B333-5554789B8D21}.Debug|Any CPU.Build.0 = Debug|Any CPU + {47297A10-E472-454B-B333-5554789B8D21}.Release|Any CPU.ActiveCfg = Release|Any CPU + {47297A10-E472-454B-B333-5554789B8D21}.Release|Any CPU.Build.0 = Release|Any CPU + {34A7974D-A37A-4D79-AF2A-5EECC9295884}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {34A7974D-A37A-4D79-AF2A-5EECC9295884}.Debug|Any CPU.Build.0 = Debug|Any CPU + {34A7974D-A37A-4D79-AF2A-5EECC9295884}.Release|Any CPU.ActiveCfg = Release|Any CPU + {34A7974D-A37A-4D79-AF2A-5EECC9295884}.Release|Any CPU.Build.0 = Release|Any CPU + {751A645A-8E65-4556-A322-5170CC3CA905}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {751A645A-8E65-4556-A322-5170CC3CA905}.Debug|Any CPU.Build.0 = Debug|Any CPU + {751A645A-8E65-4556-A322-5170CC3CA905}.Release|Any CPU.ActiveCfg = Release|Any CPU + {751A645A-8E65-4556-A322-5170CC3CA905}.Release|Any CPU.Build.0 = Release|Any CPU + {770B90B9-DD17-4279-AE68-FCC6E3783D05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {770B90B9-DD17-4279-AE68-FCC6E3783D05}.Debug|Any CPU.Build.0 = Debug|Any CPU + {770B90B9-DD17-4279-AE68-FCC6E3783D05}.Release|Any CPU.ActiveCfg = Release|Any CPU + {770B90B9-DD17-4279-AE68-FCC6E3783D05}.Release|Any CPU.Build.0 = Release|Any CPU + {A0DB1337-5532-49C3-99DD-BEBE27F9B382}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A0DB1337-5532-49C3-99DD-BEBE27F9B382}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A0DB1337-5532-49C3-99DD-BEBE27F9B382}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A0DB1337-5532-49C3-99DD-BEBE27F9B382}.Release|Any CPU.Build.0 = Release|Any CPU + {28A8AFD1-7FDB-45E4-A349-1BDD1FEB53C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {28A8AFD1-7FDB-45E4-A349-1BDD1FEB53C2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {28A8AFD1-7FDB-45E4-A349-1BDD1FEB53C2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {28A8AFD1-7FDB-45E4-A349-1BDD1FEB53C2}.Release|Any CPU.Build.0 = Release|Any CPU + {206CBCB3-8D1F-47A7-B510-AC9D34C8CBD3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {206CBCB3-8D1F-47A7-B510-AC9D34C8CBD3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {206CBCB3-8D1F-47A7-B510-AC9D34C8CBD3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {206CBCB3-8D1F-47A7-B510-AC9D34C8CBD3}.Release|Any CPU.Build.0 = Release|Any CPU + {B4567CE3-9BEC-445E-8830-B4B206FA7641}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B4567CE3-9BEC-445E-8830-B4B206FA7641}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B4567CE3-9BEC-445E-8830-B4B206FA7641}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B4567CE3-9BEC-445E-8830-B4B206FA7641}.Release|Any CPU.Build.0 = Release|Any CPU + {BA3B2D0E-484B-4075-92F5-D84B10EFDE4D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BA3B2D0E-484B-4075-92F5-D84B10EFDE4D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BA3B2D0E-484B-4075-92F5-D84B10EFDE4D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BA3B2D0E-484B-4075-92F5-D84B10EFDE4D}.Release|Any CPU.Build.0 = Release|Any CPU + {F92E5A05-034A-43E4-A7DB-0073C3E322EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F92E5A05-034A-43E4-A7DB-0073C3E322EC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F92E5A05-034A-43E4-A7DB-0073C3E322EC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F92E5A05-034A-43E4-A7DB-0073C3E322EC}.Release|Any CPU.Build.0 = Release|Any CPU + {E17B2354-AD60-4083-BA38-6A9BD85F81B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E17B2354-AD60-4083-BA38-6A9BD85F81B3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E17B2354-AD60-4083-BA38-6A9BD85F81B3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E17B2354-AD60-4083-BA38-6A9BD85F81B3}.Release|Any CPU.Build.0 = Release|Any CPU + {34F0E125-BE37-42FF-A679-4EBA9F29D86D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {34F0E125-BE37-42FF-A679-4EBA9F29D86D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {34F0E125-BE37-42FF-A679-4EBA9F29D86D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {34F0E125-BE37-42FF-A679-4EBA9F29D86D}.Release|Any CPU.Build.0 = Release|Any CPU + {4CEA5C3D-9E87-4AF9-8683-905A46D7006C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4CEA5C3D-9E87-4AF9-8683-905A46D7006C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4CEA5C3D-9E87-4AF9-8683-905A46D7006C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4CEA5C3D-9E87-4AF9-8683-905A46D7006C}.Release|Any CPU.Build.0 = Release|Any CPU + {9CB78E60-6FFB-47C3-9BF3-F20FD7573C80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9CB78E60-6FFB-47C3-9BF3-F20FD7573C80}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9CB78E60-6FFB-47C3-9BF3-F20FD7573C80}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9CB78E60-6FFB-47C3-9BF3-F20FD7573C80}.Release|Any CPU.Build.0 = Release|Any CPU + {9A9FCDC5-8E2E-4CD1-9DCB-204A6A166732}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9A9FCDC5-8E2E-4CD1-9DCB-204A6A166732}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9A9FCDC5-8E2E-4CD1-9DCB-204A6A166732}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9A9FCDC5-8E2E-4CD1-9DCB-204A6A166732}.Release|Any CPU.Build.0 = Release|Any CPU + {0268644C-135F-4217-AC55-B9139E2EA41B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0268644C-135F-4217-AC55-B9139E2EA41B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0268644C-135F-4217-AC55-B9139E2EA41B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0268644C-135F-4217-AC55-B9139E2EA41B}.Release|Any CPU.Build.0 = Release|Any CPU + {C7CF08B8-7D0D-47D0-BA43-2488EF6E16E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C7CF08B8-7D0D-47D0-BA43-2488EF6E16E6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C7CF08B8-7D0D-47D0-BA43-2488EF6E16E6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C7CF08B8-7D0D-47D0-BA43-2488EF6E16E6}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {B4BD097B-27B4-4AAE-AC40-E0CA633B2A32} = {749199BB-F36F-4019-BFEB-B04475AB5140} + {CFC9F6BF-FC2B-446E-8FB5-92A1E06CAE91} = {749199BB-F36F-4019-BFEB-B04475AB5140} + {72179984-1F4B-4C89-8E29-49D8C8B18A94} = {749199BB-F36F-4019-BFEB-B04475AB5140} + {C4EBB3CE-6BBD-473E-8CAC-012015F8FEA1} = {749199BB-F36F-4019-BFEB-B04475AB5140} + {5EA8980C-B0B1-4C20-93C8-92EFE4B88708} = {749199BB-F36F-4019-BFEB-B04475AB5140} + {E470CB5E-7369-44DB-8192-5A2567865A83} = {749199BB-F36F-4019-BFEB-B04475AB5140} + {6566D5A3-F886-4E66-9E98-7FA536D7B4D4} = {749199BB-F36F-4019-BFEB-B04475AB5140} + {2BFCAE0E-EBBC-4673-AC56-AA007679A15F} = {749199BB-F36F-4019-BFEB-B04475AB5140} + {2411F3F1-D28B-4939-85D9-921847678065} = {749199BB-F36F-4019-BFEB-B04475AB5140} + {09C6E1FA-6553-4C92-9D38-613A9A8D155B} = {749199BB-F36F-4019-BFEB-B04475AB5140} + {737EB7A2-98B4-473A-81B9-9CAB3BEB69CF} = {749199BB-F36F-4019-BFEB-B04475AB5140} + {3E397CB2-2AAF-4D66-855D-E2BA198C380E} = {4FF822AA-F380-4D92-86B0-50FE5CE6BCEE} + {90CB9984-E9D1-4821-BA45-D2C668A81813} = {4FF822AA-F380-4D92-86B0-50FE5CE6BCEE} + {279CA287-2FCE-45C7-BBD8-4E3941B09028} = {4FF822AA-F380-4D92-86B0-50FE5CE6BCEE} + {71DA93E5-2EB8-4C26-9537-3C1F18DFEC15} = {4FF822AA-F380-4D92-86B0-50FE5CE6BCEE} + {467EF678-626C-4CBB-B608-234CA2DD8613} = {3E3D01F2-BFF2-417A-BEAD-0E0AD3547A8D} + {6BED2E46-471C-484E-A7BA-EFD41A981EF3} = {3E3D01F2-BFF2-417A-BEAD-0E0AD3547A8D} + {47297A10-E472-454B-B333-5554789B8D21} = {3E3D01F2-BFF2-417A-BEAD-0E0AD3547A8D} + {34A7974D-A37A-4D79-AF2A-5EECC9295884} = {3E3D01F2-BFF2-417A-BEAD-0E0AD3547A8D} + {751A645A-8E65-4556-A322-5170CC3CA905} = {3E3D01F2-BFF2-417A-BEAD-0E0AD3547A8D} + {770B90B9-DD17-4279-AE68-FCC6E3783D05} = {3E3D01F2-BFF2-417A-BEAD-0E0AD3547A8D} + {A0DB1337-5532-49C3-99DD-BEBE27F9B382} = {3E3D01F2-BFF2-417A-BEAD-0E0AD3547A8D} + {28A8AFD1-7FDB-45E4-A349-1BDD1FEB53C2} = {6B6B76CA-287A-4FA5-99FE-8098611020F9} + {206CBCB3-8D1F-47A7-B510-AC9D34C8CBD3} = {6B6B76CA-287A-4FA5-99FE-8098611020F9} + {B4567CE3-9BEC-445E-8830-B4B206FA7641} = {6B6B76CA-287A-4FA5-99FE-8098611020F9} + {BA3B2D0E-484B-4075-92F5-D84B10EFDE4D} = {6B6B76CA-287A-4FA5-99FE-8098611020F9} + {F92E5A05-034A-43E4-A7DB-0073C3E322EC} = {6B6B76CA-287A-4FA5-99FE-8098611020F9} + {E17B2354-AD60-4083-BA38-6A9BD85F81B3} = {6B6B76CA-287A-4FA5-99FE-8098611020F9} + {34F0E125-BE37-42FF-A679-4EBA9F29D86D} = {4FF822AA-F380-4D92-86B0-50FE5CE6BCEE} + {4CEA5C3D-9E87-4AF9-8683-905A46D7006C} = {941BD935-75AD-4FEC-8D97-FD5D55905CF1} + {9CB78E60-6FFB-47C3-9BF3-F20FD7573C80} = {941BD935-75AD-4FEC-8D97-FD5D55905CF1} + {9A9FCDC5-8E2E-4CD1-9DCB-204A6A166732} = {941BD935-75AD-4FEC-8D97-FD5D55905CF1} + {0268644C-135F-4217-AC55-B9139E2EA41B} = {941BD935-75AD-4FEC-8D97-FD5D55905CF1} + {C7CF08B8-7D0D-47D0-BA43-2488EF6E16E6} = {941BD935-75AD-4FEC-8D97-FD5D55905CF1} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {6A7DE462-3436-49E8-A6F0-59158DFB417F} + EndGlobalSection +EndGlobal diff --git a/Patterns/Prototype/Program.cs b/Patterns/Prototype/Program.cs new file mode 100644 index 0000000..85c2c74 --- /dev/null +++ b/Patterns/Prototype/Program.cs @@ -0,0 +1,132 @@ +/* Прототип + Определяет несколько видов объектов, + чтобы при создании использовать объект-прототип + и создаёт новые объекты, копируя прототип + (техника клонирования объектов) + */ +class Program +{ + static void Main() + { + #region Пример №1 - базовое + IFigure cube = new Cube(10, 10); + IFigure cloneCube = cube.Clone(); + IFigure cloneMemberCube = cube.CloneMember(); + cube.GetInfo(); + cloneCube.GetInfo(); + cloneMemberCube.GetInfo(); + #endregion + + #region Пример №2 + IEntity entity = new Predator(10, 1000); + var clone = entity.CloneEntity(); + entity.GetInfo(); + clone.GetInfo(); + Console.ReadKey(); + #endregion + } +} + +/// +/// Поведение фигуры +/// +interface IFigure +{ + IFigure Clone(); + IFigure? CloneMember(); + void GetInfo(); +} + +/// +/// Шаблон куба +/// +class Cube : IFigure +{ + int Width { get; set; } + int Height { get; set; } + + public Cube(int width, int heght) + { + Width = width; + Height = heght; + } + + public IFigure Clone() + { + return new Cube(Width, Height); + } + + public IFigure? CloneMember() + { + return this.MemberwiseClone() as IFigure; + } + + public void GetInfo() + { + Console.WriteLine($"Cube {Width}/{Height}"); + } +} + +/// +/// Треугольник +/// +class Rect : IFigure +{ + int Width { get; set; } + int Height { get; set; } + + public Rect(int width, int heght) + { + Width = width; + Height = heght; + } + + public IFigure Clone() + { + return new Rect(Width, Height); + } + + public IFigure? CloneMember() + { + return this.MemberwiseClone() as IFigure; + } + + public void GetInfo() + { + Console.WriteLine($"Rect {Width}/{Height}"); + } +} + +/// +/// Поведение сущности +/// +interface IEntity +{ + IEntity CloneEntity(); + void GetInfo(); +} + +abstract record Animal(int Paws, int Weight) : IEntity +{ + public abstract IEntity CloneEntity(); + public abstract void GetInfo(); +} + +record Predator(int Paws, int Weight) : Animal(Paws, Weight) +{ + public override IEntity CloneEntity() + => this with { }; + + public override void GetInfo() + => Console.WriteLine($"Predator w={Weight} p={Paws}"); +} + +record Person(int IQ) : IEntity +{ + public IEntity CloneEntity() + => this with { }; + + public void GetInfo() + => Console.WriteLine($"Peaple with IQ={IQ}"); +} + diff --git a/Patterns/Prototype/Prototype.csproj b/Patterns/Prototype/Prototype.csproj new file mode 100644 index 0000000..74abf5c --- /dev/null +++ b/Patterns/Prototype/Prototype.csproj @@ -0,0 +1,10 @@ + + + + Exe + net6.0 + enable + enable + + + diff --git a/Patterns/Proxy/Program.cs b/Patterns/Proxy/Program.cs new file mode 100644 index 0000000..71d2a38 --- /dev/null +++ b/Patterns/Proxy/Program.cs @@ -0,0 +1,94 @@ +using Microsoft.EntityFrameworkCore; +/* Заместитель + Предоставляет объект-заместитель другого объекта + для контроля доступа к нему + */ +class Program +{ + static void Main() + { + #region Пример №1 - базовое + using (IBook book = new BookStoreProxy()) + { + //читаем первую страницу + Page page1 = book.GetPage(1); + Console.WriteLine(page1.Text); + //читаем первую страницу + Page page2 = book.GetPage(2); + Console.WriteLine(page1.Text); + //возвращаемся на первую страницу + page1 = book.GetPage(1); + Console.WriteLine(page1.Text); + } + Console.ReadKey(); + #endregion + } +} + +/// +/// отдельная страница книги +/// +/// Идентификатор +/// Номер +/// Содержимое +record Page(int Id, int Number, string Text); + +class PageContext : DbContext +{ + public DbSet Pages { get; set; } +} + +interface IBook : IDisposable +{ + Page GetPage(int number); +} + +class BookStore : IBook +{ + PageContext db; + + public BookStore() + { + db = new PageContext(); + } + + public void Dispose() + { + db.Dispose(); + } + + public Page GetPage(int number) + { + return db.Pages.FirstOrDefault(p => p.Number == number); + } +} + +class BookStoreProxy : IBook +{ + List Pages; + BookStore bookStore; + + public BookStoreProxy() + { + Pages = new List(); + } + + public void Dispose() + { + if (bookStore != null) + bookStore.Dispose(); + } + + public Page GetPage(int number) + { + Page page = Pages.FirstOrDefault(p => p.Number == number); + if(page == null) + { + if(bookStore == null) + bookStore = new BookStore(); + page = bookStore.GetPage(number); + Pages.Add(page); + } + return page; + } +} diff --git a/Patterns/Proxy/Proxy.csproj b/Patterns/Proxy/Proxy.csproj new file mode 100644 index 0000000..fed8150 --- /dev/null +++ b/Patterns/Proxy/Proxy.csproj @@ -0,0 +1,14 @@ + + + + Exe + net6.0 + enable + enable + + + + + + + diff --git a/Patterns/Singleton/Program.cs b/Patterns/Singleton/Program.cs new file mode 100644 index 0000000..7bf5224 --- /dev/null +++ b/Patterns/Singleton/Program.cs @@ -0,0 +1,44 @@ +/* Одиночка + Гарантирует что класс имеет только + один экземпляр и представляет глобальную + точку доступа к нему + */ + +class Program +{ + static void Main() + { + #region Пример №1 - базовое + (new Thread(() => + { + Console.WriteLine(GameHistory.Instance.History[1]); + })).Start(); + Console.WriteLine(GameHistory.Instance.History[0]); + Console.ReadKey(); + #endregion + } +} + +class GameHistory +{ + private static object syncRoot = new(); + private static GameHistory _instance; + public static GameHistory Instance + { + get + { + lock(syncRoot) + { + if(_instance == null) + _instance = new GameHistory(); + } + return _instance; + } + } + public string[] History { get; set; } + private GameHistory() + { + History = new[] { "One History", + "Two History"}; + } +} \ No newline at end of file diff --git a/Patterns/Singleton/Singleton.csproj b/Patterns/Singleton/Singleton.csproj new file mode 100644 index 0000000..74abf5c --- /dev/null +++ b/Patterns/Singleton/Singleton.csproj @@ -0,0 +1,10 @@ + + + + Exe + net6.0 + enable + enable + + + diff --git a/Patterns/State/Program.cs b/Patterns/State/Program.cs new file mode 100644 index 0000000..28ae1b7 --- /dev/null +++ b/Patterns/State/Program.cs @@ -0,0 +1,76 @@ +/* Состояние + Позволяет объекту изменять + своё поведение в зависимости от + внутреннего состояния + */ +class Program +{ + static void Main() + { + #region Пример №1 - базовое + var contextA = new Context(new StateA()); + var contextB = new Context(new StateB()); + contextA.Request(); + contextB.Request(); + Console.ReadKey(); + #endregion + } +} + +/// +/// Абстракция состояния +/// +abstract class State +{ + public abstract void Handle(Context context); +} + +/// +/// Реализация состояния A +/// +class StateA : State +{ + public StateA() + { + Console.WriteLine("State-A Create..."); + } + + public override void Handle(Context context) + { + context.State = new StateB(); + } +} + +/// +/// Реализация состояния B +/// +class StateB : State +{ + public StateB() + { + Console.WriteLine("State-B Create..."); + } + + public override void Handle(Context context) + { + context.State = new StateA(); + } +} + +/// +/// Контекст со своим состоянием +/// +class Context +{ + public State State { get; set; } + + public Context(State state) + { + State = state; + } + + public void Request() + { + State.Handle(this); + } +} \ No newline at end of file diff --git a/Patterns/State/State.csproj b/Patterns/State/State.csproj new file mode 100644 index 0000000..74abf5c --- /dev/null +++ b/Patterns/State/State.csproj @@ -0,0 +1,10 @@ + + + + Exe + net6.0 + enable + enable + + + diff --git a/Patterns/Strategy/ILogReader.cs b/Patterns/Strategy/ILogReader.cs new file mode 100644 index 0000000..3818115 --- /dev/null +++ b/Patterns/Strategy/ILogReader.cs @@ -0,0 +1,6 @@ +namespace Strategy; + +internal interface ILogReader +{ + List Read(); +} diff --git a/Patterns/Strategy/LogEntry.cs b/Patterns/Strategy/LogEntry.cs new file mode 100644 index 0000000..2db0304 --- /dev/null +++ b/Patterns/Strategy/LogEntry.cs @@ -0,0 +1,15 @@ +namespace Strategy; + +public enum LogType +{ + Debug, + Warning, + Fatal +} + +public struct LogEntry +{ + public DateTime DateTime { get; set; } + public LogType LogType { get; set; } + public string Message { get; set; } +} diff --git a/Patterns/Strategy/LogFileReader.cs b/Patterns/Strategy/LogFileReader.cs new file mode 100644 index 0000000..649fcc3 --- /dev/null +++ b/Patterns/Strategy/LogFileReader.cs @@ -0,0 +1,17 @@ +namespace Strategy; + +public class LogFileReader : ILogReader +{ + public List Read() + { + return new List() + { + new LogEntry() + { + DateTime = DateTime.Now, + LogType = LogType.Debug, + Message = GetType().Name + } + }; + } +} \ No newline at end of file diff --git a/Patterns/Strategy/LogProcessor.cs b/Patterns/Strategy/LogProcessor.cs new file mode 100644 index 0000000..3f43f0e --- /dev/null +++ b/Patterns/Strategy/LogProcessor.cs @@ -0,0 +1,21 @@ +namespace Strategy; + +public class LogProcessor +{ + private readonly Func> _logimporter; + + public LogProcessor(Func> logImporter) + { + _logimporter = logImporter; + } + + public void ProcessLogs() + { + foreach (var logEntry in _logimporter.Invoke()) + { + Console.WriteLine(logEntry.DateTime); + Console.WriteLine(logEntry.LogType); + Console.WriteLine(logEntry.Message); + } + } +} \ No newline at end of file diff --git a/Patterns/Strategy/Program.cs b/Patterns/Strategy/Program.cs new file mode 100644 index 0000000..9488144 --- /dev/null +++ b/Patterns/Strategy/Program.cs @@ -0,0 +1,218 @@ +/* Стратегия + Определяет группу алгоритмов, + инкапсулирует их и делает взаимозаменяемыми. + Позволяет изменять алгоритм независимо от клиентов, + его использующих. + */ +/* + * На чем строилось: + * СЕРГЕЙ ТЕПЛЯКОВ - Паттерны проектирования на платформе .Net + * ШЕВЧУК, АХРИМЕНКО, КАСЬЯНОВ - Приемы объектно-ориентированного проектирования + * + * ПАТТЕРНЫ ПОВЕДЕНИЯ + * Паттерн №1: Стратегия + * + * - является более контекстно зависимой операцией + * + * Причины применения: + * 1.необходимость инкапсуляции поведения или алгоритма + * 2.необходимость замены поведения или алгоритма во время исполнения + * + * Другими словами, стратегия обеспечивает точку расширения системы + * в определенной плоскости: класс-контекст (LogProcessor) принимает экземпляр стратегии (LogFileReader) + * и не знает, какой вариант стратегии он собирается использовать. + * + * Особенность: + * Передача интерфейса ILogReader классу LogProcessor увеличивает гибкость, + * но в то же время повышает сложность. + * Теперь клиентам класса LogProcessor нужно решить, какую реализацию использовать, + * или переложить эту ответственность на вызывающий код. + */ + +/* + * ВМЕСТО + * классической стратегии на основе наследования + * можно использовать стратегию на основе делегатов + * + * ПРИМЕР: Стратегия сортировки + */ + +/* + * ВАЖНО: Гибкость не бывает бесплатной, поэтому выделять стратегии стоит тогда, + * когда действительно нужна замена поведения во время исполнения. + */ +using Strategy; + +class Program +{ + #region Пример №3 - Сomparer + public static void SortListId(List list) + { + list.Sort(new EmployeeByIdComparer()); //используем функтор + } + + public static void SortListName(List list) + { + list.Sort((x, y) => x.Name.CompareTo(y.Name)); //используем делегат + } + #endregion + + public static void Main(string[] args) + { + #region Пример №1 - базовое + var car = new Car(new PetrolMove()); + car.Move(); + car.Movable = new ElectronicMove(); + car.Move(); + Console.ReadKey(); + #endregion + #region Пример №2 - ILogReader + LogFileReader logFileReader = new LogFileReader(); + //создали делегат который принимает в себя метод, + //в результате выполнения которого возвращается List + Func> _import = () => logFileReader.Read(); + LogProcessor processor = new LogProcessor(_import); + processor.ProcessLogs(); + #endregion + #region Пример №3 - Сomparer + List employees = new List + { + 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(comparer); //конструктор принимает IComparable + //нет конструктора, принимающего делегат Comparison + //можно создать небольшой адаптерный фабричный класс + var comparer_factory = ComparerFactory.Create((x, y) => x.Id.CompareTo(y.Id)); + //он помещает сюда фабрику + var set_factory = new SortedSet(comparer_factory); + #endregion + } +} + +/// +/// Поведение движения +/// +interface IMovable +{ + void Move(); +} + +/// +/// Бензиновый двигатель +/// +class PetrolMove : IMovable +{ + public void Move() + { + Console.WriteLine("Движение на бензине"); + } +} + +/// +/// Электродвигатель +/// +class ElectronicMove : IMovable +{ + public void Move() + { + Console.WriteLine("Движение на электричестве"); + } +} + +/// +/// Автомобиль +/// +class Car +{ + /// + /// Cпособ передвижения автомобиля + /// + public IMovable Movable { private get; set; } + + public Car(IMovable movable) + { + Movable = movable; + } + + public void Move() + { + Movable.Move(); + } +} + + +class Employee +{ + public int Id { get; set; } + public string? Name { get; set; } + public override string ToString() + { + return string.Format($"ID={Id}, Name={Name}"); + } +} + +/// +/// Реализует интерфейс сортировки +/// Добавлет возможность сортировки по ID по возрастающей +/// +class EmployeeByIdComparer : IComparer +{ + int IComparer.Compare(Employee? x, Employee? y) + { + if (x is Employee xx && y is Employee yy) + return xx.Id.CompareTo(yy.Id); + else + return 0; + } +} + +/// +/// Фабричный шаблон для создания экземпляров IComparer +/// +class ComparerFactory +{ + public static IComparer Create(Comparison comparer) + { + return new DelegateComparer(comparer); + } + + private class DelegateComparer : IComparer + { + private readonly Comparison _comparer; + + public DelegateComparer(Comparison comparer) + { + _comparer = comparer; + } + + public int Compare(T? x, T? y) + { + if (x == null || y == null) + return 0; + return _comparer(x, y); + } + } +} \ No newline at end of file diff --git a/Patterns/Strategy/Strategy.csproj b/Patterns/Strategy/Strategy.csproj new file mode 100644 index 0000000..74abf5c --- /dev/null +++ b/Patterns/Strategy/Strategy.csproj @@ -0,0 +1,10 @@ + + + + Exe + net6.0 + enable + enable + + + diff --git a/Patterns/Strategy/WindowsEventLogReader.cs b/Patterns/Strategy/WindowsEventLogReader.cs new file mode 100644 index 0000000..1ebe975 --- /dev/null +++ b/Patterns/Strategy/WindowsEventLogReader.cs @@ -0,0 +1,17 @@ +namespace Strategy; + +public class WindowsEventLogReader : ILogReader +{ + public List Read() + { + return new List() + { + new LogEntry() + { + DateTime = DateTime.Now, + Message = GetType().Name, + LogType = LogType.Debug + } + }; + } +} diff --git a/Patterns/TemplateMethod/Program.cs b/Patterns/TemplateMethod/Program.cs new file mode 100644 index 0000000..d6dfb74 --- /dev/null +++ b/Patterns/TemplateMethod/Program.cs @@ -0,0 +1,115 @@ +/* Шаблонный метод + Определяет алгоритм, некоторые этапы которого + делегируются подклассам. Позволяет подклассам + переопределить эти этапы, не меняя структуру алгоритма. + */ +class Program +{ + public static void Main(string[] args) + { + #region Пример №1 - базовое + new School().Learn(); + new University().Learn(); + Console.ReadKey(); + #endregion + } +} + +/// +/// Представление образовательного процесса +/// +abstract class Education +{ + /// + /// Обучение + /// + public virtual void Learn() + { + Enter(); + Study(); + PassExams(); + GetDocument(); + } + + /// + /// Получение документа об окончании образования + /// + protected abstract void GetDocument(); + /// + /// Cдача экзаменов в учебном заведении + /// + protected abstract void PassExams(); + /// + /// Обучение в учебном заведении + /// + protected abstract void Study(); + /// + /// Поступление в учебное заведение + /// + protected abstract void Enter(); +} + +/// +/// Школа реализовывающее процесс образования со своими дополнениями +/// +class School : Education +{ + protected override void Enter() + { + Console.WriteLine("Поступил в школу"); + } + + protected override void GetDocument() + { + Console.WriteLine("Получил аттестат"); + } + + protected override void PassExams() + { + Console.WriteLine("Сдал ЕГЭ и ОГЭ"); + } + + public void ExtraExams() + { + Console.WriteLine("Ходил на олимпиады"); + } + + protected override void Study() + { + Console.WriteLine("Обучился 11 классов"); + } + + public override void Learn() + { + base.Learn(); + ExtraExams(); + } +} + +/// +/// Университет реализовывающий процесса образования +/// +class University : Education +{ + protected override void Enter() + { + Console.WriteLine("Поступил в университет"); + } + + protected override void GetDocument() + { + Console.WriteLine("Получил диплом"); + } + + protected override void PassExams() + { + Console.WriteLine("Сдал экзамены и зачёты"); + } + + protected override void Study() + { + Console.WriteLine("Ходил на пары"); + Console.WriteLine("Ходил на лекции"); + Console.WriteLine("Сдавал лабораторные работы"); + } +} \ No newline at end of file diff --git a/Patterns/TemplateMethod/TemplateMethod.csproj b/Patterns/TemplateMethod/TemplateMethod.csproj new file mode 100644 index 0000000..74abf5c --- /dev/null +++ b/Patterns/TemplateMethod/TemplateMethod.csproj @@ -0,0 +1,10 @@ + + + + Exe + net6.0 + enable + enable + + + diff --git a/Patterns/Visitor/Program.cs b/Patterns/Visitor/Program.cs new file mode 100644 index 0000000..322c1b2 --- /dev/null +++ b/Patterns/Visitor/Program.cs @@ -0,0 +1,138 @@ +/* Посетитель + Представляет собой операцию, которая + будет выполнена над объектами группы классов. + Даёт возможность определить новую операцию + без изменения кода классов, над которыми + эта операция производитcя. + */ +class Program +{ + public static void Main(string[] args) + { + #region Пример №1 - базовое + var bank = new Bank(); + bank.Add(new Person(Name: "Joshua", Number: 1997)); + bank.Add(new Company(Name: "Microsoft", Number: 1904)); + bank.Accept(new HtmlVisitor()); + bank.Accept(new XmlVisitor()); + Console.ReadKey(); + #endregion + } +} + +/// +/// Поведение посетителя +/// отделяет логику сериализации от классов в которых она применима +/// +interface IVisitor +{ + void VisitPersonAcc(Person person); + void VisitCompanyAcc(Company company); +} + +/// +/// Поведение аккаунта +/// +interface IAccaunt +{ + void Accept(IVisitor visitor); +} + +/// +/// Шаблон банка +/// +class Bank +{ + List Accaunts; + + public Bank() + { + Accaunts = new List(); + } + + /// + /// Добавить аккаунт + /// + /// аккаунт + public void Add(IAccaunt accaunt) + { + Accaunts.Add(accaunt); + } + + /// + /// Удаллить аккаунт + /// + /// аккаунт + public void Remove(IAccaunt accaunt) + { + Accaunts.Remove(accaunt); + } + + /// + /// Получить доступ к своему аккаунту + /// + /// пользователь + public void Accept(IVisitor visitor) + { + foreach (var accaunt in Accaunts) + accaunt.Accept(visitor); + } +} + +/// +/// Пользователь +/// +/// Имя +/// Номер +record Person(string Name, int Number) : IAccaunt +{ + public void Accept(IVisitor visitor) + { + visitor.VisitPersonAcc(this); + } +} + +/// +/// Компания +/// +/// Имя +/// Номер +record Company(string Name, int Number) : IAccaunt +{ + public void Accept(IVisitor visitor) + { + visitor.VisitCompanyAcc(this); + } +} + +/// +/// HTML сериализатор +/// +class HtmlVisitor : IVisitor +{ + public void VisitCompanyAcc(Company company) + { + Console.WriteLine($"[HTML] {company}"); + } + + public void VisitPersonAcc(Person person) + { + Console.WriteLine($"[HTML] {person}"); + } +} + +/// +/// XML сериализатор +/// +class XmlVisitor : IVisitor +{ + public void VisitCompanyAcc(Company company) + { + Console.WriteLine($"[XML] {company}"); + } + + public void VisitPersonAcc(Person person) + { + Console.WriteLine($"[XML] {person}"); + } +} \ No newline at end of file diff --git a/Patterns/Visitor/Visitor.csproj b/Patterns/Visitor/Visitor.csproj new file mode 100644 index 0000000..74abf5c --- /dev/null +++ b/Patterns/Visitor/Visitor.csproj @@ -0,0 +1,10 @@ + + + + Exe + net6.0 + enable + enable + + + diff --git a/README.md b/README.md new file mode 100644 index 0000000..67c65c6 --- /dev/null +++ b/README.md @@ -0,0 +1,156 @@ +

+ + +

+ Typing SVG +

+

+ Static Badge + +

+

+ +

+

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

+

+ +## Описание содержимого 💼 + +- ⌛ Определения: **class, abstract class, struct, interface, record** +- ⌛ Разбор: **принципы SOLID, наследование, типы Dictionary, Unit тестирование** +- ⌛ Бонус: **решение [LetCode](https://leetcode.com/) задач** +- 😈 Такие паттерны как: +> +

🌐 Behavioral - Поведенческие [11]🌐


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ПаттернКраткое определение
💢 ChainOfResponsibility - Цепочка обязанностей🔎 Избегает связывание отправителя запроса с его получателем, давая возможность обработать запрос более чем одному объекту.
💢 Command - Команда🔎 Инкапсулирует запрос в виде объекта позволяя передавать их клиентам в качестве параметров, ставить в очередь, логировать, а также поддерживать отмену операций.
💢 Interpreter - Интерпретатор🔎 Получая формальный язык, определяет представление его грамматики и интерпретатор, использующий это представление для обработки выражений языка.
💢 Iterator - Итератор🔎 Предоставляет способ последовательного доступа к множеству, независимо от его внутреннего устройства.
💢 Mediator - Посредник🔎 Определяет объект инкапсулирующий способ взаимодействия объектов. Обеспечивает слабую связь, избавляя их от необходимости ссылаться друг на друга и даёт возможность независимо изменять их взаимодействие.
💢 Memento - Хранитель🔎 Не нарушая инкапсуляцию, определяет и сохраняет внутреннее состояние объекта и позволяет позже восстановить объект в этом состоянии.
💢 Observer - Наблюдатель🔎 Определяет зависимость один ко многим между объектами так, что когда один меняет своё состояние, все зависимые объекты оповещаются и обновляются автоматически.
💢 State - Состояние🔎 Позволяет объекту изменять своё поведение в зависимости от внутреннего состояния.
💢 Strategy - Стратегия🔎 Определяет группу алгоритмов, инкапсулирует их и делает взаимозаменяемыми. Позволяет изменять алгоритм независимо от клиентов, его использующих.
💢 TemplateMethod - Шаблонный метод🔎 Определяет алгоритм, некоторые этапы которого делегируются подклассам. Позволяет подклассам переопределить эти этапы, не меняя структуру алгоритма.
💢 Visitor - Посетитель🔎 Представляет собой операцию, которая будет выполнена над объектами группы классов. Даёт возможность определить новую операцию без изменения кода классов, над которыми эта операция производитcя.
+
+

💡 Creational - Порождающие [6]💡


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ПаттернКраткое определение
💢 AbstractFactory - Абстрактная фабрика🔎 Предоставляет интерфейс для создания групп связанных или зависимых объектов, не указывая их конкретный класс.
💢 Builder - Строитель🔎 Разделяет создание сложного объекта и его инициализацию так, что одинаковый процесс построения может может создавать объекты с разным состоянием.
💢 FactoryMethod - Фабричный метод🔎 Определяет интерфейс для создания объекта, но позволяет подклассам решать, какой класс создавать. Позволяет делегировать создание класса объектам класса.
💢 FluentBuilder - Гибкий(плавный, текучий) строитель🔎 Позволяет упростить процесс создания сложных объектов с помощью методов-цепочек, которые наделяют объект каким-то определенным качеством.
💢 Prototype - Прототип🔎 Определяет несколько видов объектов, чтобы при создании использовать объект-прототип и создаёт новые объекты, копируя прототип (техника клонирования объектов).
💢 Singleton - Одиночка🔎 Гарантирует что класс имеет только один экземпляр и представляет глобальную точку доступа к нему.
+
+

🏩 Structural - Структурные [7]🏩


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ПаттернКраткое определение
💢 Adapter - Адаптер🔎 Конвенртирует интерфейс класса в другой интерфейс, ожидаемый клиентом. Позволяет классам с разными интерфейсами работать вместе.
💢 Bridge - Мост🔎 Разделяет абстракцию и реализацию так, чтобы они могли изменяться независимо друг от друга.
💢 Composite - Компоновщик🔎 Компонует объекты в древовидную структуру по принципу "часть-целое", представляя их в виде иерархии. Позволяет клиенту одинаково обращаться как к отдельному, так и к целому поддереву.
💢 Decorator - Декоратор🔎 Динамически предоставляет объекту дополнительные возможности. Представляет собой гибкую альтернативу наследованию для расширения функциональности.
💢 Facade - Фасад🔎 Предоставляет единый интерфейс к группе интерфейсов подсистемы. Определяет высокоуровневый интерфейс, делая систему проще для использования.
💢 Flyweight - Приспособленец🔎 Благодаря совместному использованию, поддерживает эффективную работу с большим количеством объектов. (для оптимизации работы с памятью)
💢 Proxy - Заместитель🔎 Предоставляет объект-заместитель другого объекта для контроля доступа к нему.
\ No newline at end of file