├── .editorconfig ├── .gitattributes ├── .github └── workflows │ └── dotnet.yml ├── .gitignore ├── BehaviorPattern ├── ChainOfResponsibilityPattern │ ├── ChainOfResponsibilityPattern.csproj │ ├── Manager.cs │ ├── Program.cs │ ├── Prototype.cs │ ├── README.md │ └── Request.cs ├── CommandPattern │ ├── Barbecuer.cs │ ├── CommandPattern.csproj │ ├── OrderCommand.cs │ ├── Program.cs │ ├── Prototype.cs │ ├── README.md │ └── Waiter.cs ├── InterpreterPattern │ ├── InterpreterPattern.csproj │ ├── MusicalExpression.cs │ ├── PlayContext.cs │ ├── Program.cs │ ├── Prototype.cs │ └── README.md ├── IteratorPattern │ ├── Aggregate.cs │ ├── Iterator.cs │ ├── Iterator.mdj │ ├── IteratorPattern.csproj │ ├── Program.cs │ └── README.md ├── MediatorPattern │ ├── Colleague.cs │ ├── Mediator.cs │ ├── MediatorPattern.csproj │ ├── Program.cs │ └── README.md ├── MementoPattern │ ├── GameRole.cs │ ├── MementoPattern.csproj │ ├── Program.cs │ ├── Prototype.cs │ ├── README.md │ ├── RoleStateCarertaker.cs │ └── RoleStateMemento.cs ├── ObserverPattern │ ├── Boss.cs │ ├── ISubject.cs │ ├── Observer.cs │ ├── ObserverPattern.csproj │ ├── Program.cs │ └── README.md ├── README.md ├── StatePattern │ ├── Program.cs │ ├── Prototype.cs │ ├── README.md │ ├── StatePattern.csproj │ ├── Work.cs │ └── WorkState.cs ├── StrategyPattern │ ├── AbstractCash.cs │ ├── CashContext.cs │ ├── Program.cs │ ├── Prototype.cs │ ├── README.md │ └── StrategyPattern.csproj ├── TemplateMethodPattern │ ├── Program.cs │ ├── Prototype.cs │ ├── README.md │ ├── TemplateMethodPattern.csproj │ └── TestPaper.cs └── VisitorPattern │ ├── Actions.cs │ ├── Person.cs │ ├── PersonStructure.cs │ ├── Program.cs │ ├── Prototype.cs │ ├── README.md │ └── VisitorPattern.csproj ├── CreatePattern ├── AbstractFactoryPattern │ ├── AbstractFactoryPattern.csproj │ ├── App.config │ ├── DataAccess.cs │ ├── DbFactory.cs │ ├── Department.cs │ ├── DepartmentRepo.cs │ ├── Program.cs │ ├── README.md │ ├── User.cs │ └── UserRepo.cs ├── BuilderPattern │ ├── Builder.cs │ ├── BuilderPattern.csproj │ ├── ConcreteBuilder1.cs │ ├── ConcreteBuilder2.cs │ ├── Director.cs │ ├── Product.cs │ ├── Program.cs │ └── README.md ├── FactoryMethodPattern │ ├── FactoryMethodPattern.csproj │ ├── Leifeng.cs │ ├── LeifengFactory.cs │ ├── Program.cs │ ├── README.md │ ├── Undergradute.cs │ └── Volunteer.cs ├── PrototypePattern │ ├── ComplexResume.cs │ ├── Program.cs │ ├── Prototype.cs │ ├── PrototypePattern.csproj │ ├── README.md │ └── SimpleResume.cs ├── README.md ├── SimpleFactoryPattern │ ├── Operation.cs │ ├── OperationFactory.cs │ ├── Program.cs │ ├── README.md │ └── SimpleFactoryPattern.csproj └── SingletonPattern │ ├── Program.cs │ ├── README.md │ ├── Singleton.cs │ ├── Singleton1.cs │ ├── Singleton2.cs │ ├── Singleton3.cs │ └── SingletonPattern.csproj ├── DesignPatterns.sln ├── Directory.Build.props ├── Directory.Build.targets ├── LICENSE ├── Principles.md ├── README.md ├── StructurePattern ├── AdapterPattern │ ├── AdapterPattern.csproj │ ├── Player.cs │ ├── Program.cs │ ├── Prototype.cs │ └── README.md ├── BridgePattern │ ├── BridgePattern.csproj │ ├── HandsetBrand.cs │ ├── HandsetSoft.cs │ ├── Program.cs │ ├── Prototype.cs │ └── README.md ├── CompositePattern │ ├── Company.cs │ ├── CompositePattern.csproj │ ├── Program.cs │ ├── Prototype.cs │ └── README.md ├── DecoratorPattern │ ├── DecoratorPattern.csproj │ ├── Finery.cs │ ├── Program.cs │ ├── Prototype.cs │ └── README.md ├── FacadePattern │ ├── FacadePattern.csproj │ ├── Program.cs │ ├── Prototype.cs │ └── README.md ├── FlyweightPattern │ ├── FlyweightPattern.csproj │ ├── Program.cs │ ├── Prototype.cs │ └── README.md ├── ProxyPattern │ ├── Program.cs │ ├── Prototype.cs │ ├── ProxyPattern.csproj │ └── README.md └── README.md ├── azure-pipelines.yml └── 大话设计模式.pdf /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome:http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Don't use tabs for indentation. 7 | [*] 8 | indent_style = space 9 | # (Please don't specify an indent_size here; that has too many unintended consequences.) 10 | 11 | # Code files 12 | [*.{cs,csx,vb,vbx}] 13 | indent_size = 4 14 | insert_final_newline = true 15 | charset = utf-8-bom 16 | 17 | # Xml project files 18 | [*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}] 19 | indent_size = 2 20 | 21 | # Xml config files 22 | [*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}] 23 | indent_size = 2 24 | 25 | # JSON files 26 | [*.json] 27 | indent_size = 2 28 | 29 | # Dotnet code style settings: 30 | [*.{cs,vb}] 31 | # namespace style 32 | csharp_style_namespace_declarations=file_scoped:suggestion 33 | 34 | # Sort using and Import directives with System.* appearing first 35 | dotnet_sort_system_directives_first = false 36 | 37 | # Avoid "this." and "Me." if not necessary 38 | dotnet_style_qualification_for_field = false:suggestion 39 | dotnet_style_qualification_for_property = false:suggestion 40 | dotnet_style_qualification_for_method = false:suggestion 41 | dotnet_style_qualification_for_event = false:suggestion 42 | 43 | # Use language keywords instead of framework type names for type references 44 | dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion 45 | dotnet_style_predefined_type_for_member_access = true:suggestion 46 | 47 | # Suggest more modern language features when available 48 | dotnet_style_object_initializer = true:suggestion 49 | dotnet_style_collection_initializer = true:suggestion 50 | dotnet_style_coalesce_expression = true:suggestion 51 | dotnet_style_null_propagation = true:suggestion 52 | dotnet_style_explicit_tuple_names = true:suggestion 53 | 54 | # CSharp code style settings: 55 | [*.cs] 56 | # Prefer "var" everywhere 57 | csharp_style_var_for_built_in_types = true:suggestion 58 | csharp_style_var_when_type_is_apparent = true:suggestion 59 | csharp_style_var_elsewhere = true:suggestion 60 | 61 | # Prefer method-like constructs to have a block body 62 | csharp_style_expression_bodied_methods = false:none 63 | csharp_style_expression_bodied_constructors = false:none 64 | csharp_style_expression_bodied_operators = false:none 65 | 66 | # Prefer property-like constructs to have an expression-body 67 | csharp_style_expression_bodied_properties = true:none 68 | csharp_style_expression_bodied_indexers = true:none 69 | csharp_style_expression_bodied_accessors = true:none 70 | 71 | # Suggest more modern language features when available 72 | csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion 73 | csharp_style_pattern_matching_over_as_with_null_check = true:suggestion 74 | csharp_style_inlined_variable_declaration = true:suggestion 75 | csharp_style_throw_expression = true:suggestion 76 | csharp_style_conditional_delegate_call = true:suggestion 77 | 78 | # Newline settings 79 | csharp_new_line_before_open_brace = all 80 | csharp_new_line_before_else = true 81 | csharp_new_line_before_catch = true 82 | csharp_new_line_before_finally = true 83 | csharp_new_line_before_members_in_object_initializers = true 84 | csharp_new_line_before_members_in_anonymous_types = true -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.github/workflows/dotnet.yml: -------------------------------------------------------------------------------- 1 | name: dotnet 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | windows-build: 11 | runs-on: windows-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | - name: Setup .NET SDK 15 | uses: actions/setup-dotnet@v3 16 | with: 17 | dotnet-version: | 18 | 8.x 19 | - name: dotnet info 20 | run: dotnet --info 21 | - name: build 22 | run: dotnet build -c Release 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # Cutom files 7 | localBuild/ 8 | 9 | # User-specific files 10 | *.suo 11 | *.user 12 | *.userosscache 13 | *.sln.docstates 14 | 15 | # User-specific files (MonoDevelop/Xamarin Studio) 16 | *.userprefs 17 | 18 | # Build results 19 | [Dd]ebug/ 20 | [Dd]ebugPublic/ 21 | [Rr]elease/ 22 | [Rr]eleases/ 23 | x64/ 24 | x86/ 25 | bld/ 26 | [Bb]in/ 27 | [Oo]bj/ 28 | [Ll]og/ 29 | 30 | # Visual Studio 2015 cache/options directory 31 | .vs/ 32 | # Uncomment if you have tasks that create the project's static files in wwwroot 33 | #wwwroot/ 34 | 35 | # MSTest test Results 36 | [Tt]est[Rr]esult*/ 37 | [Bb]uild[Ll]og.* 38 | 39 | # NUNIT 40 | *.VisualState.xml 41 | TestResult.xml 42 | 43 | # Build Results of an ATL Project 44 | [Dd]ebugPS/ 45 | [Rr]eleasePS/ 46 | dlldata.c 47 | 48 | # .NET Core 49 | project.lock.json 50 | project.fragment.lock.json 51 | artifacts/ 52 | **/Properties/launchSettings.json 53 | 54 | *_i.c 55 | *_p.c 56 | *_i.h 57 | *.ilk 58 | *.meta 59 | *.obj 60 | *.pch 61 | *.pdb 62 | *.pgc 63 | *.pgd 64 | *.rsp 65 | *.sbr 66 | *.tlb 67 | *.tli 68 | *.tlh 69 | *.tmp 70 | *.tmp_proj 71 | *.log 72 | *.vspscc 73 | *.vssscc 74 | .builds 75 | *.pidb 76 | *.svclog 77 | *.scc 78 | 79 | # Chutzpah Test files 80 | _Chutzpah* 81 | 82 | # Visual C++ cache files 83 | ipch/ 84 | *.aps 85 | *.ncb 86 | *.opendb 87 | *.opensdf 88 | *.sdf 89 | *.cachefile 90 | *.VC.db 91 | *.VC.VC.opendb 92 | 93 | # Visual Studio profiler 94 | *.psess 95 | *.vsp 96 | *.vspx 97 | *.sap 98 | 99 | # TFS 2012 Local Workspace 100 | $tf/ 101 | 102 | # Guidance Automation Toolkit 103 | *.gpState 104 | 105 | # ReSharper is a .NET coding add-in 106 | _ReSharper*/ 107 | *.[Rr]e[Ss]harper 108 | *.DotSettings.user 109 | 110 | # JustCode is a .NET coding add-in 111 | .JustCode 112 | 113 | # TeamCity is a build add-in 114 | _TeamCity* 115 | 116 | # DotCover is a Code Coverage Tool 117 | *.dotCover 118 | 119 | # Visual Studio code coverage results 120 | *.coverage 121 | *.coveragexml 122 | 123 | # NCrunch 124 | _NCrunch_* 125 | .*crunch*.local.xml 126 | nCrunchTemp_* 127 | 128 | # MightyMoose 129 | *.mm.* 130 | AutoTest.Net/ 131 | 132 | # Web workbench (sass) 133 | .sass-cache/ 134 | 135 | # Installshield output folder 136 | [Ee]xpress/ 137 | 138 | # DocProject is a documentation generator add-in 139 | DocProject/buildhelp/ 140 | DocProject/Help/*.HxT 141 | DocProject/Help/*.HxC 142 | DocProject/Help/*.hhc 143 | DocProject/Help/*.hhk 144 | DocProject/Help/*.hhp 145 | DocProject/Help/Html2 146 | DocProject/Help/html 147 | 148 | # Click-Once directory 149 | publish/ 150 | 151 | # Publish Web Output 152 | *.[Pp]ublish.xml 153 | *.azurePubxml 154 | # TODO: Comment the next line if you want to checkin your web deploy settings 155 | # but database connection strings (with potential passwords) will be unencrypted 156 | *.pubxml 157 | *.publishproj 158 | 159 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 160 | # checkin your Azure Web App publish settings, but sensitive information contained 161 | # in these scripts will be unencrypted 162 | PublishScripts/ 163 | 164 | # NuGet Packages 165 | *.nupkg 166 | # The packages folder can be ignored because of Package Restore 167 | **/packages/* 168 | # except build/, which is used as an MSBuild target. 169 | !**/packages/build/ 170 | # Uncomment if necessary however generally it will be regenerated when needed 171 | #!**/packages/repositories.config 172 | # NuGet v3's project.json files produces more ignorable files 173 | *.nuget.props 174 | *.nuget.targets 175 | 176 | # Microsoft Azure Build Output 177 | csx/ 178 | *.build.csdef 179 | 180 | # Microsoft Azure Emulator 181 | ecf/ 182 | rcf/ 183 | 184 | # Windows Store app package directories and files 185 | AppPackages/ 186 | BundleArtifacts/ 187 | Package.StoreAssociation.xml 188 | _pkginfo.txt 189 | 190 | # Visual Studio cache files 191 | # files ending in .cache can be ignored 192 | *.[Cc]ache 193 | # but keep track of directories ending in .cache 194 | !*.[Cc]ache/ 195 | 196 | # Others 197 | ClientBin/ 198 | ~$* 199 | *~ 200 | *.dbmdl 201 | *.dbproj.schemaview 202 | *.jfm 203 | *.pfx 204 | *.publishsettings 205 | orleans.codegen.cs 206 | 207 | # Since there are multiple workflows, uncomment next line to ignore bower_components 208 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 209 | #bower_components/ 210 | 211 | # RIA/Silverlight projects 212 | Generated_Code/ 213 | 214 | # Backup & report files from converting an old project file 215 | # to a newer Visual Studio version. Backup files are not needed, 216 | # because we have git ;-) 217 | _UpgradeReport_Files/ 218 | Backup*/ 219 | UpgradeLog*.XML 220 | UpgradeLog*.htm 221 | 222 | # SQL Server files 223 | *.mdf 224 | *.ldf 225 | *.ndf 226 | 227 | # Business Intelligence projects 228 | *.rdl.data 229 | *.bim.layout 230 | *.bim_*.settings 231 | 232 | # Microsoft Fakes 233 | FakesAssemblies/ 234 | 235 | # GhostDoc plugin setting file 236 | *.GhostDoc.xml 237 | 238 | # Node.js Tools for Visual Studio 239 | .ntvs_analysis.dat 240 | node_modules/ 241 | 242 | # Typescript v1 declaration files 243 | typings/ 244 | 245 | # Visual Studio 6 build log 246 | *.plg 247 | 248 | # Visual Studio 6 workspace options file 249 | *.opt 250 | 251 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 252 | *.vbw 253 | 254 | # Visual Studio LightSwitch build output 255 | **/*.HTMLClient/GeneratedArtifacts 256 | **/*.DesktopClient/GeneratedArtifacts 257 | **/*.DesktopClient/ModelManifest.xml 258 | **/*.Server/GeneratedArtifacts 259 | **/*.Server/ModelManifest.xml 260 | _Pvt_Extensions 261 | 262 | # Paket dependency manager 263 | .paket/paket.exe 264 | paket-files/ 265 | 266 | # FAKE - F# Make 267 | .fake/ 268 | 269 | # JetBrains Rider 270 | .idea/ 271 | *.sln.iml 272 | 273 | # CodeRush 274 | .cr/ 275 | 276 | # Python Tools for Visual Studio (PTVS) 277 | __pycache__/ 278 | *.pyc 279 | 280 | # Cake - Uncomment if you are using it 281 | # tools/** 282 | # !tools/packages.config 283 | 284 | # Telerik's JustMock configuration file 285 | *.jmconfig 286 | 287 | # BizTalk build output 288 | *.btp.cs 289 | *.btm.cs 290 | *.odx.cs 291 | *.xsd.cs 292 | -------------------------------------------------------------------------------- /BehaviorPattern/ChainOfResponsibilityPattern/ChainOfResponsibilityPattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /BehaviorPattern/ChainOfResponsibilityPattern/Manager.cs: -------------------------------------------------------------------------------- 1 | namespace ChainOfResponsibilityPattern; 2 | 3 | internal abstract class Manager 4 | { 5 | protected readonly string ManagerName; 6 | protected Manager Superior; 7 | 8 | protected Manager(string managerName) => ManagerName = managerName; 9 | 10 | public void SetSuperior(Manager superior) 11 | { 12 | Superior = superior; 13 | } 14 | 15 | public abstract void RequestApplications(Request request); 16 | } 17 | 18 | internal class CommonManager : Manager 19 | { 20 | public CommonManager(string managerName) : base(managerName) 21 | { 22 | } 23 | 24 | public override void RequestApplications(Request request) 25 | { 26 | if (request.RequestType == "请假" && request.RequestNum <= 2) 27 | { 28 | Console.WriteLine($"{ManagerName}: {request.RequestContent} {request.RequestNum}天被批准"); 29 | } 30 | else 31 | { 32 | Superior?.RequestApplications(request); 33 | } 34 | } 35 | } 36 | 37 | internal class Majordomo : Manager 38 | { 39 | public Majordomo(string managerName) : base(managerName) 40 | { 41 | } 42 | 43 | public override void RequestApplications(Request request) 44 | { 45 | if (request.RequestType == "请假" && request.RequestNum <= 5) 46 | { 47 | Console.WriteLine($"{ManagerName}: {request.RequestContent} {request.RequestNum}天被批准"); 48 | } 49 | else 50 | { 51 | Superior?.RequestApplications(request); 52 | } 53 | } 54 | } 55 | 56 | internal class GeneralManager : Manager 57 | { 58 | public GeneralManager(string managerName) : base(managerName) 59 | { 60 | } 61 | 62 | public override void RequestApplications(Request request) 63 | { 64 | if (request.RequestType == "请假") 65 | { 66 | Console.WriteLine($"{ManagerName}: {request.RequestContent} {request.RequestNum}天被批准"); 67 | return; 68 | } 69 | if (request.RequestType == "加薪" && request.RequestNum <= 500) 70 | { 71 | Console.WriteLine($"{ManagerName}: {request.RequestContent} 数量{request.RequestNum}被批准"); 72 | return; 73 | } 74 | if (request.RequestType == "加薪" && request.RequestNum > 500) 75 | { 76 | Console.WriteLine($"{ManagerName}: {request.RequestContent} {request.RequestNum},再说吧"); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /BehaviorPattern/ChainOfResponsibilityPattern/Program.cs: -------------------------------------------------------------------------------- 1 | #region Prototype 2 | 3 | Handler h1 = new ConcreteHandler1(); 4 | Handler h2 = new ConcreteHandler2(); 5 | Handler h3 = new ConcreteHandler3(); 6 | Handler h4 = new ConcreteHandler4(); 7 | 8 | h1.SetSuccessor(h2); 9 | h2.SetSuccessor(h3); 10 | h3.SetSuccessor(h4); 11 | 12 | var random = new Random(); 13 | for (var i = 0; i < 10; i++) 14 | { 15 | h1.HandleRequest(random.Next(40)); 16 | } 17 | 18 | #endregion Prototype 19 | 20 | var manager = new CommonManager("金利"); 21 | var manager1 = new Majordomo("宗剑"); 22 | var manager2 = new GeneralManager("钟精励"); 23 | 24 | manager1.SetSuperior(manager2); 25 | manager.SetSuperior(manager1); 26 | 27 | var request = new Request() 28 | { 29 | RequestNum = 1, 30 | RequestType = "请假", 31 | RequestContent = "小菜请假" 32 | }; 33 | 34 | manager.RequestApplications(request); 35 | 36 | var request1 = new Request() 37 | { 38 | RequestNum = 4, 39 | RequestType = "请假", 40 | RequestContent = "小菜请假" 41 | }; 42 | 43 | manager.RequestApplications(request1); 44 | 45 | var request2 = new Request() 46 | { 47 | RequestNum = 500, 48 | RequestType = "加薪", 49 | RequestContent = "小菜请求加薪" 50 | }; 51 | 52 | manager.RequestApplications(request2); 53 | 54 | var request3 = new Request() 55 | { 56 | RequestNum = 1000, 57 | RequestType = "加薪", 58 | RequestContent = "小菜请求加薪" 59 | }; 60 | 61 | manager.RequestApplications(request3); 62 | 63 | Console.ReadLine(); 64 | -------------------------------------------------------------------------------- /BehaviorPattern/ChainOfResponsibilityPattern/Prototype.cs: -------------------------------------------------------------------------------- 1 | namespace ChainOfResponsibilityPattern; 2 | 3 | internal abstract class Handler 4 | { 5 | protected Handler Successor; 6 | 7 | public void SetSuccessor(Handler successor) 8 | { 9 | Successor = successor; 10 | } 11 | 12 | public abstract void HandleRequest(int request); 13 | } 14 | 15 | internal class ConcreteHandler1 : Handler 16 | { 17 | public override void HandleRequest(int request) 18 | { 19 | if (request >= 0 && request < 10) 20 | { 21 | Console.WriteLine($"{GetType().Name} 处理请求{request}"); 22 | } 23 | else 24 | { 25 | Successor?.HandleRequest(request); 26 | } 27 | } 28 | } 29 | 30 | internal class ConcreteHandler2 : Handler 31 | { 32 | public override void HandleRequest(int request) 33 | { 34 | if (request >= 10 && request < 20) 35 | { 36 | Console.WriteLine($"{GetType().Name} 处理请求{request}"); 37 | } 38 | else 39 | { 40 | Successor?.HandleRequest(request); 41 | } 42 | } 43 | } 44 | 45 | internal class ConcreteHandler3 : Handler 46 | { 47 | public override void HandleRequest(int request) 48 | { 49 | if (request >= 20 && request < 30) 50 | { 51 | Console.WriteLine($"{GetType().Name} 处理请求{request}"); 52 | } 53 | else 54 | { 55 | Successor?.HandleRequest(request); 56 | } 57 | } 58 | } 59 | 60 | internal class ConcreteHandler4 : Handler 61 | { 62 | public override void HandleRequest(int request) 63 | { 64 | Console.WriteLine($"{GetType().Name} 处理请求{request}"); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /BehaviorPattern/ChainOfResponsibilityPattern/README.md: -------------------------------------------------------------------------------- 1 | # 职责链(责任链)模式 Chain of Responsibility 2 | 3 | ## Intro 4 | 5 | 职责链(责任链)模式,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。 6 | 发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。 7 | 8 | ## Sample 9 | 10 | ``` csharp 11 | public class Request 12 | { 13 | public string RequestContent { get; set; } 14 | 15 | public int RequestNum { get; set; } 16 | } 17 | 18 | public abstract class Manager 19 | { 20 | protected readonly string ManagerName; 21 | protected Manager Superior; 22 | 23 | protected Manager(string managerName) => ManagerName = managerName; 24 | 25 | public void SetSuperior(Manager superior) 26 | { 27 | Superior = superior; 28 | } 29 | 30 | public abstract void RequestApplications(Request request); 31 | } 32 | 33 | public class CommonManager : Manager 34 | { 35 | public CommonManager(string managerName) : base(managerName) 36 | { 37 | } 38 | 39 | public override void RequestApplications(Request request) 40 | { 41 | if (request.RequestNum <= 2) 42 | { 43 | Console.WriteLine($"{ManagerName}: {request.RequestContent} {request.RequestNum}天被批准"); 44 | } 45 | else 46 | { 47 | Superior?.RequestApplications(request); 48 | } 49 | } 50 | } 51 | 52 | public class Majordomo : Manager 53 | { 54 | public Majordomo(string managerName) : base(managerName) 55 | { 56 | } 57 | 58 | public override void RequestApplications(Request request) 59 | { 60 | if (request.RequestNum <= 5) 61 | { 62 | Console.WriteLine($"{ManagerName}: {request.RequestContent} {request.RequestNum}天被批准"); 63 | } 64 | else 65 | { 66 | Superior?.RequestApplications(request); 67 | } 68 | } 69 | } 70 | 71 | public class GeneralManager : Manager 72 | { 73 | public GeneralManager(string managerName) : base(managerName) 74 | { 75 | } 76 | 77 | public override void RequestApplications(Request request) 78 | { 79 | if (request.RequestNum <= 10) 80 | { 81 | Console.WriteLine($"{ManagerName}: {request.RequestContent} {request.RequestNum}天被批准"); 82 | } 83 | else 84 | { 85 | Console.WriteLine($"{ManagerName}: {request.RequestContent} {request.RequestNum}天不被批准"); 86 | } 87 | } 88 | } 89 | 90 | 91 | var manager = new CommonManager("金利"); 92 | var manager1 = new Majordomo("宗剑"); 93 | var manager2 = new GeneralManager("钟精励"); 94 | 95 | manager1.SetSuperior(manager2); 96 | manager.SetSuperior(manager1); 97 | 98 | var request = new Request() 99 | { 100 | RequestNum = 4, 101 | RequestContent = "小菜请假" 102 | }; 103 | 104 | manager.RequestApplications(request); 105 | ``` 106 | 107 | ## AndMore 108 | 109 | asp.net core 中请求管道中间件的设计就是这种模式的变形,可以很灵活的处理请求 110 | 111 | 我封装了一个 `PipelineBuilder` () 用来轻松的构建中间件模式的代码,来看下面的示例: 112 | 113 | ``` csharp 114 | private class RequestContext 115 | { 116 | public string RequesterName { get; set; } 117 | 118 | public int Hour { get; set; } 119 | } 120 | 121 | public static void Test() 122 | { 123 | var requestContext = new RequestContext() 124 | { 125 | RequesterName = "Kangkang", 126 | Hour = 12, 127 | }; 128 | 129 | var builder = PipelineBuilder.Create(context => 130 | { 131 | Console.WriteLine($"{context.RequesterName} {context.Hour}h apply failed"); 132 | }) 133 | .Use((context, next) => 134 | { 135 | if (context.Hour <= 2) 136 | { 137 | Console.WriteLine("pass 1"); 138 | } 139 | else 140 | { 141 | next(); 142 | } 143 | }) 144 | .Use((context, next) => 145 | { 146 | if (context.Hour <= 4) 147 | { 148 | Console.WriteLine("pass 2"); 149 | } 150 | else 151 | { 152 | next(); 153 | } 154 | }) 155 | .Use((context, next) => 156 | { 157 | if (context.Hour <= 6) 158 | { 159 | Console.WriteLine("pass 3"); 160 | } 161 | else 162 | { 163 | next(); 164 | } 165 | }) 166 | ; 167 | var requestPipeline = builder.Build(); 168 | foreach (var i in Enumerable.Range(1, 8)) 169 | { 170 | Console.WriteLine(); 171 | Console.WriteLine($"--------- h:{i} apply Pipeline------------------"); 172 | requestContext.Hour = i; 173 | requestPipeline.Invoke(requestContext); 174 | Console.WriteLine("----------------------------"); 175 | Console.WriteLine(); 176 | } 177 | } 178 | ``` 179 | 180 | ## More 181 | 182 | 更多设计模式及示例代码 [传送门](https://github.com/WeihanLi/DesignPatterns) 183 | -------------------------------------------------------------------------------- /BehaviorPattern/ChainOfResponsibilityPattern/Request.cs: -------------------------------------------------------------------------------- 1 | namespace ChainOfResponsibilityPattern; 2 | 3 | internal class Request 4 | { 5 | public string RequestType { get; set; } 6 | 7 | public string RequestContent { get; set; } 8 | 9 | public int RequestNum { get; set; } 10 | } 11 | -------------------------------------------------------------------------------- /BehaviorPattern/CommandPattern/Barbecuer.cs: -------------------------------------------------------------------------------- 1 | namespace CommandPattern; 2 | 3 | public class Barbecuer 4 | { 5 | public void BakeMutton() 6 | { 7 | Console.WriteLine("烤羊肉串"); 8 | } 9 | 10 | public void BakeChickenWing() 11 | { 12 | Console.WriteLine("烤鸡翅"); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /BehaviorPattern/CommandPattern/CommandPattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /BehaviorPattern/CommandPattern/OrderCommand.cs: -------------------------------------------------------------------------------- 1 | namespace CommandPattern; 2 | 3 | public abstract class OrderCommand 4 | { 5 | protected Barbecuer Receiver; 6 | 7 | protected OrderCommand(Barbecuer receiver) => Receiver = receiver ?? throw new ArgumentNullException(nameof(receiver)); 8 | 9 | public abstract void ExecuteCommand(); 10 | } 11 | 12 | internal class BakeMuttonCommand : OrderCommand 13 | { 14 | public BakeMuttonCommand(Barbecuer receiver) : base(receiver) 15 | { 16 | } 17 | 18 | public override void ExecuteCommand() 19 | { 20 | Receiver.BakeMutton(); 21 | } 22 | 23 | public override string ToString() => nameof(BakeMuttonCommand); 24 | } 25 | 26 | internal class BakeChickenWingCommand : OrderCommand 27 | { 28 | public BakeChickenWingCommand(Barbecuer receiver) : base(receiver) 29 | { 30 | } 31 | 32 | public override void ExecuteCommand() 33 | { 34 | Receiver.BakeChickenWing(); 35 | } 36 | 37 | public override string ToString() => nameof(BakeChickenWingCommand); 38 | } 39 | -------------------------------------------------------------------------------- /BehaviorPattern/CommandPattern/Program.cs: -------------------------------------------------------------------------------- 1 | #region Prototype 2 | 3 | var receiver = new Receiver(); 4 | var command = new ConcreteCommand(receiver); 5 | var invoker = new Invoker(); 6 | invoker.SetCommand(command); 7 | invoker.ExecuteCommand(); 8 | 9 | #endregion Prototype 10 | 11 | var barbecuer = new Barbecuer(); 12 | var waiter = new Waiter(); 13 | 14 | waiter.SetOrder(new BakeChickenWingCommand(barbecuer)); 15 | waiter.SetOrder(new BakeMuttonCommand(barbecuer)); 16 | waiter.SetOrder(new BakeMuttonCommand(barbecuer)); 17 | 18 | var willCancelOrder = new BakeMuttonCommand(barbecuer); 19 | waiter.SetOrder(willCancelOrder); 20 | waiter.CancelOrder(willCancelOrder); 21 | 22 | waiter.Notify(); 23 | 24 | Console.ReadLine(); 25 | -------------------------------------------------------------------------------- /BehaviorPattern/CommandPattern/Prototype.cs: -------------------------------------------------------------------------------- 1 | namespace CommandPattern; 2 | 3 | internal class Receiver 4 | { 5 | public void Action() 6 | { 7 | Console.WriteLine("Action in receiver"); 8 | } 9 | } 10 | 11 | internal abstract class Command 12 | { 13 | protected readonly Receiver Receiver; 14 | 15 | protected Command(Receiver receiver) => 16 | Receiver = receiver ?? throw new ArgumentNullException(nameof(receiver)); 17 | 18 | public abstract void Execute(); 19 | } 20 | 21 | internal class ConcreteCommand : Command 22 | { 23 | public ConcreteCommand(Receiver receiver) : base(receiver) 24 | { 25 | } 26 | 27 | public override void Execute() 28 | { 29 | Receiver.Action(); 30 | } 31 | } 32 | 33 | internal class Invoker 34 | { 35 | private Command _command; 36 | 37 | public void SetCommand(Command command) 38 | { 39 | _command = command; 40 | } 41 | 42 | public void ExecuteCommand() 43 | { 44 | _command.Execute(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /BehaviorPattern/CommandPattern/README.md: -------------------------------------------------------------------------------- 1 | # 命令模式 Command 2 | 3 | ## Intro 4 | 5 | 命令模式,将一个请求封装为一个对象,从而使得可以用不同的请求进行参数化,对请求排队或者记录请求日志以及支持可撤销的操作。 6 | 7 | 命令模式是对命令进行封装,由调用者发起命令请求,接收者执行请求。 8 | 9 | 当我们调用时,执行的时序首先是调用者类,然后是命令类,最后是接收者类。 10 | 也就是说一条命令的执行被分成了三步,它的耦合度要比把所有的操作都封装到一个类中要低的多, 11 | 而这也正是命令模式的精髓所在:把命令的调用者与执行者分开,使双方不必关心对方是如何操作的。 12 | 13 | 基本结构: 14 | 15 | - Command:命令的抽象,类中对需要执行的命令进行声明,一般来说要对外暴露一个 Execute 方法用来执行命令 16 | - ConcreteCommand:Command 的实现类 17 | - Invoker:调用者,负责调用命令 18 | - Receiver:接收者,负责接收命令并且执行命令 19 | 20 | ## Sample 21 | 22 | ``` csharp 23 | public class Receiver 24 | { 25 | public void Action() 26 | { 27 | Console.WriteLine("Action in receiver"); 28 | } 29 | } 30 | 31 | public abstract class Command 32 | { 33 | protected readonly Receiver Receiver; 34 | 35 | protected Command(Receiver receiver) => 36 | Receiver = receiver ?? throw new ArgumentNullException(nameof(receiver)); 37 | 38 | public abstract void Execute(); 39 | } 40 | public class ConcreteCommand : Command 41 | { 42 | public ConcreteCommand(Receiver receiver) : base(receiver) 43 | { 44 | } 45 | 46 | public override void Execute() 47 | { 48 | Receiver.Action(); 49 | } 50 | } 51 | 52 | public class Invoker 53 | { 54 | private Command _command; 55 | 56 | public void SetCommand(Command command) 57 | { 58 | _command = command; 59 | } 60 | 61 | public void ExecuteCommand() 62 | { 63 | _command.Execute(); 64 | } 65 | } 66 | 67 | 68 | var receiver = new Receiver(); 69 | var command = new ConcreteCommand(receiver); 70 | var invoker = new Invoker(); 71 | invoker.SetCommand(command); 72 | invoker.ExecuteCommand(); 73 | 74 | // another sample 75 | var barbecuer = new Barbecuer(); 76 | var waiter = new Waiter(); 77 | 78 | waiter.SetOrder(new BakeChickenWingCommand(barbecuer)); 79 | waiter.SetOrder(new BakeMuttonCommand(barbecuer)); 80 | waiter.SetOrder(new BakeMuttonCommand(barbecuer)); 81 | 82 | var willCancelOrder = new BakeMuttonCommand(barbecuer); 83 | waiter.SetOrder(willCancelOrder); 84 | waiter.CancelOrder(willCancelOrder); 85 | 86 | waiter.Notify(); 87 | ``` 88 | 89 | ## More 90 | 91 | 更多设计模式及示例代码 [传送门](https://github.com/WeihanLi/DesignPatterns) 92 | -------------------------------------------------------------------------------- /BehaviorPattern/CommandPattern/Waiter.cs: -------------------------------------------------------------------------------- 1 | namespace CommandPattern; 2 | 3 | public class Waiter 4 | { 5 | private readonly ICollection _orders = new List(); 6 | 7 | public void SetOrder(OrderCommand order) 8 | { 9 | if (order.ToString() == "BakeChickenWingCommand") 10 | { 11 | Console.WriteLine("鸡翅没有了,换点别的吧"); 12 | } 13 | else 14 | { 15 | Console.WriteLine($"{order} 下单成功"); 16 | _orders.Add(order); 17 | } 18 | } 19 | 20 | public void CancelOrder(OrderCommand order) 21 | { 22 | _orders.Remove(order); 23 | Console.WriteLine($"取消订单:{order},取消时间:{DateTime.Now:yyyy-MM-dd HH:mm:ss}"); 24 | } 25 | 26 | public void Notify() 27 | { 28 | foreach (var order in _orders) 29 | { 30 | order.ExecuteCommand(); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /BehaviorPattern/InterpreterPattern/InterpreterPattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /BehaviorPattern/InterpreterPattern/MusicalExpression.cs: -------------------------------------------------------------------------------- 1 | namespace InterpreterPattern; 2 | 3 | internal abstract class MusicalExpression 4 | { 5 | public virtual void Interpret(PlayContext context) 6 | { 7 | if (string.IsNullOrEmpty(context.PlayText)) 8 | { 9 | return; 10 | } 11 | 12 | var playKey = context.PlayText.Substring(0, 1); 13 | context.PlayText = context.PlayText.Substring(2); 14 | var playValue = context.PlayText.IndexOf(" ", StringComparison.Ordinal) > 0 ? Convert.ToDouble(context.PlayText.Substring(0, context.PlayText.IndexOf(" ", StringComparison.Ordinal))) : 0; 15 | 16 | context.PlayText = context.PlayText.Substring(context.PlayText.IndexOf(" ", StringComparison.Ordinal) + 1); 17 | 18 | Execute(playKey, playValue); 19 | } 20 | 21 | public abstract void Execute(string key, double value); 22 | } 23 | 24 | internal class MusicalNote : MusicalExpression 25 | { 26 | public override void Execute(string key, double value) 27 | { 28 | var note = key switch 29 | { 30 | "C" => "1", 31 | "D" => "2", 32 | "E" => "3", 33 | "F" => "4", 34 | "G" => "5", 35 | "A" => "6", 36 | "B" => "7", 37 | _ => string.Empty 38 | }; 39 | Console.Write($"{note} "); 40 | } 41 | } 42 | 43 | internal class MusicalScale : MusicalExpression 44 | { 45 | public override void Execute(string key, double value) 46 | { 47 | var scale = string.Empty; 48 | 49 | switch (value) 50 | { 51 | case 1: 52 | scale = "低音"; 53 | break; 54 | 55 | case 2: 56 | scale = "中音"; 57 | break; 58 | 59 | case 3: 60 | scale = "高音"; 61 | break; 62 | } 63 | 64 | Console.Write(scale + " "); 65 | } 66 | } 67 | 68 | internal class MusicalSpeed : MusicalExpression 69 | { 70 | public override void Execute(string key, double value) 71 | { 72 | string speed; 73 | if (value < 500) 74 | { 75 | speed = "快速"; 76 | } 77 | else if (value >= 1000) 78 | { 79 | speed = "快速"; 80 | } 81 | else 82 | { 83 | speed = "中速"; 84 | } 85 | Console.Write(speed + " "); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /BehaviorPattern/InterpreterPattern/PlayContext.cs: -------------------------------------------------------------------------------- 1 | namespace InterpreterPattern; 2 | 3 | internal class PlayContext 4 | { 5 | public string PlayText { get; set; } 6 | } 7 | -------------------------------------------------------------------------------- /BehaviorPattern/InterpreterPattern/Program.cs: -------------------------------------------------------------------------------- 1 | #region Prototype 2 | 3 | var context = new Context(); 4 | ICollection expressions = new List(); 5 | 6 | expressions.Add(new TerminalExpression()); 7 | expressions.Add(new TerminalExpression()); 8 | expressions.Add(new NoneTerminalExpression()); 9 | 10 | foreach (var expression in expressions) 11 | { 12 | expression.Interpret(context); 13 | } 14 | 15 | #endregion Prototype 16 | 17 | var playContext = new PlayContext 18 | { 19 | PlayText = "T 500 O 2 E 0.5 G 0.5 A 3 E 0.5 G 0.5 D 3 E 0.5 G 0.5 A 0.5 O 3 E 0.5 D 3 " 20 | }; 21 | MusicalExpression musicalExpression = null; 22 | 23 | while (!string.IsNullOrEmpty(playContext.PlayText)) 24 | { 25 | var str = playContext.PlayText.Substring(0, 1); 26 | switch (str) 27 | { 28 | case "O": 29 | musicalExpression = new MusicalScale(); 30 | break; 31 | 32 | case "T": 33 | musicalExpression = new MusicalSpeed(); 34 | break; 35 | 36 | case "A": 37 | case "B": 38 | case "C": 39 | case "D": 40 | case "E": 41 | case "F": 42 | case "G": 43 | case "P": 44 | musicalExpression = new MusicalNote(); 45 | break; 46 | } 47 | musicalExpression?.Interpret(playContext); 48 | } 49 | 50 | Console.ReadLine(); 51 | -------------------------------------------------------------------------------- /BehaviorPattern/InterpreterPattern/Prototype.cs: -------------------------------------------------------------------------------- 1 | namespace InterpreterPattern; 2 | 3 | internal class Context 4 | { 5 | public string Input { get; set; } 6 | public string Output { get; set; } 7 | } 8 | 9 | internal abstract class AbstractExpression 10 | { 11 | public abstract void Interpret(Context context); 12 | } 13 | 14 | internal class TerminalExpression : AbstractExpression 15 | { 16 | public override void Interpret(Context context) 17 | { 18 | Console.WriteLine("TerminalExpressionInterpreter"); 19 | } 20 | } 21 | 22 | internal class NoneTerminalExpression : AbstractExpression 23 | { 24 | public override void Interpret(Context context) 25 | { 26 | Console.WriteLine("NonTerminalExpressionInterpreter"); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /BehaviorPattern/InterpreterPattern/README.md: -------------------------------------------------------------------------------- 1 | # 解释器模式 Interpreter 2 | 3 | ## Intro 4 | 5 | 解释器模式,给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。 6 | 7 | 这和解释型编程语言的解释器有点类似,要根据一段输入转换成一段输出,将不易读的文本转换为易读的文本,将机器不能识别的输入转成二进制机器可读的输出 8 | 9 | 当有一个语言需要解释执行,并且你可以将该语言中的句子表示为一个抽象语法树时,可以使用解释器模式。 10 | 11 | ## Prototype 12 | 13 | - Context: 解释器上下文 14 | - AbstractExpression: 解释表达式抽象,定义解释操作 15 | - ConcreteExpression: 解释表达式实现类,实现具体的解释逻辑 16 | 17 | ## Sample 18 | 19 | ``` csharp 20 | public class Context 21 | { 22 | public string Input { get; set; } 23 | public string Output { get; set; } 24 | } 25 | 26 | public abstract class AbstractExpression 27 | { 28 | public abstract void Interpret(Context context); 29 | } 30 | public class TerminalExpression : AbstractExpression 31 | { 32 | public override void Interpret(Context context) 33 | { 34 | Console.WriteLine("TerminalExpressionInterpreter"); 35 | } 36 | } 37 | public class NoneTerminalExpression : AbstractExpression 38 | { 39 | public override void Interpret(Context context) 40 | { 41 | Console.WriteLine("NonTerminalExpressionInterpreter"); 42 | } 43 | } 44 | 45 | 46 | var context = new Context(); 47 | ICollection expressions = new List(); 48 | 49 | expressions.Add(new TerminalExpression()); 50 | expressions.Add(new TerminalExpression()); 51 | expressions.Add(new NoneTerminalExpression()); 52 | 53 | foreach (var expression in expressions) 54 | { 55 | expression.Interpret(context); 56 | } 57 | ``` 58 | 59 | ## More 60 | 61 | 更多设计模式及示例代码 [传送门](https://github.com/WeihanLi/DesignPatterns) 62 | -------------------------------------------------------------------------------- /BehaviorPattern/IteratorPattern/Aggregate.cs: -------------------------------------------------------------------------------- 1 | namespace IteratorPattern; 2 | 3 | internal abstract class Aggregate 4 | { 5 | /// 6 | /// 创建迭代器 7 | /// 8 | /// 9 | public abstract Iterator CreateIterator(); 10 | } 11 | 12 | internal class ConcreteAggregate : Aggregate 13 | { 14 | private readonly IList _items = new List(); 15 | 16 | public override Iterator CreateIterator() 17 | { 18 | return new ConcreteIterator(this); 19 | } 20 | 21 | public int TotalCount => _items.Count; 22 | 23 | public object this[int index] 24 | { 25 | get => _items[index]; 26 | set => _items.Insert(index, value); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /BehaviorPattern/IteratorPattern/Iterator.cs: -------------------------------------------------------------------------------- 1 | namespace IteratorPattern; 2 | 3 | internal abstract class Iterator 4 | { 5 | public abstract object First(); 6 | 7 | public abstract object Next(); 8 | 9 | public abstract bool IsDone(); 10 | 11 | public abstract object CurrentItem(); 12 | } 13 | 14 | internal class ConcreteIterator : Iterator 15 | { 16 | private readonly ConcreteAggregate _aggregate; 17 | private int _current = 0; 18 | 19 | public ConcreteIterator(ConcreteAggregate aggregate) => _aggregate = aggregate; 20 | 21 | public override object First() 22 | { 23 | return _aggregate[0]; 24 | } 25 | 26 | public override object Next() 27 | { 28 | _current++; 29 | return _current >= _aggregate.TotalCount ? null : _aggregate[_current]; 30 | } 31 | 32 | public override bool IsDone() => _current >= _aggregate.TotalCount; 33 | 34 | public override object CurrentItem() => _aggregate[_current]; 35 | } 36 | 37 | internal class ConcreteIteratorDesc : Iterator 38 | { 39 | private readonly ConcreteAggregate _aggregate; 40 | private int _current; 41 | 42 | public ConcreteIteratorDesc(ConcreteAggregate aggregate) 43 | { 44 | _aggregate = aggregate; 45 | _current = _aggregate.TotalCount - 1; 46 | } 47 | 48 | public override object First() => _aggregate[_aggregate.TotalCount - 1]; 49 | 50 | public override object Next() 51 | { 52 | _current--; 53 | return _current >= 0 ? _aggregate[_current] : null; 54 | } 55 | 56 | public override bool IsDone() => _current < 0; 57 | 58 | public override object CurrentItem() => _aggregate[_current]; 59 | } 60 | -------------------------------------------------------------------------------- /BehaviorPattern/IteratorPattern/IteratorPattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /BehaviorPattern/IteratorPattern/Program.cs: -------------------------------------------------------------------------------- 1 | var aggregate = new ConcreteAggregate 2 | { 3 | [0] = "大鸟", 4 | [1] = "小菜", 5 | [2] = "行李", 6 | [3] = "老外", 7 | [4] = "公交员工", 8 | [5] = "小偷" 9 | }; 10 | 11 | Console.WriteLine("ConcreteIterator:"); 12 | Iterator iterator = new ConcreteIterator(aggregate); 13 | do 14 | { 15 | Console.WriteLine($"{iterator.CurrentItem()} 请买车票"); 16 | iterator.Next(); 17 | } while (!iterator.IsDone()); 18 | 19 | Console.WriteLine("ConcreteIteratorDesc:"); 20 | Iterator iteratorDesc = new ConcreteIteratorDesc(aggregate); 21 | do 22 | { 23 | Console.WriteLine($"{iteratorDesc.CurrentItem()} 请买车票"); 24 | iteratorDesc.Next(); 25 | } while (!iteratorDesc.IsDone()); 26 | 27 | Console.ReadLine(); 28 | -------------------------------------------------------------------------------- /BehaviorPattern/IteratorPattern/README.md: -------------------------------------------------------------------------------- 1 | # 迭代器模式 Iterator 2 | 3 | ## Intro 4 | 5 | 迭代器模式,提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。 6 | 7 | 迭代器模式是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可以让外部代码透明地访问集合内部的数据。 8 | 9 | ## 使用场景 10 | 11 | 当你需要访问一个聚集对象,而且不管这些对象是什么都需要遍历的时候,你就应该考虑用迭代器模式。 12 | 13 | 当你需要对聚集有多种方式遍历时,可以考虑用迭代器模式。 14 | 15 | ## 实现方式 16 | 17 | 在 C# 中实现 `IEnumerable` 接口就可以比较方便的实现一个迭代器 18 | 19 | 来看它的实现: 20 | 21 | ``` csharp 22 | // 聚集抽象 23 | public interface IEnumerable 24 | { 25 | /// Returns an enumerator that iterates through a collection. 26 | /// An object that can be used to iterate through the collection. 27 | IEnumerator GetEnumerator(); 28 | } 29 | 30 | // 迭代器抽象 31 | public interface IEnumerator 32 | { 33 | /// Advances the enumerator to the next element of the collection. 34 | /// 35 | /// if the enumerator was successfully advanced to the next element; if the enumerator has passed the end of the collection. 36 | /// The collection was modified after the enumerator was created. 37 | bool MoveNext(); 38 | 39 | /// Gets the element in the collection at the current position of the enumerator. 40 | /// The element in the collection at the current position of the enumerator. 41 | object Current { get; } 42 | 43 | /// Sets the enumerator to its initial position, which is before the first element in the collection. 44 | /// The collection was modified after the enumerator was created. 45 | void Reset(); 46 | } 47 | ``` 48 | 49 | 如果要自己实现需要有下面几个类: 50 | 51 | 一个迭代器抽象类(或接口) 52 | 53 | 一个聚集抽象类(或接口) 54 | 55 | 具体实现的迭代器类 56 | 57 | 具体实现的聚集类 58 | 59 | ## Sample 60 | 61 | ``` csharp 62 | public abstract class Iterator 63 | { 64 | public abstract object First(); 65 | 66 | public abstract object Next(); 67 | 68 | public abstract bool IsDone(); 69 | 70 | public abstract object CurrentItem(); 71 | } 72 | 73 | public class ConcreteIterator : Iterator 74 | { 75 | private readonly ConcreteAggregate _aggregate; 76 | private int _current = 0; 77 | 78 | public ConcreteIterator(ConcreteAggregate aggregate) => _aggregate = aggregate; 79 | 80 | public override object First() 81 | { 82 | return _aggregate[0]; 83 | } 84 | 85 | public override object Next() 86 | { 87 | _current++; 88 | return _current >= _aggregate.TotalCount ? null : _aggregate[_current]; 89 | } 90 | 91 | public override bool IsDone() => _current >= _aggregate.TotalCount; 92 | 93 | public override object CurrentItem() => _aggregate[_current]; 94 | } 95 | 96 | public abstract class Aggregate 97 | { 98 | /// 99 | /// 创建迭代器 100 | /// 101 | /// 102 | public abstract Iterator CreateIterator(); 103 | } 104 | 105 | public class ConcreteAggregate : Aggregate 106 | { 107 | private readonly IList _items = new List(); 108 | 109 | public override Iterator CreateIterator() 110 | { 111 | return new ConcreteIterator(this); 112 | } 113 | 114 | public int TotalCount => _items.Count; 115 | 116 | public object this[int index] 117 | { 118 | get => _items[index]; 119 | set => _items.Insert(index, value); 120 | } 121 | } 122 | 123 | 124 | var aggregate = new ConcreteAggregate 125 | { 126 | [0] = "大鸟", 127 | [1] = "小菜", 128 | [2] = "行李", 129 | [3] = "老外", 130 | [4] = "公交员工", 131 | [5] = "小偷" 132 | }; 133 | 134 | Iterator iterator = new ConcreteIterator(aggregate); 135 | do 136 | { 137 | Console.WriteLine($"{iterator.CurrentItem()} 请买车票"); 138 | iterator.Next(); 139 | } while (!iterator.IsDone()); 140 | 141 | ``` 142 | 143 | ## More 144 | 145 | 更多设计模式及示例代码 [传送门](https://github.com/WeihanLi/DesignPatterns) 146 | -------------------------------------------------------------------------------- /BehaviorPattern/MediatorPattern/Colleague.cs: -------------------------------------------------------------------------------- 1 | namespace MediatorPattern; 2 | 3 | internal abstract class Colleague 4 | { 5 | protected Mediator Mediator; 6 | 7 | protected Colleague(Mediator mediator) => Mediator = mediator; 8 | 9 | public abstract void Notify(string message); 10 | } 11 | 12 | internal class ConcreteColleague1 : Colleague 13 | { 14 | public ConcreteColleague1(Mediator mediator) : base(mediator) 15 | { 16 | } 17 | 18 | public void Send(string message) 19 | { 20 | Mediator.Send(message, this); 21 | } 22 | 23 | public override void Notify(string message) 24 | { 25 | Console.WriteLine($"同事1 得到信息:{message}"); 26 | } 27 | } 28 | 29 | internal class ConcreteColleague2 : Colleague 30 | { 31 | public ConcreteColleague2(Mediator mediator) : base(mediator) 32 | { 33 | } 34 | 35 | public void Send(string message) 36 | { 37 | Mediator.Send(message, this); 38 | } 39 | 40 | public override void Notify(string message) 41 | { 42 | Console.WriteLine($"同事2 得到信息:{message}"); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /BehaviorPattern/MediatorPattern/Mediator.cs: -------------------------------------------------------------------------------- 1 | namespace MediatorPattern; 2 | 3 | internal abstract class Mediator 4 | { 5 | public abstract void Send(string message, Colleague colleague); 6 | } 7 | 8 | internal class ConcreteMediator : Mediator 9 | { 10 | public Colleague Colleague1 { private get; set; } 11 | public Colleague Colleague2 { private get; set; } 12 | 13 | public override void Send(string message, Colleague colleague) 14 | { 15 | if (colleague == Colleague1) 16 | { 17 | Colleague2.Notify(message); 18 | } 19 | else 20 | { 21 | Colleague1.Notify(message); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /BehaviorPattern/MediatorPattern/MediatorPattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /BehaviorPattern/MediatorPattern/Program.cs: -------------------------------------------------------------------------------- 1 | var mediator = new ConcreteMediator(); 2 | 3 | var c1 = new ConcreteColleague1(mediator); 4 | var c2 = new ConcreteColleague2(mediator); 5 | mediator.Colleague1 = c1; 6 | mediator.Colleague2 = c2; 7 | 8 | c1.Send("吃饭了吗?"); 9 | c2.Send("没有呢,你打算请客?"); 10 | 11 | Console.ReadLine(); 12 | -------------------------------------------------------------------------------- /BehaviorPattern/MediatorPattern/README.md: -------------------------------------------------------------------------------- 1 | # 中介者模式 Mediator 2 | 3 | ## Intro 4 | 5 | > 中介者模式,用一个中介对象来封装一系列的对象交互。 6 | > 中介者使得各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变他们之间的交互。 7 | 8 | ## 使用场景 9 | 10 | 中介者模式一般应用于一组对象以定义良好但是复杂的方式进行通信的场合,以及想定制一个分布在多个类种的行为而又不想生成太多子类的场合。 11 | 12 | ## 优缺点 13 | 14 | > 中介者模式很容易在系统中应用,也很容易在系统中误用。当系统出现了“多对多”交互复杂的对象群时,不要急于使用中介者模式,而要先反思你的系统在设计上是不是合理。 15 | 16 | - 优点 17 | 18 | > 中介者(`Mediator`)的出现减少了各个 `Colleague` 的耦合,使得可以独立地改变和复用各个 `Colleague` 类和 `Mediator`;其次,由于把对象如何协作进行了抽象,将中介作为一个独立的概念并将其封装在一个对象中,这样关注的对象就从对象各自本身的行为转移到它们之间的交互上来,也就是站在一个更宏观的角度去看待系统 19 | 20 | - 缺点 21 | 22 | > 由于 `ConcreteMediator` 控制了集中化,于是就把交互复杂性变为了中介者的复杂性,这就使得中介者会变得比任何一个 `ConcreteColleague` 都复杂 23 | 24 | 25 | ## Sample 26 | 27 | ``` csharp 28 | public abstract class Mediator 29 | { 30 | public abstract void Send(string message, Colleague colleague); 31 | } 32 | 33 | public class ConcreteMediator : Mediator 34 | { 35 | public Colleague Colleague1 { private get; set; } 36 | public Colleague Colleague2 { private get; set; } 37 | 38 | public override void Send(string message, Colleague colleague) 39 | { 40 | if (colleague == Colleague1) 41 | { 42 | Colleague2.Notify(message); 43 | } 44 | else 45 | { 46 | Colleague1.Notify(message); 47 | } 48 | } 49 | } 50 | 51 | public abstract class Colleague 52 | { 53 | protected Mediator Mediator; 54 | 55 | protected Colleague(Mediator mediator) => Mediator = mediator; 56 | 57 | public abstract void Notify(string message); 58 | } 59 | public class ConcreteColleague1 : Colleague 60 | { 61 | public ConcreteColleague1(Mediator mediator) : base(mediator) 62 | { 63 | } 64 | 65 | public void Send(string message) 66 | { 67 | Mediator.Send(message, this); 68 | } 69 | 70 | public override void Notify(string message) 71 | { 72 | Console.WriteLine($"同事1 得到信息:{message}"); 73 | } 74 | } 75 | public class ConcreteColleague2 : Colleague 76 | { 77 | public ConcreteColleague2(Mediator mediator) : base(mediator) 78 | { 79 | } 80 | 81 | public void Send(string message) 82 | { 83 | Mediator.Send(message, this); 84 | } 85 | 86 | public override void Notify(string message) 87 | { 88 | Console.WriteLine($"同事2 得到信息:{message}"); 89 | } 90 | } 91 | 92 | 93 | var mediator = new ConcreteMediator(); 94 | 95 | var c1 = new ConcreteColleague1(mediator); 96 | var c2 = new ConcreteColleague2(mediator); 97 | mediator.Colleague1 = c1; 98 | mediator.Colleague2 = c2; 99 | 100 | c1.Send("吃饭了吗?"); 101 | c2.Send("没有呢,你打算请客?"); 102 | ``` 103 | 104 | ## More 105 | 106 | 更多设计模式及示例代码 [传送门](https://github.com/WeihanLi/DesignPatterns) 107 | -------------------------------------------------------------------------------- /BehaviorPattern/MementoPattern/GameRole.cs: -------------------------------------------------------------------------------- 1 | namespace MementoPattern; 2 | 3 | internal class GameRole 4 | { 5 | public GameRole() 6 | { 7 | Vitality = 100; 8 | Attack = 100; 9 | Defense = 100; 10 | } 11 | 12 | /// 13 | /// 生命力 14 | /// 15 | public int Vitality { get; set; } 16 | 17 | /// 18 | /// 攻击力 19 | /// 20 | public int Attack { get; set; } 21 | 22 | /// 23 | /// 防御力 24 | /// 25 | public int Defense { get; set; } 26 | 27 | public void StateDisplay() 28 | { 29 | Console.WriteLine("角色当前状态:"); 30 | Console.WriteLine($"生命力:{Vitality}"); 31 | Console.WriteLine($"攻击力:{Attack}"); 32 | Console.WriteLine($"防御力:{Defense}"); 33 | Console.WriteLine(); 34 | } 35 | 36 | public void FightWithBoss() 37 | { 38 | Vitality = 1; 39 | Attack = 10; 40 | Defense = 0; 41 | } 42 | 43 | public RoleStateMemento SaveState() 44 | { 45 | return new RoleStateMemento(Vitality, Attack, Defense); 46 | } 47 | 48 | public void RecoveryState(RoleStateMemento memento) 49 | { 50 | Vitality = memento.Vitality; 51 | Attack = memento.Attack; 52 | Defense = memento.Defense; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /BehaviorPattern/MementoPattern/MementoPattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /BehaviorPattern/MementoPattern/Program.cs: -------------------------------------------------------------------------------- 1 | #region Prototype 2 | 3 | var originator = new Originator 4 | { 5 | State = "On" 6 | }; 7 | originator.Show(); 8 | 9 | var caretaker = new Caretaker 10 | { 11 | Memento = originator.CreateMemento() 12 | }; 13 | 14 | originator.State = "Off"; 15 | originator.Show(); 16 | 17 | originator.SetMemento(caretaker.Memento); 18 | originator.Show(); 19 | 20 | Console.WriteLine(); 21 | 22 | #endregion Prototype 23 | 24 | var lixiaoyao = new GameRole(); 25 | lixiaoyao.StateDisplay(); 26 | 27 | //保存状态 28 | var stateCaretaker = new RoleStateCaretaker 29 | { 30 | Memento = lixiaoyao.SaveState() 31 | }; 32 | 33 | // 大战 Boss 34 | lixiaoyao.FightWithBoss(); 35 | lixiaoyao.StateDisplay(); 36 | 37 | // 快被 Boss 打挂了,恢复之前的状态,继续打 38 | lixiaoyao.RecoveryState(stateCaretaker.Memento); 39 | lixiaoyao.StateDisplay(); 40 | 41 | Console.ReadLine(); 42 | -------------------------------------------------------------------------------- /BehaviorPattern/MementoPattern/Prototype.cs: -------------------------------------------------------------------------------- 1 | namespace MementoPattern; 2 | 3 | /// 4 | /// 发起人 5 | /// 6 | internal class Originator 7 | { 8 | public string State { get; set; } 9 | 10 | public Memento CreateMemento() 11 | { 12 | return new Memento(State); 13 | } 14 | 15 | public void SetMemento(Memento memento) 16 | { 17 | State = memento?.State; 18 | } 19 | 20 | public void Show() 21 | { 22 | Console.WriteLine($"State:{State}"); 23 | } 24 | } 25 | 26 | internal class Memento 27 | { 28 | public string State { get; } 29 | 30 | public Memento(string state) => State = state; 31 | } 32 | 33 | internal class Caretaker 34 | { 35 | public Memento Memento { get; set; } 36 | } 37 | -------------------------------------------------------------------------------- /BehaviorPattern/MementoPattern/README.md: -------------------------------------------------------------------------------- 1 | # 备忘录模式 Memento 2 | 3 | ## Intro 4 | 5 | > 备忘录模式,在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。 6 | 7 | ## 使用场景 8 | 9 | 备忘录(Memento)模式比较适用于功能比较复杂的,但需要维护或记录属性历史的类,或者需要保存的属性只是众多属性中的一小部分时, 10 | 11 | `Originator` 可以根据保存的 `Memento` 信息还原到前一状态。 12 | 13 | 可以用来做数据(状态)备份和恢复。 14 | 15 | ## Prototype 16 | 17 | - Originator 拥有状态的宿主,需要提供一个入口来获取和更新当前状态 18 | - State/Memento 需要备份状态信息 19 | - Caretaker 状态备忘录,备份状态信息 20 | 21 | ## Sample 22 | 23 | ``` csharp 24 | internal class Originator 25 | { 26 | public string State { get; set; } 27 | 28 | public Memento CreateMemento() 29 | { 30 | return new Memento(State); 31 | } 32 | 33 | public void SetMemento(Memento memento) 34 | { 35 | State = memento?.State; 36 | } 37 | 38 | public void Show() 39 | { 40 | Console.WriteLine($"State:{State}"); 41 | } 42 | } 43 | 44 | internal class Memento 45 | { 46 | public string State { get; } 47 | 48 | public Memento(string state) => State = state; 49 | } 50 | 51 | internal class Caretaker 52 | { 53 | public Memento Memento { get; set; } 54 | } 55 | 56 | var originator = new Originator 57 | { 58 | State = "On" 59 | }; 60 | originator.Show(); 61 | 62 | var caretaker = new Caretaker 63 | { 64 | Memento = originator.CreateMemento() 65 | }; 66 | 67 | originator.State = "Off"; 68 | originator.Show(); 69 | 70 | originator.SetMemento(caretaker.Memento); 71 | originator.Show(); 72 | ``` 73 | 74 | ## More 75 | 76 | 更多设计模式及示例代码 [传送门](https://github.com/WeihanLi/DesignPatterns) 77 | -------------------------------------------------------------------------------- /BehaviorPattern/MementoPattern/RoleStateCarertaker.cs: -------------------------------------------------------------------------------- 1 | namespace MementoPattern; 2 | 3 | /// 4 | /// 角色状态管理者 5 | /// 6 | internal class RoleStateCaretaker 7 | { 8 | public RoleStateMemento Memento { get; set; } 9 | } 10 | -------------------------------------------------------------------------------- /BehaviorPattern/MementoPattern/RoleStateMemento.cs: -------------------------------------------------------------------------------- 1 | namespace MementoPattern; 2 | 3 | /// 4 | /// 游戏角色信息备忘录 5 | /// 6 | internal class RoleStateMemento 7 | { 8 | public RoleStateMemento(int vitality, int attack, int defense) 9 | { 10 | Vitality = vitality; 11 | Attack = attack; 12 | Defense = defense; 13 | } 14 | 15 | /// 16 | /// 生命力 17 | /// 18 | public int Vitality { get; } 19 | 20 | /// 21 | /// 攻击力 22 | /// 23 | public int Attack { get; } 24 | 25 | /// 26 | /// 防御力 27 | /// 28 | public int Defense { get; } 29 | } 30 | -------------------------------------------------------------------------------- /BehaviorPattern/ObserverPattern/Boss.cs: -------------------------------------------------------------------------------- 1 | namespace ObserverPattern; 2 | 3 | internal class Boss : ISubject 4 | { 5 | private readonly IList _observers = new List(); 6 | 7 | public void Attach(Observer observer) 8 | { 9 | _observers.Add(observer); 10 | } 11 | 12 | public void Detach(Observer observer) 13 | { 14 | _observers.Remove(observer); 15 | } 16 | 17 | public void Notify() 18 | { 19 | foreach (var observer in _observers) 20 | { 21 | observer.Update(); 22 | } 23 | } 24 | 25 | public string SubjectState { get; set; } 26 | } 27 | 28 | internal class NewBoss : ISubject 29 | { 30 | public event Action Update; 31 | 32 | public void Notify() 33 | { 34 | Update?.Invoke(); 35 | } 36 | 37 | public string SubjectState { get; set; } 38 | } 39 | -------------------------------------------------------------------------------- /BehaviorPattern/ObserverPattern/ISubject.cs: -------------------------------------------------------------------------------- 1 | namespace ObserverPattern; 2 | 3 | internal interface ISubject 4 | { 5 | void Notify(); 6 | 7 | string SubjectState { get; set; } 8 | } 9 | -------------------------------------------------------------------------------- /BehaviorPattern/ObserverPattern/Observer.cs: -------------------------------------------------------------------------------- 1 | namespace ObserverPattern; 2 | 3 | internal abstract class Observer 4 | { 5 | protected string Name; 6 | protected ISubject Subject; 7 | 8 | protected Observer(string name, ISubject subject) 9 | { 10 | Name = name; 11 | Subject = subject; 12 | } 13 | 14 | public abstract void Update(); 15 | } 16 | 17 | internal class StockObserver : Observer 18 | { 19 | public StockObserver(string name, ISubject subject) : base(name, subject) 20 | { 21 | } 22 | 23 | public override void Update() 24 | { 25 | Console.WriteLine($"{Name} {Subject.SubjectState} 关闭股票行情,继续工作"); 26 | } 27 | } 28 | 29 | // ReSharper disable once InconsistentNaming 30 | internal class NBAObserver : Observer 31 | { 32 | public NBAObserver(string name, ISubject subject) : base(name, subject) 33 | { 34 | } 35 | 36 | public override void Update() 37 | { 38 | Console.WriteLine($"{Name} {Subject.SubjectState} 关闭 NBA 直播,继续工作"); 39 | } 40 | } 41 | 42 | internal class GamePlayerObserver 43 | { 44 | private readonly string _name; 45 | private readonly ISubject _subject; 46 | 47 | public GamePlayerObserver(string name, ISubject subject) 48 | { 49 | _name = name; 50 | _subject = subject; 51 | } 52 | 53 | public void CloseGame() 54 | { 55 | Console.WriteLine($"{_name} {_subject.SubjectState} 关闭 LOL 游戏,继续工作"); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /BehaviorPattern/ObserverPattern/ObserverPattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /BehaviorPattern/ObserverPattern/Program.cs: -------------------------------------------------------------------------------- 1 | var boss = new Boss(); 2 | 3 | var stockObserver = new StockObserver("魏关姹", boss); 4 | var nbaObserver = new NBAObserver("易管查", boss); 5 | 6 | boss.Attach(stockObserver); 7 | boss.Attach(nbaObserver); 8 | 9 | boss.Detach(stockObserver); 10 | 11 | boss.SubjectState = "老板我胡汉三回来了"; 12 | 13 | boss.Notify(); 14 | Console.WriteLine(); 15 | 16 | // 借助多播委托来实现,通过事件来通知的新老板 17 | var newBoss = new NewBoss(); 18 | var gameObserver = new GamePlayerObserver("西门", newBoss); 19 | 20 | // 注册通知事件 21 | newBoss.Update += stockObserver.Update; 22 | newBoss.Update += nbaObserver.Update; 23 | newBoss.Update += gameObserver.CloseGame; 24 | 25 | newBoss.SubjectState = "老板我胡汉三回来了"; 26 | newBoss.Notify(); 27 | 28 | Console.ReadLine(); 29 | -------------------------------------------------------------------------------- /BehaviorPattern/ObserverPattern/README.md: -------------------------------------------------------------------------------- 1 | # 观察者模式 Observer 2 | 3 | ## Intro 4 | 5 | > 观察者模式又叫做 发布订阅(Publish/Subscribe)模式 6 | > 观察者模式定义了一种一对多的依赖关系,让多个观察者同时监听某一主题对象。 7 | > 这个主题对象在状态发生变化时,会通知所有观察者对象,使得他们能够自动更新自己。 8 | 9 | ## 使用场景 10 | 11 | 观察者模式所做的工作其实就是在解耦,让耦合的双方都依赖于抽象而不是具体,从而使得各自的变化都不会影响另一边的变化。 12 | 13 | 当一个对象的改变需要改变其他对象的时候,而且它不知道具体有多少对象有待改变的时候,应该考虑使用观察者模式。 14 | 15 | 一个抽象模型有两方面,其中一方面依赖于另一方面,这时用观察者模式可以将这两者封装在独立的对象中使得他们各自独立地改变和复用。 16 | 17 | ## Sample 18 | 19 | 20 | ``` csharp 21 | public interface ISubject 22 | { 23 | void Notify(); 24 | 25 | string SubjectState { get; set; } 26 | } 27 | public class Boss : ISubject 28 | { 29 | private readonly IList _observers = new List(); 30 | 31 | public void Attach(Observer observer) 32 | { 33 | _observers.Add(observer); 34 | } 35 | 36 | public void Detach(Observer observer) 37 | { 38 | _observers.Remove(observer); 39 | } 40 | 41 | public void Notify() 42 | { 43 | foreach (var observer in _observers) 44 | { 45 | observer.Update(); 46 | } 47 | } 48 | 49 | public string SubjectState { get; set; } 50 | } 51 | 52 | public abstract class Observer 53 | { 54 | protected string Name; 55 | protected ISubject Subject; 56 | 57 | protected Observer(string name, ISubject subject) 58 | { 59 | Name = name; 60 | Subject = subject; 61 | } 62 | 63 | public abstract void Update(); 64 | } 65 | public class StockObserver : Observer 66 | { 67 | public StockObserver(string name, ISubject subject) : base(name, subject) 68 | { 69 | } 70 | 71 | public override void Update() 72 | { 73 | Console.WriteLine($"{Name} {Subject.SubjectState} 关闭股票行情,继续工作"); 74 | } 75 | } 76 | public class NBAObserver : Observer 77 | { 78 | public NBAObserver(string name, ISubject subject) : base(name, subject) 79 | { 80 | } 81 | 82 | public override void Update() 83 | { 84 | Console.WriteLine($"{Name} {Subject.SubjectState} 关闭 NBA 直播,继续工作"); 85 | } 86 | } 87 | 88 | 89 | var boss = new Boss(); 90 | var stockObserver = new StockObserver("魏关姹", boss); 91 | var nbaObserver = new NBAObserver("易管查", boss); 92 | 93 | boss.Attach(stockObserver); 94 | boss.Attach(nbaObserver); 95 | 96 | boss.Detach(stockObserver); 97 | 98 | boss.SubjectState = "老板我胡汉三回来了"; 99 | boss.Notify(); 100 | ``` 101 | 102 | 借助 event(委托) 我们可以实现可以灵活的观察者模式,我们定义了一个新老板来演示事件的方式,来看下面的示例: 103 | 104 | ``` csharp 105 | public class NewBoss : ISubject 106 | { 107 | public event Action Update; 108 | 109 | public void Notify() 110 | { 111 | Update?.Invoke(); 112 | } 113 | 114 | public string SubjectState { get; set; } 115 | } 116 | 117 | public class GamePlayerObserver 118 | { 119 | private readonly string _name; 120 | private readonly ISubject _subject; 121 | 122 | public GamePlayerObserver(string name, ISubject subject) 123 | { 124 | _name = name; 125 | _subject = subject; 126 | } 127 | 128 | public void CloseGame() 129 | { 130 | Console.WriteLine($"{_name} {_subject.SubjectState} 关闭 LOL 游戏,继续工作"); 131 | } 132 | } 133 | 134 | var newBoss = new NewBoss(); 135 | var stockObserver = new StockObserver("魏关姹", boss); 136 | var nbaObserver = new NBAObserver("易管查", boss); 137 | var gameObserver = new GamePlayerObserver("西门", newBoss); 138 | 139 | // 注册通知事件 140 | newBoss.Update += stockObserver.Update; 141 | newBoss.Update += nbaObserver.Update; 142 | newBoss.Update += gameObserver.CloseGame; 143 | 144 | newBoss.Update -= stockObserver.Update; 145 | 146 | newBoss.SubjectState = "老板我胡汉三回来了"; 147 | newBoss.Notify(); 148 | ``` 149 | 150 | 从上面这个示例可以看到,通过事件的方式,我们可以不要求显示继承于 `Observer` 这个抽象类,可以更加灵活,扩展性更强,这也是很多类库中会使用事件来扩展的重要原因 151 | 152 | ## More 153 | 154 | 更多设计模式及示例代码 [传送门](https://github.com/WeihanLi/DesignPatterns) 155 | -------------------------------------------------------------------------------- /BehaviorPattern/README.md: -------------------------------------------------------------------------------- 1 | # 行为型设计模式总结 2 | 3 | ## Intro 4 | 5 | 行为型模式是将不同的行为代码解耦,从而解决特定场景问题的一些经典结构。 6 | 7 | 行为型设计模式主要解决的就是“类或对象之间的交互”问题。行为型设计模式比较多,有 11 个,几乎占了 23 种经典设计模式的一半。它们分别是:观察者模式、模板模式、策略模式、职责链模式、状态模式、迭代器模式、访问者模式、备忘录模式、命令模式、解释器模式、中介模式。 8 | 9 | ## 总结 10 | 11 | ### 责任链(Chain of Responsibility) 12 | 13 | 多个处理器依次处理同一个请求。一个请求先经过 A 处理器处理,然后再把请求传递给 B 处理器,B 处理器处理完后再传递给 C 处理器,以此类推,形成一个链条。链条上的每个处理器各自承担各自的处理职责。 14 | 15 | ### 模板方法模式(Template Method) 16 | 17 | 定义一个操作中的算法骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算的结构即使重定义该算法的某些特定步骤。 18 | 19 | 换句话说,公用的处理逻辑放在父类中处理,不同的处理逻辑放在子类中 20 | 21 | ### 迭代器(Iterator) 22 | 23 | 提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。常用于遍历一个集合对象 24 | 25 | ### 备忘录模式(Memento) 26 | 27 | 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。多用于数据备份和恢复的场景。 28 | 29 | ### 状态模式(State) 30 | 31 | 当一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为时就可以考虑状态模式 32 | 33 | ### 观察者模式(Observer) 34 | 35 | 在对象之间定义一个一对多的依赖,当一个对象状态改变的时候,所有依赖的对象都会自动收到通知。将观察者和被观察者代码解耦。 36 | 37 | ### 命令模式 (Command) 38 | 39 | 将一个请求封装为一个对象,从而使得可以用不同的请求进行参数化,对请求排队或者记录请求日志以及支持可撤销的操作。 40 | 41 | ### 中介模式(Mediator) 42 | 43 | 中介模式定义了一个单独的(中介)对象,来封装一组对象之间的交互。将这组对象之间的交互委派给与中介对象交互,来避免对象之间的直接交互。 44 | 45 | ### 策略模式(Strategy) 46 | 47 | 策略模式会定义一系列算法,从概念上来看,所有这些算法完全的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用类之间的耦合。 48 | 49 | ### 解释器模式(Interpreter) 50 | 51 | 当有一个语言需要解释执行,并且你可以将该语言中的句子表示为一个抽象语法树时,可以使用解释器模式 52 | 53 | ### 访问者模式(Visitor) 54 | 55 | 访问者模式适用于数据结构相对稳定的系统,它把数据结构和作用域结构上的操作之间的耦合解脱开,使用操作集合可以相对自由地演化。 56 | 57 | ## Reference 58 | 59 | - [责任链模式](./ChainOfResponsibilityPattern) 60 | - [模板方法模式](./TemplateMethodPattern) 61 | - [迭代器模式](./IteratorPattern) 62 | - [备忘录模式](./MementoPattern) 63 | - [状态模式](./StatePattern) 64 | - [观察者模式](./ObserverPattern) 65 | - [命令模式](./CommandPattern) 66 | - [中介者模式](./MediatorPattern) 67 | - [策略模式](./StrategyPattern) 68 | - [访问者模式](./VisitorPattern) 69 | - [解释器模式](./InterpreterPattern) 70 | - [访问者模式](./VisitorPattern) 71 | -------------------------------------------------------------------------------- /BehaviorPattern/StatePattern/Program.cs: -------------------------------------------------------------------------------- 1 | #region Prototype 2 | 3 | var context = new Context(new ConcreteStateA()); 4 | context.Request(); 5 | context.Request(); 6 | context.Request(); 7 | context.Request(); 8 | 9 | Console.WriteLine(); 10 | 11 | #endregion Prototype 12 | 13 | var emergenceWork = new Work(); 14 | 15 | emergenceWork.Hour = 9; 16 | emergenceWork.WriteProgram(); 17 | 18 | emergenceWork.Hour = 10; 19 | emergenceWork.WriteProgram(); 20 | 21 | emergenceWork.Hour = 12; 22 | emergenceWork.WriteProgram(); 23 | 24 | emergenceWork.Hour = 13; 25 | emergenceWork.WriteProgram(); 26 | 27 | emergenceWork.Hour = 14; 28 | emergenceWork.WriteProgram(); 29 | 30 | emergenceWork.Hour = 17; 31 | emergenceWork.WriteProgram(); 32 | 33 | emergenceWork.TaskFinished = true;//任务完成,可以提前回家了 34 | // emergenceWork.TaskFinished = false;//任务没完成,在公司加班吧 35 | 36 | emergenceWork.Hour = 19; 37 | emergenceWork.WriteProgram(); 38 | 39 | emergenceWork.Hour = 21; 40 | emergenceWork.WriteProgram(); 41 | 42 | Console.ReadLine(); 43 | -------------------------------------------------------------------------------- /BehaviorPattern/StatePattern/Prototype.cs: -------------------------------------------------------------------------------- 1 | namespace StatePattern; 2 | 3 | internal class Context 4 | { 5 | private State _state; 6 | 7 | public Context(State state) => _state = state; 8 | 9 | public State State 10 | { 11 | get => _state; 12 | set 13 | { 14 | _state = value; 15 | Console.WriteLine($"当前状态:{_state.GetType().Name}"); 16 | } 17 | } 18 | 19 | public void Request() 20 | { 21 | _state.Handle(this); 22 | } 23 | } 24 | 25 | internal abstract class State 26 | { 27 | public abstract void Handle(Context context); 28 | } 29 | 30 | internal class ConcreteStateA : State 31 | { 32 | public override void Handle(Context context) 33 | { 34 | context.State = new ConcreteStateB(); //设置 ConcreteStateA 的下一状态是 ConcreteStateB 35 | } 36 | } 37 | 38 | internal class ConcreteStateB : State 39 | { 40 | public override void Handle(Context context) 41 | { 42 | context.State = new ConcreteStateA();//设置 ConcreteStateB 的下一状态是 ConcreteStateA 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /BehaviorPattern/StatePattern/README.md: -------------------------------------------------------------------------------- 1 | # 状态模式 State 2 | 3 | ## Intro 4 | 5 | > 状态模式(State),当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。 6 | 7 | ## 使用场景 8 | 9 | 当一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为时就可以考虑状态模式。 10 | 11 | 状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。 12 | 13 | 状态模式的好处是将与特定状态相关的行为局部化,并且将不同状态的行为分隔开来。将特定的状态相关的行为都放入一个对象中,由于所有与状态相关的代码都存在于某个 `State` 中,所以通过定义新的子类可以很容易地增加新地状态和转换。 14 | 15 | 状态模式通过把各种状态转义逻辑分布到 `State` 的子类之间,来减少相互之间地依赖。 16 | 17 | ## Sample 18 | 19 | ``` csharp 20 | class Work 21 | { 22 | private WorkState _currentState; 23 | 24 | public Work() 25 | { 26 | _currentState = new ForenoonState(); 27 | } 28 | 29 | public int Hour { get; set; } 30 | 31 | public bool TaskFinished { get; set; } 32 | 33 | public void SetState(WorkState workState) 34 | { 35 | _currentState = workState; 36 | } 37 | 38 | public void WriteProgram() 39 | { 40 | _currentState.WriteProgram(this); 41 | } 42 | } 43 | 44 | 45 | internal abstract class WorkState 46 | { 47 | public abstract void WriteProgram(Work work); 48 | } 49 | 50 | internal class ForenoonState : WorkState 51 | { 52 | public override void WriteProgram(Work work) 53 | { 54 | if (work.Hour < 12) 55 | { 56 | Console.WriteLine($"当前时间:{work.Hour}点 上午工作,精神百倍"); 57 | } 58 | else 59 | { 60 | work.SetState(new NoonState()); 61 | work.WriteProgram(); 62 | } 63 | } 64 | } 65 | 66 | internal class NoonState : WorkState 67 | { 68 | public override void WriteProgram(Work work) 69 | { 70 | if (work.Hour < 13) 71 | { 72 | Console.WriteLine($"当前时间:{work.Hour}点 饿了,午饭。犯困,午休"); 73 | } 74 | else 75 | { 76 | work.SetState(new AfternoonState()); 77 | work.WriteProgram(); 78 | } 79 | } 80 | } 81 | 82 | internal class AfternoonState : WorkState 83 | { 84 | public override void WriteProgram(Work work) 85 | { 86 | if (work.Hour < 18) 87 | { 88 | Console.WriteLine($"当前时间:{work.Hour}点 下午状态还不错,继续努力"); 89 | } 90 | else 91 | { 92 | work.SetState(new EveningState()); 93 | work.WriteProgram(); 94 | } 95 | } 96 | } 97 | 98 | internal class EveningState : WorkState 99 | { 100 | public override void WriteProgram(Work work) 101 | { 102 | if (work.TaskFinished) 103 | { 104 | work.SetState(new RestState()); 105 | work.WriteProgram(); 106 | } 107 | else 108 | { 109 | if (work.Hour < 21) 110 | { 111 | Console.WriteLine($"当前时间:{work.Hour}点 还在加班啊,疲累之极"); 112 | } 113 | else 114 | { 115 | work.SetState(new SleepingState()); 116 | work.WriteProgram(); 117 | } 118 | } 119 | } 120 | } 121 | 122 | internal class RestState : WorkState 123 | { 124 | public override void WriteProgram(Work work) 125 | { 126 | Console.WriteLine($"当前时间:{work.Hour}点 下班回家了"); 127 | } 128 | } 129 | 130 | internal class SleepingState : WorkState 131 | { 132 | public override void WriteProgram(Work work) 133 | { 134 | Console.WriteLine($"当前时间:{work.Hour}点了,不行了,睡着了。"); 135 | } 136 | } 137 | 138 | 139 | var emergenceWork = new Work(); 140 | 141 | emergenceWork.Hour = 9; 142 | emergenceWork.WriteProgram(); 143 | 144 | emergenceWork.Hour = 10; 145 | emergenceWork.WriteProgram(); 146 | 147 | emergenceWork.Hour = 12; 148 | emergenceWork.WriteProgram(); 149 | 150 | emergenceWork.Hour = 13; 151 | emergenceWork.WriteProgram(); 152 | 153 | emergenceWork.Hour = 14; 154 | emergenceWork.WriteProgram(); 155 | 156 | emergenceWork.Hour = 17; 157 | emergenceWork.WriteProgram(); 158 | 159 | emergenceWork.TaskFinished = true;//任务完成,可以提前回家了 160 | // emergenceWork.TaskFinished = false;//任务没完成,在公司加班吧 161 | 162 | emergenceWork.Hour = 19; 163 | emergenceWork.WriteProgram(); 164 | 165 | emergenceWork.Hour = 21; 166 | emergenceWork.WriteProgram(); 167 | ``` 168 | 169 | ## More 170 | 171 | 更多设计模式及示例代码 [传送门](https://github.com/WeihanLi/DesignPatterns) 172 | -------------------------------------------------------------------------------- /BehaviorPattern/StatePattern/StatePattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /BehaviorPattern/StatePattern/Work.cs: -------------------------------------------------------------------------------- 1 | namespace StatePattern; 2 | 3 | internal class Work 4 | { 5 | private WorkState _currentState; 6 | 7 | public Work() 8 | { 9 | _currentState = new ForenoonState(); 10 | } 11 | 12 | public int Hour { get; set; } 13 | 14 | public bool TaskFinished { get; set; } 15 | 16 | public void SetState(WorkState workState) 17 | { 18 | _currentState = workState; 19 | } 20 | 21 | public void WriteProgram() 22 | { 23 | _currentState.WriteProgram(this); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /BehaviorPattern/StatePattern/WorkState.cs: -------------------------------------------------------------------------------- 1 | namespace StatePattern; 2 | 3 | internal abstract class WorkState 4 | { 5 | public abstract void WriteProgram(Work work); 6 | } 7 | 8 | internal class ForenoonState : WorkState 9 | { 10 | public override void WriteProgram(Work work) 11 | { 12 | if (work.Hour < 12) 13 | { 14 | Console.WriteLine($"当前时间:{work.Hour}点 上午工作,精神百倍"); 15 | } 16 | else 17 | { 18 | work.SetState(new NoonState()); 19 | work.WriteProgram(); 20 | } 21 | } 22 | } 23 | 24 | internal class NoonState : WorkState 25 | { 26 | public override void WriteProgram(Work work) 27 | { 28 | if (work.Hour < 13) 29 | { 30 | Console.WriteLine($"当前时间:{work.Hour}点 饿了,午饭。犯困,午休"); 31 | } 32 | else 33 | { 34 | work.SetState(new AfternoonState()); 35 | work.WriteProgram(); 36 | } 37 | } 38 | } 39 | 40 | internal class AfternoonState : WorkState 41 | { 42 | public override void WriteProgram(Work work) 43 | { 44 | if (work.Hour < 18) 45 | { 46 | Console.WriteLine($"当前时间:{work.Hour}点 下午状态还不错,继续努力"); 47 | } 48 | else 49 | { 50 | work.SetState(new EveningState()); 51 | work.WriteProgram(); 52 | } 53 | } 54 | } 55 | 56 | internal class EveningState : WorkState 57 | { 58 | public override void WriteProgram(Work work) 59 | { 60 | if (work.TaskFinished) 61 | { 62 | work.SetState(new RestState()); 63 | work.WriteProgram(); 64 | } 65 | else 66 | { 67 | if (work.Hour < 21) 68 | { 69 | Console.WriteLine($"当前时间:{work.Hour}点 还在加班啊,疲累之极"); 70 | } 71 | else 72 | { 73 | work.SetState(new SleepingState()); 74 | work.WriteProgram(); 75 | } 76 | } 77 | } 78 | } 79 | 80 | internal class RestState : WorkState 81 | { 82 | public override void WriteProgram(Work work) 83 | { 84 | Console.WriteLine($"当前时间:{work.Hour}点 下班回家了"); 85 | } 86 | } 87 | 88 | internal class SleepingState : WorkState 89 | { 90 | public override void WriteProgram(Work work) 91 | { 92 | Console.WriteLine($"当前时间:{work.Hour}点了,不行了,睡着了。"); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /BehaviorPattern/StrategyPattern/AbstractCash.cs: -------------------------------------------------------------------------------- 1 | namespace StrategyPattern; 2 | 3 | /// 4 | /// 结算方式 5 | /// 6 | internal abstract class AbstractCash 7 | { 8 | /// 9 | /// 实际收取金额 10 | /// 11 | /// 原价 12 | /// 按算法计算之后的实收金额 13 | public abstract double AcceptCash(double money); 14 | } 15 | 16 | internal class CashNormal : AbstractCash 17 | { 18 | public override double AcceptCash(double money) 19 | { 20 | //正常收费,原价 21 | return money; 22 | } 23 | } 24 | 25 | internal class CashRebate : AbstractCash 26 | { 27 | private readonly double _rebate; 28 | 29 | public CashRebate(double rebate) => _rebate = rebate; 30 | 31 | public override double AcceptCash(double money) 32 | { 33 | return money * _rebate; 34 | } 35 | } 36 | 37 | internal class CashReturn : AbstractCash 38 | { 39 | private readonly double _condition; 40 | private readonly double _return; 41 | 42 | public CashReturn(double condition, double mReturn) 43 | { 44 | _condition = condition; 45 | _return = mReturn; 46 | } 47 | 48 | public override double AcceptCash(double money) 49 | { 50 | return money >= _condition ? money - Math.Floor(money / _condition) * _return : money; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /BehaviorPattern/StrategyPattern/CashContext.cs: -------------------------------------------------------------------------------- 1 | namespace StrategyPattern; 2 | 3 | internal class CashContext 4 | { 5 | private readonly AbstractCash _cash; 6 | 7 | public string StrategyType { get; } 8 | 9 | public CashContext(string type) 10 | { 11 | StrategyType = type; 12 | _cash = type switch 13 | { 14 | "满300返100" => new CashReturn(300, 100), 15 | "8 折" => new CashRebate(0.8), 16 | _ => new CashNormal() 17 | }; 18 | } 19 | 20 | public double GetResult(double money) 21 | { 22 | return _cash.AcceptCash(money); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /BehaviorPattern/StrategyPattern/Program.cs: -------------------------------------------------------------------------------- 1 | #region Prototype 2 | 3 | var context = new Context(new ConcreteStrategyA()); 4 | context.Implement(); 5 | 6 | context = new Context(new ConcreteStrategyB()); 7 | context.Implement(); 8 | 9 | context = new Context(new ConcreteStrategyC()); 10 | context.Implement(); 11 | 12 | Console.WriteLine(); 13 | 14 | #endregion Prototype 15 | 16 | var strategyArray = new[] 17 | { 18 | "8 折", 19 | "正常", 20 | "原价", 21 | "满300返100" 22 | }; 23 | 24 | var random = new Random(); 25 | 26 | for (var i = 0; i < 10; i++) 27 | { 28 | var cashContext = new CashContext(strategyArray[random.Next(strategyArray.Length)]); 29 | 30 | var money = random.Next(500); 31 | Console.WriteLine($"结算方式:{cashContext.StrategyType} ,原价{money},实际收取:{cashContext.GetResult(money)}"); 32 | } 33 | 34 | Console.ReadLine(); 35 | -------------------------------------------------------------------------------- /BehaviorPattern/StrategyPattern/Prototype.cs: -------------------------------------------------------------------------------- 1 | namespace StrategyPattern; 2 | 3 | internal class Context 4 | { 5 | private readonly Strategy _strategy; 6 | 7 | public Context(Strategy strategy) => _strategy = strategy; 8 | 9 | public void Implement() 10 | { 11 | _strategy.AlgorithmImplement(); 12 | } 13 | } 14 | 15 | internal abstract class Strategy 16 | { 17 | public abstract void AlgorithmImplement(); 18 | } 19 | 20 | internal class ConcreteStrategyA : Strategy 21 | { 22 | public override void AlgorithmImplement() 23 | { 24 | Console.WriteLine("算法A实现"); 25 | } 26 | } 27 | 28 | internal class ConcreteStrategyB : Strategy 29 | { 30 | public override void AlgorithmImplement() 31 | { 32 | Console.WriteLine("算法B实现"); 33 | } 34 | } 35 | 36 | internal class ConcreteStrategyC : Strategy 37 | { 38 | public override void AlgorithmImplement() 39 | { 40 | Console.WriteLine("算法C实现"); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /BehaviorPattern/StrategyPattern/README.md: -------------------------------------------------------------------------------- 1 | # 策略模式 Strategy 2 | 3 | ## Intro 4 | 5 | > 策略模式(Strategy):它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化不会影响到使用算法的 `Context`。 6 | > 7 | > 策略模式是一种定义一系列算法的方法,从概念上来看,所有这些算法完全的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用类之间的耦合。 8 | 9 | ## 使用场景 10 | 11 | 策略模式就是用来封装算法的,但在实践中也可以用它来封装几乎任何类型的规则,只要在分析过程中听到需要在不同时间应用不同的业务规则,就可以考虑使用策略模式处理这种变化的可能性。 12 | 13 | ## 优点 14 | 15 | - 减少了具体的算法和使用算法类之间的耦合 16 | - 策略模式的 Strategy 类层为 `Context` 定义了一系列的可供重用的算法或行为,继承有助于析取这些算法中的公共功能 17 | - 简化了单元测试,因为每个算法都有自己的类,可以通过自己的接口单独测试 18 | 19 | ## Sample 20 | 21 | ``` csharp 22 | public class Context 23 | { 24 | private readonly Strategy _strategy; 25 | 26 | public Context(Strategy strategy) => _strategy = strategy; 27 | 28 | public void Implement() 29 | { 30 | _strategy.AlgorithmImplement(); 31 | } 32 | } 33 | 34 | public abstract class Strategy 35 | { 36 | public abstract void AlgorithmImplement(); 37 | } 38 | 39 | public class ConcreteStrategyA : Strategy 40 | { 41 | public override void AlgorithmImplement() 42 | { 43 | Console.WriteLine("算法A实现"); 44 | } 45 | } 46 | 47 | public class ConcreteStrategyB : Strategy 48 | { 49 | public override void AlgorithmImplement() 50 | { 51 | Console.WriteLine("算法B实现"); 52 | } 53 | } 54 | 55 | public class ConcreteStrategyC : Strategy 56 | { 57 | public override void AlgorithmImplement() 58 | { 59 | Console.WriteLine("算法C实现"); 60 | } 61 | } 62 | ``` 63 | 64 | ## More 65 | 66 | 更多设计模式及示例代码 [传送门](https://github.com/WeihanLi/DesignPatterns) 67 | -------------------------------------------------------------------------------- /BehaviorPattern/StrategyPattern/StrategyPattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /BehaviorPattern/TemplateMethodPattern/Program.cs: -------------------------------------------------------------------------------- 1 | #region Prototype 2 | 3 | AbstractClass c = new ConcreteClassA(); 4 | c.TemplateMethod(); 5 | c = new ConcreteClassB(); 6 | c.TemplateMethod(); 7 | 8 | Console.WriteLine(); 9 | 10 | #endregion Prototype 11 | 12 | var paper1 = new TestPaperA(); 13 | paper1.TestResult(); 14 | 15 | var pager2 = new TestPaperB(); 16 | pager2.TestResult(); 17 | 18 | Console.ReadLine(); 19 | -------------------------------------------------------------------------------- /BehaviorPattern/TemplateMethodPattern/Prototype.cs: -------------------------------------------------------------------------------- 1 | namespace TemplateMethodPattern; 2 | 3 | internal abstract class AbstractClass 4 | { 5 | protected abstract void PrimitiveOperation1(); 6 | 7 | protected abstract void PrimitiveOperation2(); 8 | 9 | public void TemplateMethod() 10 | { 11 | Console.WriteLine("-------Begin-------"); 12 | PrimitiveOperation1(); 13 | PrimitiveOperation2(); 14 | Console.WriteLine("-------End-------"); 15 | } 16 | } 17 | 18 | internal class ConcreteClassA : AbstractClass 19 | { 20 | protected override void PrimitiveOperation1() 21 | { 22 | Console.WriteLine("具体类A 方法1 的实现"); 23 | } 24 | 25 | protected override void PrimitiveOperation2() 26 | { 27 | Console.WriteLine("具体类A 方法2 的实现"); 28 | } 29 | } 30 | 31 | internal class ConcreteClassB : AbstractClass 32 | { 33 | protected override void PrimitiveOperation1() 34 | { 35 | Console.WriteLine("具体类B 方法1 的实现"); 36 | } 37 | 38 | protected override void PrimitiveOperation2() 39 | { 40 | Console.WriteLine("具体类B 方法2 的实现"); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /BehaviorPattern/TemplateMethodPattern/README.md: -------------------------------------------------------------------------------- 1 | # 模板方法模式 Template Method 2 | 3 | ## Intro 4 | 5 | > 模板方法模式,定义一个操作中的算法骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算的结构即使重定义该算法的某些特定步骤 6 | 7 | 8 | 这里的“算法”,我们可以理解为广义上的“业务逻辑”,并不特指数据结构和算法中的“算法”。这里的算法骨架就是“模板”,包含算法骨架的方法就是“模板方法”,这也是模板方法模式名字的由来。 9 | 10 | 我一直觉得模板方法这个设计模式是最简单最实用最能体验面向对象特性的一个设计模式 11 | 12 | 面向对象的三大特性,封装、继承、多态在模板方法模式中都有体现 13 | 14 | 一些通用的逻辑通常会 **封装** 在父类中,不同的部分通常在父类中定义一个抽象方法或者虚方法(具体根据实际场景选择),然后在子类中 **继承** 父类以复用父类中的通用逻辑,在具体的子类中实现需要重写的逻辑,以此来实现 **多态** 15 | 16 | ## 使用场景 17 | 18 | 模板方法模式是通过把不变行为搬移到基类中,去除子类中的重复代码来体现它的优势,提供了一个很好的代码复用平台。 19 | 20 | 当不变的和可变的行为在方法的子类实现中混合在一起的时候,不变的行为就会在子类中重复出现,我们通过可以借助模板方法模式把这些行为搬移到单一的地方,这样就帮助子类摆脱重复的不变行为的纠缠。 21 | 22 | ## Sample 23 | 24 | 来看一个简单的示例: 25 | 26 | ``` csharp 27 | internal abstract class AbstractClass 28 | { 29 | protected abstract void PrimitiveOperation1(); 30 | 31 | protected abstract void PrimitiveOperation2(); 32 | 33 | public void TemplateMethod() 34 | { 35 | Console.WriteLine("-------Begin-------"); 36 | PrimitiveOperation1(); 37 | PrimitiveOperation2(); 38 | Console.WriteLine("-------End-------"); 39 | } 40 | } 41 | 42 | internal class ConcreteClassA : AbstractClass 43 | { 44 | protected override void PrimitiveOperation1() 45 | { 46 | Console.WriteLine("具体类A 方法1 的实现"); 47 | } 48 | 49 | protected override void PrimitiveOperation2() 50 | { 51 | Console.WriteLine("具体类A 方法2 的实现"); 52 | } 53 | } 54 | 55 | internal class ConcreteClassB : AbstractClass 56 | { 57 | protected override void PrimitiveOperation1() 58 | { 59 | Console.WriteLine("具体类B 方法1 的实现"); 60 | } 61 | 62 | protected override void PrimitiveOperation2() 63 | { 64 | Console.WriteLine("具体类B 方法2 的实现"); 65 | } 66 | } 67 | ``` 68 | 69 | ## More 70 | 71 | 更多设计模式及示例代码 [传送门](https://github.com/WeihanLi/DesignPatterns) 72 | -------------------------------------------------------------------------------- /BehaviorPattern/TemplateMethodPattern/TemplateMethodPattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /BehaviorPattern/TemplateMethodPattern/TestPaper.cs: -------------------------------------------------------------------------------- 1 | namespace TemplateMethodPattern; 2 | 3 | /// 4 | /// 金庸小说考试试题 5 | /// 6 | internal class TestPaper 7 | { 8 | protected string StudentName { get; set; } 9 | 10 | public void TestResult() 11 | { 12 | Console.WriteLine($"学生 {StudentName} 的试卷:"); 13 | TestQuestion1(); 14 | TestQuestion2(); 15 | TestQuestion3(); 16 | Console.WriteLine(); 17 | } 18 | 19 | private void TestQuestion1() 20 | { 21 | Console.WriteLine("杨过得到后来给了郭靖,炼成倚天剑、屠龙刀的玄铁可能是 [ ]\r\na.球磨铸铁 b.马口铁 c.高速合金钢 d.碳素纤维 "); 22 | Console.WriteLine($"答案:{Answer1()}"); 23 | } 24 | 25 | private void TestQuestion2() 26 | { 27 | Console.WriteLine("杨过、程英、陆无双铲除了情花,造成 [ ]\r\na.使得这种植物不再害人 b.使一种珍稀物种灭绝了 c. 破坏了那个生物圈的生态平衡 d.造成该地区的沙漠化"); 28 | Console.WriteLine($"答案:{Answer2()}"); 29 | } 30 | 31 | private void TestQuestion3() 32 | { 33 | Console.WriteLine("蓝凤凰致使华山师徒、桃谷六仙呕吐不止,如果你是大夫,会给他们开什么药 [ ]\r\na.阿司匹林 b.牛黄解毒片 c.黄连 d.让他们喝生牛奶 e.以上都不对"); 34 | Console.WriteLine($"答案:{Answer3()}"); 35 | } 36 | 37 | protected virtual string Answer1() 38 | { 39 | return ""; 40 | } 41 | 42 | protected virtual string Answer2() 43 | { 44 | return ""; 45 | } 46 | 47 | protected virtual string Answer3() 48 | { 49 | return ""; 50 | } 51 | } 52 | 53 | internal class TestPaperA : TestPaper 54 | { 55 | public TestPaperA() 56 | { 57 | StudentName = "路人甲"; 58 | } 59 | 60 | protected override string Answer1() 61 | { 62 | return "b"; 63 | } 64 | 65 | protected override string Answer2() 66 | { 67 | return "c"; 68 | } 69 | 70 | protected override string Answer3() 71 | { 72 | return "a"; 73 | } 74 | } 75 | 76 | internal class TestPaperB : TestPaper 77 | { 78 | public TestPaperB() 79 | { 80 | StudentName = "吃泡面乙"; 81 | } 82 | 83 | protected override string Answer1() 84 | { 85 | return "c"; 86 | } 87 | 88 | protected override string Answer2() 89 | { 90 | return "b"; 91 | } 92 | 93 | protected override string Answer3() 94 | { 95 | return "a"; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /BehaviorPattern/VisitorPattern/Actions.cs: -------------------------------------------------------------------------------- 1 | namespace VisitorPattern; 2 | 3 | internal abstract class AbstractAction 4 | { 5 | public abstract void GetManConclusion(Man man); 6 | 7 | public abstract void GetWomanConclusion(Woman woman); 8 | } 9 | 10 | internal class Success : AbstractAction 11 | { 12 | public override void GetManConclusion(Man man) 13 | { 14 | Console.WriteLine($"{man.GetType().Name} {GetType().Name} 时,背后多半有一个伟大的女人"); 15 | } 16 | 17 | public override void GetWomanConclusion(Woman woman) 18 | { 19 | Console.WriteLine($"{woman.GetType().Name} {GetType().Name} 时,背后多有一个不成功的男人"); 20 | } 21 | } 22 | 23 | internal class Fail : AbstractAction 24 | { 25 | public override void GetManConclusion(Man man) 26 | { 27 | Console.WriteLine($"{man.GetType().Name} {GetType().Name} 时,背后多半有一个伟大的女人"); 28 | } 29 | 30 | public override void GetWomanConclusion(Woman woman) 31 | { 32 | Console.WriteLine($"{woman.GetType().Name} {GetType().Name} 时,背后多有一个不成功的男人"); 33 | } 34 | } 35 | 36 | internal class Marriage : AbstractAction 37 | { 38 | public override void GetManConclusion(Man man) 39 | { 40 | Console.WriteLine($"{man.GetType().Name} {GetType().Name} 时,感慨道:恋爱游戏终结时,'有妻徒刑'遥无期"); 41 | } 42 | 43 | public override void GetWomanConclusion(Woman woman) 44 | { 45 | Console.WriteLine($"{woman.GetType().Name} {GetType().Name} 时,欣慰曰:爱情长路跑漫漫,婚姻保险保平安."); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /BehaviorPattern/VisitorPattern/Person.cs: -------------------------------------------------------------------------------- 1 | namespace VisitorPattern; 2 | 3 | internal abstract class Person 4 | { 5 | public abstract void Accept(AbstractAction visitor); 6 | } 7 | 8 | internal class Man : Person 9 | { 10 | public override void Accept(AbstractAction visitor) 11 | { 12 | visitor.GetManConclusion(this); 13 | } 14 | } 15 | 16 | internal class Woman : Person 17 | { 18 | public override void Accept(AbstractAction visitor) 19 | { 20 | visitor.GetWomanConclusion(this); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /BehaviorPattern/VisitorPattern/PersonStructure.cs: -------------------------------------------------------------------------------- 1 | namespace VisitorPattern; 2 | 3 | internal class PersonStructure 4 | { 5 | private readonly IList _persons = new List(); 6 | 7 | public void Attach(Person person) 8 | { 9 | _persons.Add(person); 10 | } 11 | 12 | public void Detach(Person person) 13 | { 14 | _persons.Remove(person); 15 | } 16 | 17 | public void Display(AbstractAction visitor) 18 | { 19 | foreach (var person in _persons) 20 | { 21 | person.Accept(visitor); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /BehaviorPattern/VisitorPattern/Program.cs: -------------------------------------------------------------------------------- 1 | #region Prototype 2 | 3 | var o = new ObjectStructure(); 4 | o.Attach(new ConcreteElementA()); 5 | o.Attach(new ConcreteElementB()); 6 | o.Accept(new ConcreteVisitor1()); 7 | o.Accept(new ConcreteVisitor2()); 8 | 9 | Console.WriteLine(); 10 | 11 | #endregion Prototype 12 | 13 | var personStructure = new PersonStructure(); 14 | personStructure.Attach(new Man()); 15 | personStructure.Attach(new Woman()); 16 | 17 | personStructure.Display(new Success()); 18 | personStructure.Display(new Fail()); 19 | personStructure.Display(new Marriage()); 20 | 21 | Console.ReadLine(); 22 | -------------------------------------------------------------------------------- /BehaviorPattern/VisitorPattern/Prototype.cs: -------------------------------------------------------------------------------- 1 | namespace VisitorPattern; 2 | 3 | #region Element 4 | 5 | internal abstract class Element 6 | { 7 | public abstract void Accept(Visitor visitor); 8 | } 9 | 10 | internal class ConcreteElementA : Element 11 | { 12 | public override void Accept(Visitor visitor) 13 | { 14 | visitor.VisitConcreteElementA(this); 15 | } 16 | 17 | public void OperationA() 18 | { 19 | } 20 | } 21 | 22 | internal class ConcreteElementB : Element 23 | { 24 | public override void Accept(Visitor visitor) 25 | { 26 | visitor.VisitConcreteElementB(this); 27 | } 28 | 29 | public void OperationB() 30 | { 31 | } 32 | } 33 | 34 | #endregion Element 35 | 36 | #region Visitor 37 | 38 | internal abstract class Visitor 39 | { 40 | public abstract void VisitConcreteElementA(ConcreteElementA element); 41 | 42 | public abstract void VisitConcreteElementB(ConcreteElementB element); 43 | } 44 | 45 | internal class ConcreteVisitor1 : Visitor 46 | { 47 | public override void VisitConcreteElementA(ConcreteElementA element) 48 | { 49 | Console.WriteLine($"{element.GetType().Name} 被 {GetType().Name} 访问"); 50 | } 51 | 52 | public override void VisitConcreteElementB(ConcreteElementB element) 53 | { 54 | Console.WriteLine($"{element.GetType().Name} 被 {GetType().Name} 访问"); 55 | } 56 | } 57 | 58 | internal class ConcreteVisitor2 : Visitor 59 | { 60 | public override void VisitConcreteElementA(ConcreteElementA element) 61 | { 62 | Console.WriteLine($"{element.GetType().Name} 被 {GetType().Name} 访问"); 63 | } 64 | 65 | public override void VisitConcreteElementB(ConcreteElementB element) 66 | { 67 | Console.WriteLine($"{element.GetType().Name} 被 {GetType().Name} 访问"); 68 | } 69 | } 70 | 71 | #endregion Visitor 72 | 73 | internal class ObjectStructure 74 | { 75 | private readonly IList _elements = new List(); 76 | 77 | public void Attach(Element element) 78 | { 79 | _elements.Add(element); 80 | } 81 | 82 | public void Detach(Element element) 83 | { 84 | _elements.Remove(element); 85 | } 86 | 87 | public void Accept(Visitor visitor) 88 | { 89 | foreach (var element in _elements) 90 | { 91 | element.Accept(visitor); 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /BehaviorPattern/VisitorPattern/README.md: -------------------------------------------------------------------------------- 1 | # 访问者模式 Visitor 2 | 3 | ## Intro 4 | 5 | > 访问者模式(Visitor),表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。 6 | 7 | ## 使用场景 8 | 9 | 访问者模式适用于数据结构相对稳定的系统,它把数据结构和作用域结构上的操作之间的耦合解脱开,使用操作集合可以相对自由地演化。 10 | 11 | 访问者模式的目的是要把处理从数据结构分离出来,有比较稳定的数据结构,又有易于变化的算法时,使用访问者模式就是比较适合的, 12 | 因为访问者模式使得算法操作的增加变得容易。反之,如果数据结构对象易于变化,经常有新的数据对象增加进来,就不适合使用访问者模式。 13 | 14 | ## 优缺点 15 | 16 | 优点: 17 | 18 | - 增加新的操作很容易,增加新的操作就意味着增加一个新的访问者,访问者模式将有关的行为集中到一个访问者对象中。 19 | 20 | 缺点: 21 | 22 | - 增加新的数据结构困难,破坏 开放封闭 原则 23 | 24 | 25 | ## Sample 26 | 27 | ``` csharp 28 | public abstract class Person 29 | { 30 | public abstract void Accept(AbstractAction visitor); 31 | } 32 | 33 | public class Man : Person 34 | { 35 | public override void Accept(AbstractAction visitor) 36 | { 37 | visitor.GetManConclusion(this); 38 | } 39 | } 40 | 41 | public class Woman : Person 42 | { 43 | public override void Accept(AbstractAction visitor) 44 | { 45 | visitor.GetWomanConclusion(this); 46 | } 47 | } 48 | 49 | public abstract class AbstractAction 50 | { 51 | public abstract void GetManConclusion(Man man); 52 | 53 | public abstract void GetWomanConclusion(Woman woman); 54 | } 55 | 56 | public class Success : AbstractAction 57 | { 58 | public override void GetManConclusion(Man man) 59 | { 60 | Console.WriteLine($"{man.GetType().Name} {GetType().Name} 时,背后多半有一个伟大的女人"); 61 | } 62 | 63 | public override void GetWomanConclusion(Woman woman) 64 | { 65 | Console.WriteLine($"{woman.GetType().Name} {GetType().Name} 时,背后多有一个不成功的男人"); 66 | } 67 | } 68 | public class Fail : AbstractAction 69 | { 70 | public override void GetManConclusion(Man man) 71 | { 72 | Console.WriteLine($"{man.GetType().Name} {GetType().Name} 时,背后多半有一个伟大的女人"); 73 | } 74 | 75 | public override void GetWomanConclusion(Woman woman) 76 | { 77 | Console.WriteLine($"{woman.GetType().Name} {GetType().Name} 时,背后多有一个不成功的男人"); 78 | } 79 | } 80 | public class Marriage : AbstractAction 81 | { 82 | public override void GetManConclusion(Man man) 83 | { 84 | Console.WriteLine($"{man.GetType().Name} {GetType().Name} 时,感慨道:恋爱游戏终结时,'有妻徒刑'遥无期"); 85 | } 86 | 87 | public override void GetWomanConclusion(Woman woman) 88 | { 89 | Console.WriteLine($"{woman.GetType().Name} {GetType().Name} 时,欣慰曰:爱情长路跑漫漫,婚姻保险保平安."); 90 | } 91 | } 92 | 93 | public class PersonStructure 94 | { 95 | private readonly IList _persons = new List(); 96 | 97 | public void Attach(Person person) 98 | { 99 | _persons.Add(person); 100 | } 101 | 102 | public void Detach(Person person) 103 | { 104 | _persons.Remove(person); 105 | } 106 | 107 | public void Display(AbstractAction visitor) 108 | { 109 | foreach (var person in _persons) 110 | { 111 | person.Accept(visitor); 112 | } 113 | } 114 | } 115 | 116 | 117 | var personStructure = new PersonStructure(); 118 | personStructure.Attach(new Man()); 119 | personStructure.Attach(new Woman()); 120 | 121 | personStructure.Display(new Success()); 122 | personStructure.Display(new Fail()); 123 | personStructure.Display(new Marriage()); 124 | ``` 125 | 126 | ## More 127 | 128 | 更多设计模式及示例代码 [传送门](https://github.com/WeihanLi/DesignPatterns) 129 | -------------------------------------------------------------------------------- /BehaviorPattern/VisitorPattern/VisitorPattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /CreatePattern/AbstractFactoryPattern/AbstractFactoryPattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /CreatePattern/AbstractFactoryPattern/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /CreatePattern/AbstractFactoryPattern/DataAccess.cs: -------------------------------------------------------------------------------- 1 | namespace AbstractFactoryPattern; 2 | 3 | public class DataAccess 4 | { 5 | private static readonly string AssemblyName = "AbstractFactoryPattern"; 6 | private static readonly string DbName = System.Configuration.ConfigurationManager.AppSettings["DbName"]; 7 | 8 | public static IUserRepo CreateUserRepo() 9 | { 10 | return (IUserRepo)typeof(DataAccess).Assembly.CreateInstance($"{AssemblyName}.{DbName}UserRepo"); 11 | } 12 | 13 | public static IDepartmentRepo CreateDepartmentRepo() 14 | { 15 | return (IDepartmentRepo)typeof(DataAccess).Assembly.CreateInstance($"{AssemblyName}.{DbName}DepartmentRepo"); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /CreatePattern/AbstractFactoryPattern/DbFactory.cs: -------------------------------------------------------------------------------- 1 | namespace AbstractFactoryPattern; 2 | 3 | public interface IDbFactory 4 | { 5 | IUserRepo CreateUserRepo(); 6 | 7 | IDepartmentRepo CreateDepartmentRepo(); 8 | } 9 | 10 | internal class SqlServerFactory : IDbFactory 11 | { 12 | public IUserRepo CreateUserRepo() 13 | { 14 | return new SqlServerUserRepo(); 15 | } 16 | 17 | public IDepartmentRepo CreateDepartmentRepo() 18 | { 19 | return new SqlServerDepartmentRepo(); 20 | } 21 | } 22 | 23 | internal class AccessFactory : IDbFactory 24 | { 25 | public IUserRepo CreateUserRepo() 26 | { 27 | return new AccessUserRepo(); 28 | } 29 | 30 | public IDepartmentRepo CreateDepartmentRepo() 31 | { 32 | return new AccessDepartmentRepo(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /CreatePattern/AbstractFactoryPattern/Department.cs: -------------------------------------------------------------------------------- 1 | namespace AbstractFactoryPattern; 2 | 3 | public class Department 4 | { 5 | } 6 | -------------------------------------------------------------------------------- /CreatePattern/AbstractFactoryPattern/DepartmentRepo.cs: -------------------------------------------------------------------------------- 1 | namespace AbstractFactoryPattern; 2 | 3 | public interface IDepartmentRepo 4 | { 5 | void CreateDepartment(Department department); 6 | } 7 | 8 | internal class SqlServerDepartmentRepo : IDepartmentRepo 9 | { 10 | public void CreateDepartment(Department department) 11 | { 12 | Console.WriteLine("Create department in SqlServer"); 13 | } 14 | } 15 | 16 | internal class AccessDepartmentRepo : IDepartmentRepo 17 | { 18 | public void CreateDepartment(Department department) 19 | { 20 | Console.WriteLine("Create department in Access"); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /CreatePattern/AbstractFactoryPattern/Program.cs: -------------------------------------------------------------------------------- 1 | #region AbstractFactory 2 | 3 | IDbFactory factory = new AccessFactory(); 4 | var userRepo = factory.CreateUserRepo(); 5 | userRepo.Insert(null); 6 | 7 | factory = new SqlServerFactory(); 8 | userRepo = factory.CreateUserRepo(); 9 | userRepo.Insert(null); 10 | 11 | #endregion AbstractFactory 12 | 13 | #region AbstractFactory + Reflection 14 | 15 | var departmentRepo = DataAccess.CreateDepartmentRepo(); 16 | departmentRepo.CreateDepartment(null); 17 | 18 | #endregion AbstractFactory + Reflection 19 | 20 | #region AbstractFactory + DependencyInjection 21 | 22 | using var services = new ServiceCollection() 23 | .AddSingleton() 24 | .BuildServiceProvider(); 25 | 26 | var dbFactory = services.GetRequiredService(); 27 | dbFactory.CreateDepartmentRepo().CreateDepartment(null); 28 | 29 | #endregion AbstractFactory + DependencyInjection 30 | 31 | Console.ReadLine(); -------------------------------------------------------------------------------- /CreatePattern/AbstractFactoryPattern/README.md: -------------------------------------------------------------------------------- 1 | # 抽象工厂模式 AbstractFactory 2 | 3 | ## Intro 简介 4 | 5 | > 抽象工厂模式,提供一系列相关或相互依赖对象的接口,而无需指定他们具体的类。 6 | 7 | 实现抽象工作模式所需要的组件,主要部分: 8 | 9 | - 抽象工厂/抽象产品 10 | - 具体工厂1/具体产品1 11 | - 具体工厂2/具体产品2 12 | - ... 13 | 14 | 在客户端根据不同的配置选择不同的工厂,例如根据配置的数据库类型的不同选择使用 Access 数据库仓储的工厂还是使用 SqlServer 数据库的仓储工厂 15 | 16 | ``` csharp 17 | IDbFactory factory = new AccessFactory(); 18 | var userRepo = factory.CreateUserRepo(); 19 | userRepo.Insert(null); 20 | var departmentRepo = factory.CreateDepartmentRepo(); 21 | 22 | factory = new SqlServerFactory(); 23 | userRepo = factory.CreateUserRepo(); 24 | userRepo.Insert(null); 25 | ``` 26 | 27 | ## 工厂方法和抽象工厂的区别 28 | 29 | 工厂方法模式:定义一个用于创建对象的接口,让子类决定实例化哪一个类 30 | 抽象工厂模式:为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类 31 | 区别在于产品,如果产品单一,最合适用工厂模式,但是如果有多个业务品种、业务分类时,通过抽象工厂模式产生需要的对象是一种非常好的解决方式。再通俗深化理解下:工厂模式针对的是一个产品等级结构 ,抽象工厂模式针对的是面向多个产品等级结构的。 32 | 33 | 抽象工厂关键在于产品之间的抽象关系,所以一般至少要两个产品;工厂方法在于生成产品,不关注产品间的关系,所以可以只生成一个产品。 34 | 35 | 抽象工厂更像一个复杂版本的策略模式,策略模式通过更换策略来改变处理方式或者结果;而抽象工厂的客户端,通过更换工厂而改变结果。 36 | 37 | 工厂方法目的是生产产品,所以能看到产品,而且还要使用产品。当然,如果产品在创建者内部使用,那么工厂方法就是为了完善创建者,从而可以使用创建者。另外创建者本身是不能更换所生产产品的。 38 | 39 | 抽象工厂的工厂是类;工厂方法的工厂是方法。抽象工厂的工厂类就做一件事情生产产品。生产的产品给客户端使用,绝不给自己用。工厂方法生产产品,可以给系统用,可以给客户端用,也可以自己这个类使用。自己这个类除了这个工厂方法外,还可以有其他功能性的方法。 40 | 41 | ## More 42 | 43 | 更多设计模式及示例代码 [传送门](https://github.com/WeihanLi/DesignPatterns) 44 | -------------------------------------------------------------------------------- /CreatePattern/AbstractFactoryPattern/User.cs: -------------------------------------------------------------------------------- 1 | namespace AbstractFactoryPattern; 2 | 3 | public class User 4 | { 5 | } 6 | -------------------------------------------------------------------------------- /CreatePattern/AbstractFactoryPattern/UserRepo.cs: -------------------------------------------------------------------------------- 1 | namespace AbstractFactoryPattern; 2 | 3 | public interface IUserRepo 4 | { 5 | void Insert(User user); 6 | 7 | User GetUser(int userId); 8 | } 9 | 10 | internal class SqlServerUserRepo : IUserRepo 11 | { 12 | public void Insert(User user) 13 | { 14 | Console.WriteLine("insert user in SqlServer"); 15 | } 16 | 17 | public User GetUser(int userId) 18 | { 19 | Console.WriteLine("Get user from SqlServer by userId"); 20 | return null; 21 | } 22 | } 23 | 24 | internal class AccessUserRepo : IUserRepo 25 | { 26 | public void Insert(User user) 27 | { 28 | Console.WriteLine("insert user in Access"); 29 | } 30 | 31 | public User GetUser(int userId) 32 | { 33 | Console.WriteLine("Get user from Access by userId"); 34 | return null; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /CreatePattern/BuilderPattern/Builder.cs: -------------------------------------------------------------------------------- 1 | namespace BuilderPattern; 2 | 3 | internal abstract class Builder 4 | { 5 | public abstract void BuildPartA(); 6 | 7 | public abstract void BuildPartB(); 8 | 9 | public abstract Product GetResult(); 10 | } 11 | -------------------------------------------------------------------------------- /CreatePattern/BuilderPattern/BuilderPattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /CreatePattern/BuilderPattern/ConcreteBuilder1.cs: -------------------------------------------------------------------------------- 1 | namespace BuilderPattern; 2 | 3 | internal class ConcreteBuilder1 : Builder 4 | { 5 | private readonly Product _product = new(); 6 | 7 | public override void BuildPartA() => _product.Add("PartA"); 8 | 9 | public override void BuildPartB() => _product.Add("PartB"); 10 | 11 | public override Product GetResult() => _product; 12 | } 13 | -------------------------------------------------------------------------------- /CreatePattern/BuilderPattern/ConcreteBuilder2.cs: -------------------------------------------------------------------------------- 1 | namespace BuilderPattern; 2 | 3 | internal class ConcreteBuilder2 : Builder 4 | { 5 | private readonly Product _product = new(); 6 | 7 | public override void BuildPartA() => _product.Add("PartX"); 8 | 9 | public override void BuildPartB() => _product.Add("PartY"); 10 | 11 | public override Product GetResult() => _product; 12 | } 13 | -------------------------------------------------------------------------------- /CreatePattern/BuilderPattern/Director.cs: -------------------------------------------------------------------------------- 1 | namespace BuilderPattern; 2 | 3 | internal class Director 4 | { 5 | public void Construct(Builder builder) 6 | { 7 | builder.BuildPartA(); 8 | builder.BuildPartB(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /CreatePattern/BuilderPattern/Product.cs: -------------------------------------------------------------------------------- 1 | namespace BuilderPattern; 2 | 3 | internal class Product 4 | { 5 | private readonly ICollection _parts = new List(); 6 | 7 | public void Add(string part) => _parts.Add(part); 8 | 9 | public void Show() 10 | { 11 | Console.WriteLine("\n产品 创建----"); 12 | foreach (var part in _parts) 13 | { 14 | Console.WriteLine(part); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /CreatePattern/BuilderPattern/Program.cs: -------------------------------------------------------------------------------- 1 | var director = new Director(); 2 | Builder builder1 = new ConcreteBuilder1(), builder2 = new ConcreteBuilder2(); 3 | director.Construct(builder1); 4 | director.Construct(builder2); 5 | 6 | builder1.GetResult().Show(); 7 | builder2.GetResult().Show(); 8 | 9 | Console.ReadLine(); 10 | -------------------------------------------------------------------------------- /CreatePattern/BuilderPattern/README.md: -------------------------------------------------------------------------------- 1 | # 建造者模式 Builder 2 | 3 | ## Intro 简介 4 | 5 | > 建造者模式: 建造者模式隐藏了复杂对象的创建过程,它把复杂对象的创建过程加以抽象,通过子类继承或者重载的方式,动态的创建具有复合属性的对象。 6 | 7 | 需要的组件: 8 | 9 | - Product 10 | - AbstractBuilder 创建一个 Product 的抽象 builder 11 | - ConcreteBuilder1/ConcreteBuilder2 创建 Product 具体的 builder 12 | - Director 指挥 builder 如何创建一个复杂的 Product 13 | 14 | ## Sample 15 | 16 | ``` csharp 17 | var director = new Director(); 18 | Builder builder1 = new ConcreteBuilder1(), builder2 = new ConcreteBuilder2(); 19 | 20 | director.Construct(builder1); 21 | director.Construct(builder2); 22 | 23 | var product2 = builder1.GetResult(); 24 | var product2 = builder2.GetResult(); 25 | ``` 26 | 27 | .net core 中的各种 builder (`HostBuilder`/`ConfigurationBuilder`/...) 我觉得也是属于建造者模式的,只是 Builder 本身就是 Director, 28 | 通过 builder 来实现对象的各种参数配置构建最后的 Product (`Host`/`Configuration`/...) 29 | 30 | ## More 31 | 32 | 更多设计模式及示例代码 [传送门](https://github.com/WeihanLi/DesignPatterns) 33 | -------------------------------------------------------------------------------- /CreatePattern/FactoryMethodPattern/FactoryMethodPattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /CreatePattern/FactoryMethodPattern/Leifeng.cs: -------------------------------------------------------------------------------- 1 | namespace FactoryMethodPattern; 2 | 3 | internal class Leifeng 4 | { 5 | public void Sweep() 6 | { 7 | Console.WriteLine("扫地"); 8 | } 9 | 10 | public void Wash() 11 | { 12 | Console.WriteLine("洗衣"); 13 | } 14 | 15 | public void BuyRice() 16 | { 17 | Console.WriteLine("买米"); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /CreatePattern/FactoryMethodPattern/LeifengFactory.cs: -------------------------------------------------------------------------------- 1 | namespace FactoryMethodPattern; 2 | 3 | internal interface ILeifengFactory 4 | { 5 | Leifeng CreateLeifeng(); 6 | } 7 | 8 | internal class UndergraduteFactory : ILeifengFactory 9 | { 10 | public Leifeng CreateLeifeng() 11 | { 12 | return new Undergradute(); 13 | } 14 | } 15 | 16 | internal class VolunteerFactory : ILeifengFactory 17 | { 18 | public Leifeng CreateLeifeng() 19 | { 20 | return new Volunteer(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /CreatePattern/FactoryMethodPattern/Program.cs: -------------------------------------------------------------------------------- 1 | // 这里显示 new 对象的地方同样可以通过 配置+反射 和 依赖注入 的方式去做,可参考 抽象工厂模式 2 | ILeifengFactory factory = new UndergraduteFactory(); 3 | var studentLeifeng = factory.CreateLeifeng(); 4 | studentLeifeng.BuyRice(); 5 | var studentLeifeng1 = factory.CreateLeifeng(); 6 | studentLeifeng1.Sweep(); 7 | 8 | // 依赖注入 9 | using var services = new ServiceCollection() 10 | .AddSingleton() 11 | .BuildServiceProvider(); 12 | 13 | var leifengFactory = services.GetRequiredService(); 14 | var volunteer = leifengFactory.CreateLeifeng(); 15 | volunteer.Wash(); 16 | 17 | Console.ReadLine(); -------------------------------------------------------------------------------- /CreatePattern/FactoryMethodPattern/README.md: -------------------------------------------------------------------------------- 1 | # 工厂方法 FactoryMethod 2 | 3 | ## Intro 简介 4 | 5 | > 工厂方法模式(Factory Method)定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到子类。 6 | 7 | ## 特点 8 | 9 | 工厂方法模式实现时,客户端需要决定实例化哪一个工厂来实现客户端的操作,也会存在着选择判断的问题,不过和简单工厂相比,简单工厂的选择判断是在工厂内部,而工厂方法则将选择判断转移到了客户端。 10 | 11 | ## Sample 12 | 13 | ``` csharp 14 | ILeifengFactory factory = new UndergraduteFactory(); 15 | var studentLeifeng = factory.CreateLeifeng(); 16 | studentLeifeng.BuyRice(); 17 | 18 | factory = new VolunteerFactory(); 19 | var leifeng1 = factory.CreateLeifeng(); 20 | leifeng1.Sweep(); 21 | ``` 22 | 23 | ## More 24 | 25 | 更多设计模式及示例代码 [传送门](https://github.com/WeihanLi/DesignPatterns) 26 | -------------------------------------------------------------------------------- /CreatePattern/FactoryMethodPattern/Undergradute.cs: -------------------------------------------------------------------------------- 1 | namespace FactoryMethodPattern; 2 | 3 | internal class Undergradute : Leifeng 4 | { 5 | } 6 | -------------------------------------------------------------------------------- /CreatePattern/FactoryMethodPattern/Volunteer.cs: -------------------------------------------------------------------------------- 1 | namespace FactoryMethodPattern; 2 | 3 | internal class Volunteer : Leifeng 4 | { 5 | } 6 | -------------------------------------------------------------------------------- /CreatePattern/PrototypePattern/ComplexResume.cs: -------------------------------------------------------------------------------- 1 | namespace PrototypePattern; 2 | 3 | internal class WorkExperience : ICloneable 4 | { 5 | public string TimePeriod { get; set; } 6 | public string Company { get; set; } 7 | 8 | public object Clone() => MemberwiseClone(); 9 | } 10 | 11 | /// 12 | /// Deep Copy 13 | /// 14 | internal class ComplexResume : ICloneable 15 | { 16 | private readonly WorkExperience _workExperience; 17 | private string _name; 18 | private string _email; 19 | 20 | public ComplexResume() => _workExperience = new WorkExperience(); 21 | 22 | private ComplexResume(WorkExperience workExperience) => _workExperience = (WorkExperience)workExperience.Clone(); 23 | 24 | public void SetPersonalInfo(string name, string email) 25 | { 26 | _name = name; 27 | _email = email; 28 | } 29 | 30 | public void SetWorkExperience(string comapny, string timePeriod) 31 | { 32 | _workExperience.Company = comapny; 33 | _workExperience.TimePeriod = timePeriod; 34 | } 35 | 36 | public void Show() 37 | { 38 | Console.WriteLine($"{_name} {_email}"); 39 | Console.WriteLine($"Work Experience: {_workExperience.Company} {_workExperience.TimePeriod}"); 40 | } 41 | 42 | public object Clone() => new ComplexResume(_workExperience) 43 | { 44 | _name = _name, 45 | _email = _email 46 | }; 47 | } 48 | -------------------------------------------------------------------------------- /CreatePattern/PrototypePattern/Program.cs: -------------------------------------------------------------------------------- 1 | #region shallow copy 2 | 3 | var resume = new SimpleResume(); 4 | resume.SetPersonalInfo("小明", "xiaoming@abc.xyz"); 5 | resume.SetWorkExperience("xxx公司", "1990~2000"); 6 | resume.Display(); 7 | var resume1 = (SimpleResume)resume.Clone(); 8 | resume1.SetWorkExperience("xxx企业", "1998~1999"); 9 | resume1.Display(); 10 | var resume2 = (SimpleResume)resume.Clone(); 11 | resume2.SetPersonalInfo("xiaohong", "xiaohong@abc.xyz"); 12 | resume2.Display(); 13 | 14 | #endregion shallow copy 15 | 16 | #region deep copy 17 | 18 | var complexResume = new ComplexResume(); 19 | complexResume.SetPersonalInfo("xiaoming", "xiaoming@abc.xyz"); 20 | complexResume.SetWorkExperience("xiaomingTecch", "2001~2005"); 21 | complexResume.Show(); 22 | 23 | var complexResume1 = (ComplexResume)complexResume.Clone(); 24 | complexResume1.SetPersonalInfo("xiaohong", "xiaohong@abc.xyz"); 25 | complexResume1.Show(); 26 | 27 | #endregion deep copy 28 | 29 | Console.ReadLine(); 30 | -------------------------------------------------------------------------------- /CreatePattern/PrototypePattern/Prototype.cs: -------------------------------------------------------------------------------- 1 | namespace PrototypePattern; 2 | 3 | internal abstract class Prototype 4 | { 5 | public string Id { get; } 6 | 7 | protected Prototype(string id) => Id = id; 8 | 9 | public abstract Prototype Clone(); 10 | } 11 | 12 | internal class ConcretePrototype1 : Prototype 13 | { 14 | public ConcretePrototype1(string id) : base(id) 15 | { 16 | } 17 | 18 | public override Prototype Clone() 19 | { 20 | return (Prototype)MemberwiseClone(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /CreatePattern/PrototypePattern/PrototypePattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /CreatePattern/PrototypePattern/README.md: -------------------------------------------------------------------------------- 1 | # 原型模式 Prototype 2 | 3 | ## Intro 简介 4 | 5 | > 原型模式,用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象 6 | 7 | 原型模式其实就是从一个对象再创建另外一个可定制的对象而且不需要知道任何创建的细节。 8 | 9 | ## 实现方式 10 | 11 | 实现方式大致如下: 12 | 13 | 在 c# 中可以实现 `ICloneable` 接口和 `MemberwiseClone` 方法来方便的实现原型模式 14 | 15 | ``` csharp 16 | // 浅复制 17 | public object Clone() => MemberwiseClone(); 18 | ``` 19 | 20 | ## More 21 | 22 | 更多设计模式及示例代码 [传送门](https://github.com/WeihanLi/DesignPatterns) 23 | -------------------------------------------------------------------------------- /CreatePattern/PrototypePattern/SimpleResume.cs: -------------------------------------------------------------------------------- 1 | namespace PrototypePattern; 2 | 3 | /// 4 | /// ShallowCopy 5 | /// 6 | internal class SimpleResume : ICloneable 7 | { 8 | private string _name; 9 | private string _email; 10 | 11 | private string _timePeriod; 12 | private string _company; 13 | 14 | public void SetPersonalInfo(string name, string email) 15 | { 16 | _name = name; 17 | _email = email; 18 | } 19 | 20 | public void SetWorkExperience(string company, string timePeriod) 21 | { 22 | _company = company; 23 | _timePeriod = timePeriod; 24 | } 25 | 26 | public void Display() 27 | { 28 | Console.WriteLine($"{_name} {_email}"); 29 | Console.WriteLine($"工作经历:{_timePeriod} {_company}"); 30 | } 31 | 32 | public object Clone() => MemberwiseClone(); 33 | } 34 | -------------------------------------------------------------------------------- /CreatePattern/README.md: -------------------------------------------------------------------------------- 1 | # 创建型设计模式总结 2 | 3 | ## Intro 4 | 5 | 前面几篇文章已经把创建型设计模式都介绍了,来做一个简单的总结。 6 | 7 | 创建型设计模式,就是用来创建对象的设计模式,根据要创建的对象的复杂度以及是否允许多实例以及是否需要容易扩展等多方面考虑去选择合适的设计模式来创建对象。 8 | 9 | ## Summary 10 | 11 | ### 单例模式(Singleton) 12 | 13 | 需要保证保证一个类仅有一个实例的时候需要考虑使用单例模式,搭配依赖注入框架使用会更香哈 14 | 15 | ### 原型模式(Prototype) 16 | 17 | 对象频繁复制,对象的大多数元素(属性/字段)相同,需要频繁创建对象考虑使用原型模式,让对象创建更容易,需要注意深复制浅复制区别 18 | 19 | ### 建造者模式(Builder) 20 | 21 | 对象比较复杂,需要大量的配置参数,创建过程复杂,考虑使用建造者模式,让复杂的创建过程简单化 22 | 23 | ### 抽象工厂(AbstractFactory) 24 | 25 | 抽象工厂,提供一系列相关或相互依赖对象的接口,而无需指定他们具体的类,由具体的工厂创建具体类型的实例 26 | 27 | ### 工厂方法(FactoryMethod) 28 | 29 | 工厂方法模式定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到子类。 30 | 31 | 类的创建由具体的工厂相应的方法创建具体的实例 32 | 33 | ## More 34 | 35 | 抽象工厂的工厂是类;工厂方法的工厂是方法。 36 | 37 | 抽象工厂关键在于产品之间的抽象关系,所以一般至少要两个产品;工厂方法在于生成产品,不关注产品间的关系,所以可以只生成一个产品。 38 | 39 | ## Reference 40 | 41 | - [简单工厂(SimpleFactory)](./SimpleFactoryPattern) 42 | - [抽象工厂(AbstractFactory)](./AbstractFactoryPattern) 43 | - [工厂方法(FactoryMethod)](./FactoryMethodPattern) 44 | - [建造者模式(Builder)](./BuilderPattern) 45 | - [原型模式(Prototype)](./PrototypePattern) 46 | - [单例模式(Singleton)](./SingletonPattern) 47 | -------------------------------------------------------------------------------- /CreatePattern/SimpleFactoryPattern/Operation.cs: -------------------------------------------------------------------------------- 1 | namespace SimpleFactoryPattern; 2 | 3 | public class Operation 4 | { 5 | public double NumberA { get; set; } 6 | public double NumberB { get; set; } 7 | 8 | public virtual double GetResult() 9 | { 10 | return 0; 11 | } 12 | } 13 | 14 | public class OperationAdd : Operation 15 | { 16 | public override double GetResult() 17 | { 18 | return NumberA + NumberB; 19 | } 20 | } 21 | 22 | public class OpertaionSub : Operation 23 | { 24 | public override double GetResult() 25 | { 26 | return NumberA - NumberB; 27 | } 28 | } 29 | 30 | public class OperationMul : Operation 31 | { 32 | public override double GetResult() 33 | { 34 | return NumberA * NumberB; 35 | } 36 | } 37 | 38 | public class OperationDiv : Operation 39 | { 40 | public override double GetResult() 41 | { 42 | if (NumberB == 0) 43 | { 44 | throw new Exception("除数不能为0"); 45 | } 46 | return NumberA / NumberB; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /CreatePattern/SimpleFactoryPattern/OperationFactory.cs: -------------------------------------------------------------------------------- 1 | namespace SimpleFactoryPattern; 2 | 3 | public class OperationFactory 4 | { 5 | public static Operation CreateOperation(string operate) 6 | { 7 | Operation operation = null; 8 | switch (operate) 9 | { 10 | case "+": 11 | operation = new OperationAdd(); 12 | break; 13 | 14 | case "-": 15 | operation = new OpertaionSub(); 16 | break; 17 | 18 | case "*": 19 | operation = new OperationMul(); 20 | break; 21 | 22 | case "/": 23 | operation = new OperationDiv(); 24 | break; 25 | } 26 | return operation; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /CreatePattern/SimpleFactoryPattern/Program.cs: -------------------------------------------------------------------------------- 1 | var oper = OperationFactory.CreateOperation("+"); 2 | oper.NumberA = 2.1; 3 | oper.NumberB = 1.2; 4 | Console.WriteLine($"Opertaion: {oper.NumberA} + {oper.NumberB}, result:{oper.GetResult()}"); 5 | Console.ReadLine(); 6 | -------------------------------------------------------------------------------- /CreatePattern/SimpleFactoryPattern/README.md: -------------------------------------------------------------------------------- 1 | # SimpleFactory 简单工厂 2 | 3 | ## Intro 简介 4 | 5 | 简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。 6 | 7 | 简单工厂模式是工厂模式家族中最简单实用的模式,但不属于23种GOF设计模式之一。因为每次要新增类型的时候必须修改工厂内部代码,不符合开闭原则。 8 | 9 | 在实际的业务代码里,简单工厂的应用还是蛮多的。 10 | 11 | ## 实现方式 12 | 13 | 实现方式大致如下: 14 | 15 | ``` csharp 16 | public class OperationFactory 17 | { 18 | public static Operation CreateOperation(string operate) 19 | { 20 | Operation operation = null; 21 | switch (operate) 22 | { 23 | case "+": 24 | operation = new OperationAdd(); 25 | break; 26 | 27 | case "-": 28 | operation = new OpertaionSub(); 29 | break; 30 | 31 | case "*": 32 | operation = new OperationMul(); 33 | break; 34 | 35 | case "/": 36 | operation = new OperationDiv(); 37 | break; 38 | } 39 | return operation; 40 | } 41 | } 42 | ``` 43 | 44 | ## More 45 | 46 | 更多设计模式及示例代码 [传送门](https://github.com/WeihanLi/DesignPatterns) -------------------------------------------------------------------------------- /CreatePattern/SimpleFactoryPattern/SimpleFactoryPattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /CreatePattern/SingletonPattern/Program.cs: -------------------------------------------------------------------------------- 1 | // //0 2 | // var i0 = Singleton.GetInstance(); 3 | // Console.WriteLine($"Singleton {ReferenceEquals(i0, Singleton.GetInstance())}"); 4 | // //1 5 | // var i1 = Singleton1.GetInstance(); 6 | // Console.WriteLine($"Singleton1 {ReferenceEquals(i1, Singleton1.GetInstance())}"); 7 | // //2 8 | // var i2 = Singleton2.GetInstance(); 9 | // Console.WriteLine($"Singleton2 {ReferenceEquals(i2, Singleton2.GetInstance())}"); 10 | 11 | Console.WriteLine("Singleton"); 12 | Enumerable.Range(1, 10).Select(i => Task.Run(() => 13 | { 14 | Console.WriteLine($"{Singleton.GetInstance().GetHashCode()}"); 15 | })).WhenAll().Wait(); 16 | 17 | Console.WriteLine("Singleton1"); 18 | Enumerable.Range(1, 10).Select(i => Task.Run(() => 19 | { 20 | Console.WriteLine($"{Singleton1.GetInstance().GetHashCode()}"); 21 | })).WhenAll().Wait(); 22 | 23 | Console.WriteLine("Singleton2"); 24 | Enumerable.Range(1, 10).Select(i => Task.Run(() => 25 | { 26 | Console.WriteLine($"{Singleton2.GetInstance().GetHashCode()}"); 27 | })).WhenAll().Wait(); 28 | 29 | Console.WriteLine("Singleton3"); 30 | Enumerable.Range(1, 10).Select(i => Task.Run(() => 31 | { 32 | Console.WriteLine($"{Singleton3.GetInstance().GetHashCode()}"); 33 | })).WhenAll().Wait(); 34 | 35 | Console.ReadLine(); 36 | -------------------------------------------------------------------------------- /CreatePattern/SingletonPattern/README.md: -------------------------------------------------------------------------------- 1 | # 单例模式 Singleton 2 | 3 | ## Intro 4 | 5 | > 单例模式,保证一个类仅有一个实例,并提供一个访问它的全局访问点。 6 | 7 | ## 场景 8 | 9 | 单例模式主要用来确保某个类型的实例只能有一个。比如手机上的蓝牙之类的只能有一个的实例的场景可以考虑用单例模式。 10 | 11 | ## 实现方式 12 | 13 | 基本实现方式是将构造方法私有化,让实例的过程控制在类的内部去完成并对外部提供一个访问实例的方式。 14 | 15 | ### 双重锁定(double-check locking)(懒汉模式) 16 | 17 | ``` csharp 18 | /// 19 | /// 双重判空加锁,饱汉模式(懒汉式),用到的时候再去实例化 20 | /// 21 | public class Singleton 22 | { 23 | private static Singleton _instance; 24 | private static readonly object SyncLock = new object(); 25 | 26 | private Singleton() 27 | { 28 | } 29 | 30 | public static Singleton GetInstance() 31 | { 32 | if (_instance == null) 33 | { 34 | lock (SyncLock) 35 | { 36 | if (_instance == null) 37 | { 38 | _instance = new Singleton(); 39 | } 40 | } 41 | } 42 | 43 | return _instance; 44 | } 45 | } 46 | ``` 47 | 48 | ### 静态初始化 (饿汉模式) 49 | 50 | ``` csharp 51 | /// 52 | /// 饿汉模式-就是屌丝,担心饿死。类加载就给准备好 53 | /// 54 | public sealed class Singleton1 55 | { 56 | /// 57 | /// 静态初始化,由 CLR 去创建 58 | /// 59 | private static readonly Singleton1 Instance = new Singleton1(); 60 | 61 | private Singleton1() 62 | { 63 | } 64 | 65 | public static Singleton1 GetInstance() => Instance; 66 | } 67 | ``` 68 | 69 | ### 并发集合(懒汉模式) 70 | 71 | ``` csharp 72 | /// 73 | /// 使用 ConcurrentDictionary 实现的单例方法,用到的时候再去实例化 74 | /// 这种方式类似于第一种方式,只是使用了并发集合代替了双重判断和 lock 75 | /// 76 | public class Singleton2 77 | { 78 | private static readonly ConcurrentDictionary Instances = new ConcurrentDictionary(); 79 | 80 | private Singleton2() 81 | { 82 | } 83 | 84 | public static Singleton2 GetInstance() => Instances.GetOrAdd(1, k => new Singleton2()); 85 | } 86 | ``` 87 | 88 | ## Lazy 89 | 90 | ``` csharp 91 | /// 92 | /// 使用 Lazy 实现的单例方法,用到的时候再去实例化 93 | /// 94 | public class Singleton3 95 | { 96 | private static readonly Lazy 97 | LazyInstance = new Lazy 98 | (() => new Singleton3()); 99 | 100 | private Singleton3() 101 | { 102 | } 103 | 104 | public static Singleton3 GetInstance() => LazyInstance.Value; 105 | } 106 | ``` 107 | 108 | ## More 109 | 110 | 更多设计模式及示例代码 [传送门](https://github.com/WeihanLi/DesignPatterns) 111 | -------------------------------------------------------------------------------- /CreatePattern/SingletonPattern/Singleton.cs: -------------------------------------------------------------------------------- 1 | namespace SingletonPattern; 2 | 3 | /// 4 | /// 双重判空加锁,饱汉模式(懒汉式),用到的时候再去实例化 5 | /// 6 | public class Singleton 7 | { 8 | private static Singleton _instance; 9 | private static readonly object SyncLock = new(); 10 | 11 | private Singleton() 12 | { 13 | } 14 | 15 | public static Singleton GetInstance() 16 | { 17 | if (_instance == null) 18 | { 19 | lock (SyncLock) 20 | { 21 | if (_instance == null) 22 | { 23 | _instance = new Singleton(); 24 | } 25 | } 26 | } 27 | 28 | return _instance; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /CreatePattern/SingletonPattern/Singleton1.cs: -------------------------------------------------------------------------------- 1 | namespace SingletonPattern; 2 | 3 | /// 4 | /// 饿汉模式-就是屌丝,担心饿死。类加载就给准备好 5 | /// 6 | public sealed class Singleton1 7 | { 8 | /// 9 | /// 静态初始化,由 CLR 去创建 10 | /// 11 | private static readonly Singleton1 Instance = new(); 12 | 13 | private Singleton1() 14 | { 15 | } 16 | 17 | public static Singleton1 GetInstance() => Instance; 18 | } 19 | -------------------------------------------------------------------------------- /CreatePattern/SingletonPattern/Singleton2.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Concurrent; 2 | 3 | namespace SingletonPattern; 4 | 5 | /// 6 | /// 使用 ConcurrentDictionary 实现的单例方法,用到的时候再去实例化 7 | /// 这种方式类似于双重锁定方式,只是使用了并发集合代替了双重判断和 lock 8 | /// 9 | public class Singleton2 10 | { 11 | private static readonly ConcurrentDictionary Instances = new(); 12 | 13 | private Singleton2() 14 | { 15 | } 16 | 17 | public static Singleton2 GetInstance() => Instances.GetOrAdd(1, k => new Singleton2()); 18 | } 19 | -------------------------------------------------------------------------------- /CreatePattern/SingletonPattern/Singleton3.cs: -------------------------------------------------------------------------------- 1 | namespace SingletonPattern; 2 | 3 | /// 4 | /// 使用 Lazy 实现的单例方法,用到的时候再去实例化 5 | /// 6 | public class Singleton3 7 | { 8 | private static readonly Lazy 9 | LazyInstance = new(() => new Singleton3()); 10 | 11 | private Singleton3() 12 | { 13 | } 14 | 15 | public static Singleton3 GetInstance() => LazyInstance.Value; 16 | } 17 | -------------------------------------------------------------------------------- /CreatePattern/SingletonPattern/SingletonPattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /DesignPatterns.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27428.2015 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CreatePatterns", "CreatePatterns", "{40E504AB-1483-4A57-882C-A736FF5B7E3C}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "StructurePatterns", "StructurePatterns", "{EB426AC4-F584-4997-9C32-BF01A110133F}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BehaviorPatterns", "BehaviorPatterns", "{E40E3345-7362-45AC-B8F9-DC8F1C16F22B}" 11 | EndProject 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SingletonPattern", "CreatePattern\SingletonPattern\SingletonPattern.csproj", "{89AF4B3E-1417-4C07-A5D4-4C9C41B41857}" 13 | EndProject 14 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SimpleFactoryPattern", "CreatePattern\SimpleFactoryPattern\SimpleFactoryPattern.csproj", "{66CC9E63-BF43-4C5D-9902-5AB9F8345F5A}" 15 | EndProject 16 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AbstractFactoryPattern", "CreatePattern\AbstractFactoryPattern\AbstractFactoryPattern.csproj", "{D57292CA-661A-41F0-9FB5-CAC3CC57AC23}" 17 | EndProject 18 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FactoryMethodPattern", "CreatePattern\FactoryMethodPattern\FactoryMethodPattern.csproj", "{04FE2827-1965-4A9F-807B-B96B6F9D0237}" 19 | EndProject 20 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BuilderPattern", "CreatePattern\BuilderPattern\BuilderPattern.csproj", "{1FD2929A-7048-44FE-A365-AF70D85CE39E}" 21 | EndProject 22 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PrototypePattern", "CreatePattern\PrototypePattern\PrototypePattern.csproj", "{97FB695E-9628-4C12-A1EE-E5196DBC04D7}" 23 | EndProject 24 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AdapterPattern", "StructurePattern\AdapterPattern\AdapterPattern.csproj", "{77D3D55F-AABF-44D3-A312-784694EAE2EA}" 25 | EndProject 26 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BridgePattern", "StructurePattern\BridgePattern\BridgePattern.csproj", "{B13F961A-5B41-4F42-9FF3-104892EE5076}" 27 | EndProject 28 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CompositePattern", "StructurePattern\CompositePattern\CompositePattern.csproj", "{5617388E-09D3-4978-BEA5-FE3D0EE18639}" 29 | EndProject 30 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DecoratorPattern", "StructurePattern\DecoratorPattern\DecoratorPattern.csproj", "{10C86558-B165-4625-83E1-2F6BA14F35DD}" 31 | EndProject 32 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FacadePattern", "StructurePattern\FacadePattern\FacadePattern.csproj", "{24E81A12-7A22-43E6-8BFD-B57E2AAD5C09}" 33 | EndProject 34 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProxyPattern", "StructurePattern\ProxyPattern\ProxyPattern.csproj", "{B8E74FFE-1B61-4192-82D7-56F5062E5693}" 35 | EndProject 36 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FlyweightPattern", "StructurePattern\FlyweightPattern\FlyweightPattern.csproj", "{26B53C4A-165E-48BA-B6C8-0358DE3456A3}" 37 | EndProject 38 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommandPattern", "BehaviorPattern\CommandPattern\CommandPattern.csproj", "{8D79904A-17FB-4201-830C-6219D7A4AD4C}" 39 | EndProject 40 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChainOfResponsibilityPattern", "BehaviorPattern\ChainOfResponsibilityPattern\ChainOfResponsibilityPattern.csproj", "{B13F34F8-7A54-4752-9C7A-8690071C5A75}" 41 | EndProject 42 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InterpreterPattern", "BehaviorPattern\InterpreterPattern\InterpreterPattern.csproj", "{455F28EB-5E95-43CA-9CDD-B7E02780383E}" 43 | EndProject 44 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IteratorPattern", "BehaviorPattern\IteratorPattern\IteratorPattern.csproj", "{04E11001-6581-411C-98CF-BD1D5E59FEA6}" 45 | EndProject 46 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediatorPattern", "BehaviorPattern\MediatorPattern\MediatorPattern.csproj", "{508EBD55-6B98-4EB9-A3E8-00907F232B7B}" 47 | EndProject 48 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MementoPattern", "BehaviorPattern\MementoPattern\MementoPattern.csproj", "{7C917440-EC62-49B5-A1BC-22722FD2A607}" 49 | EndProject 50 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ObserverPattern", "BehaviorPattern\ObserverPattern\ObserverPattern.csproj", "{97F43C8B-2F15-4384-A865-D858C0453C78}" 51 | EndProject 52 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StatePattern", "BehaviorPattern\StatePattern\StatePattern.csproj", "{8E4B4C5F-C73D-4D1F-B69E-4A2370B4BE7D}" 53 | EndProject 54 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StrategyPattern", "BehaviorPattern\StrategyPattern\StrategyPattern.csproj", "{3BA9EE2A-C046-4102-A26F-3878CAF60D5D}" 55 | EndProject 56 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TemplateMethodPattern", "BehaviorPattern\TemplateMethodPattern\TemplateMethodPattern.csproj", "{B2CDC899-8C25-46E1-B03C-772C2485C73D}" 57 | EndProject 58 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VisitorPattern", "BehaviorPattern\VisitorPattern\VisitorPattern.csproj", "{312EBED8-38B5-4573-9F77-4A63AC6ED47D}" 59 | EndProject 60 | Global 61 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 62 | Debug|Any CPU = Debug|Any CPU 63 | Release|Any CPU = Release|Any CPU 64 | EndGlobalSection 65 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 66 | {89AF4B3E-1417-4C07-A5D4-4C9C41B41857}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 67 | {89AF4B3E-1417-4C07-A5D4-4C9C41B41857}.Debug|Any CPU.Build.0 = Debug|Any CPU 68 | {89AF4B3E-1417-4C07-A5D4-4C9C41B41857}.Release|Any CPU.ActiveCfg = Release|Any CPU 69 | {89AF4B3E-1417-4C07-A5D4-4C9C41B41857}.Release|Any CPU.Build.0 = Release|Any CPU 70 | {66CC9E63-BF43-4C5D-9902-5AB9F8345F5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 71 | {66CC9E63-BF43-4C5D-9902-5AB9F8345F5A}.Debug|Any CPU.Build.0 = Debug|Any CPU 72 | {66CC9E63-BF43-4C5D-9902-5AB9F8345F5A}.Release|Any CPU.ActiveCfg = Release|Any CPU 73 | {66CC9E63-BF43-4C5D-9902-5AB9F8345F5A}.Release|Any CPU.Build.0 = Release|Any CPU 74 | {D57292CA-661A-41F0-9FB5-CAC3CC57AC23}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 75 | {D57292CA-661A-41F0-9FB5-CAC3CC57AC23}.Debug|Any CPU.Build.0 = Debug|Any CPU 76 | {D57292CA-661A-41F0-9FB5-CAC3CC57AC23}.Release|Any CPU.ActiveCfg = Release|Any CPU 77 | {D57292CA-661A-41F0-9FB5-CAC3CC57AC23}.Release|Any CPU.Build.0 = Release|Any CPU 78 | {04FE2827-1965-4A9F-807B-B96B6F9D0237}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 79 | {04FE2827-1965-4A9F-807B-B96B6F9D0237}.Debug|Any CPU.Build.0 = Debug|Any CPU 80 | {04FE2827-1965-4A9F-807B-B96B6F9D0237}.Release|Any CPU.ActiveCfg = Release|Any CPU 81 | {04FE2827-1965-4A9F-807B-B96B6F9D0237}.Release|Any CPU.Build.0 = Release|Any CPU 82 | {1FD2929A-7048-44FE-A365-AF70D85CE39E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 83 | {1FD2929A-7048-44FE-A365-AF70D85CE39E}.Debug|Any CPU.Build.0 = Debug|Any CPU 84 | {1FD2929A-7048-44FE-A365-AF70D85CE39E}.Release|Any CPU.ActiveCfg = Release|Any CPU 85 | {1FD2929A-7048-44FE-A365-AF70D85CE39E}.Release|Any CPU.Build.0 = Release|Any CPU 86 | {97FB695E-9628-4C12-A1EE-E5196DBC04D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 87 | {97FB695E-9628-4C12-A1EE-E5196DBC04D7}.Debug|Any CPU.Build.0 = Debug|Any CPU 88 | {97FB695E-9628-4C12-A1EE-E5196DBC04D7}.Release|Any CPU.ActiveCfg = Release|Any CPU 89 | {97FB695E-9628-4C12-A1EE-E5196DBC04D7}.Release|Any CPU.Build.0 = Release|Any CPU 90 | {77D3D55F-AABF-44D3-A312-784694EAE2EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 91 | {77D3D55F-AABF-44D3-A312-784694EAE2EA}.Debug|Any CPU.Build.0 = Debug|Any CPU 92 | {77D3D55F-AABF-44D3-A312-784694EAE2EA}.Release|Any CPU.ActiveCfg = Release|Any CPU 93 | {77D3D55F-AABF-44D3-A312-784694EAE2EA}.Release|Any CPU.Build.0 = Release|Any CPU 94 | {B13F961A-5B41-4F42-9FF3-104892EE5076}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 95 | {B13F961A-5B41-4F42-9FF3-104892EE5076}.Debug|Any CPU.Build.0 = Debug|Any CPU 96 | {B13F961A-5B41-4F42-9FF3-104892EE5076}.Release|Any CPU.ActiveCfg = Release|Any CPU 97 | {B13F961A-5B41-4F42-9FF3-104892EE5076}.Release|Any CPU.Build.0 = Release|Any CPU 98 | {5617388E-09D3-4978-BEA5-FE3D0EE18639}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 99 | {5617388E-09D3-4978-BEA5-FE3D0EE18639}.Debug|Any CPU.Build.0 = Debug|Any CPU 100 | {5617388E-09D3-4978-BEA5-FE3D0EE18639}.Release|Any CPU.ActiveCfg = Release|Any CPU 101 | {5617388E-09D3-4978-BEA5-FE3D0EE18639}.Release|Any CPU.Build.0 = Release|Any CPU 102 | {10C86558-B165-4625-83E1-2F6BA14F35DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 103 | {10C86558-B165-4625-83E1-2F6BA14F35DD}.Debug|Any CPU.Build.0 = Debug|Any CPU 104 | {10C86558-B165-4625-83E1-2F6BA14F35DD}.Release|Any CPU.ActiveCfg = Release|Any CPU 105 | {10C86558-B165-4625-83E1-2F6BA14F35DD}.Release|Any CPU.Build.0 = Release|Any CPU 106 | {24E81A12-7A22-43E6-8BFD-B57E2AAD5C09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 107 | {24E81A12-7A22-43E6-8BFD-B57E2AAD5C09}.Debug|Any CPU.Build.0 = Debug|Any CPU 108 | {24E81A12-7A22-43E6-8BFD-B57E2AAD5C09}.Release|Any CPU.ActiveCfg = Release|Any CPU 109 | {24E81A12-7A22-43E6-8BFD-B57E2AAD5C09}.Release|Any CPU.Build.0 = Release|Any CPU 110 | {B8E74FFE-1B61-4192-82D7-56F5062E5693}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 111 | {B8E74FFE-1B61-4192-82D7-56F5062E5693}.Debug|Any CPU.Build.0 = Debug|Any CPU 112 | {B8E74FFE-1B61-4192-82D7-56F5062E5693}.Release|Any CPU.ActiveCfg = Release|Any CPU 113 | {B8E74FFE-1B61-4192-82D7-56F5062E5693}.Release|Any CPU.Build.0 = Release|Any CPU 114 | {26B53C4A-165E-48BA-B6C8-0358DE3456A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 115 | {26B53C4A-165E-48BA-B6C8-0358DE3456A3}.Debug|Any CPU.Build.0 = Debug|Any CPU 116 | {26B53C4A-165E-48BA-B6C8-0358DE3456A3}.Release|Any CPU.ActiveCfg = Release|Any CPU 117 | {26B53C4A-165E-48BA-B6C8-0358DE3456A3}.Release|Any CPU.Build.0 = Release|Any CPU 118 | {8D79904A-17FB-4201-830C-6219D7A4AD4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 119 | {8D79904A-17FB-4201-830C-6219D7A4AD4C}.Debug|Any CPU.Build.0 = Debug|Any CPU 120 | {8D79904A-17FB-4201-830C-6219D7A4AD4C}.Release|Any CPU.ActiveCfg = Release|Any CPU 121 | {8D79904A-17FB-4201-830C-6219D7A4AD4C}.Release|Any CPU.Build.0 = Release|Any CPU 122 | {B13F34F8-7A54-4752-9C7A-8690071C5A75}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 123 | {B13F34F8-7A54-4752-9C7A-8690071C5A75}.Debug|Any CPU.Build.0 = Debug|Any CPU 124 | {B13F34F8-7A54-4752-9C7A-8690071C5A75}.Release|Any CPU.ActiveCfg = Release|Any CPU 125 | {B13F34F8-7A54-4752-9C7A-8690071C5A75}.Release|Any CPU.Build.0 = Release|Any CPU 126 | {455F28EB-5E95-43CA-9CDD-B7E02780383E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 127 | {455F28EB-5E95-43CA-9CDD-B7E02780383E}.Debug|Any CPU.Build.0 = Debug|Any CPU 128 | {455F28EB-5E95-43CA-9CDD-B7E02780383E}.Release|Any CPU.ActiveCfg = Release|Any CPU 129 | {455F28EB-5E95-43CA-9CDD-B7E02780383E}.Release|Any CPU.Build.0 = Release|Any CPU 130 | {04E11001-6581-411C-98CF-BD1D5E59FEA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 131 | {04E11001-6581-411C-98CF-BD1D5E59FEA6}.Debug|Any CPU.Build.0 = Debug|Any CPU 132 | {04E11001-6581-411C-98CF-BD1D5E59FEA6}.Release|Any CPU.ActiveCfg = Release|Any CPU 133 | {04E11001-6581-411C-98CF-BD1D5E59FEA6}.Release|Any CPU.Build.0 = Release|Any CPU 134 | {508EBD55-6B98-4EB9-A3E8-00907F232B7B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 135 | {508EBD55-6B98-4EB9-A3E8-00907F232B7B}.Debug|Any CPU.Build.0 = Debug|Any CPU 136 | {508EBD55-6B98-4EB9-A3E8-00907F232B7B}.Release|Any CPU.ActiveCfg = Release|Any CPU 137 | {508EBD55-6B98-4EB9-A3E8-00907F232B7B}.Release|Any CPU.Build.0 = Release|Any CPU 138 | {7C917440-EC62-49B5-A1BC-22722FD2A607}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 139 | {7C917440-EC62-49B5-A1BC-22722FD2A607}.Debug|Any CPU.Build.0 = Debug|Any CPU 140 | {7C917440-EC62-49B5-A1BC-22722FD2A607}.Release|Any CPU.ActiveCfg = Release|Any CPU 141 | {7C917440-EC62-49B5-A1BC-22722FD2A607}.Release|Any CPU.Build.0 = Release|Any CPU 142 | {97F43C8B-2F15-4384-A865-D858C0453C78}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 143 | {97F43C8B-2F15-4384-A865-D858C0453C78}.Debug|Any CPU.Build.0 = Debug|Any CPU 144 | {97F43C8B-2F15-4384-A865-D858C0453C78}.Release|Any CPU.ActiveCfg = Release|Any CPU 145 | {97F43C8B-2F15-4384-A865-D858C0453C78}.Release|Any CPU.Build.0 = Release|Any CPU 146 | {8E4B4C5F-C73D-4D1F-B69E-4A2370B4BE7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 147 | {8E4B4C5F-C73D-4D1F-B69E-4A2370B4BE7D}.Debug|Any CPU.Build.0 = Debug|Any CPU 148 | {8E4B4C5F-C73D-4D1F-B69E-4A2370B4BE7D}.Release|Any CPU.ActiveCfg = Release|Any CPU 149 | {8E4B4C5F-C73D-4D1F-B69E-4A2370B4BE7D}.Release|Any CPU.Build.0 = Release|Any CPU 150 | {3BA9EE2A-C046-4102-A26F-3878CAF60D5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 151 | {3BA9EE2A-C046-4102-A26F-3878CAF60D5D}.Debug|Any CPU.Build.0 = Debug|Any CPU 152 | {3BA9EE2A-C046-4102-A26F-3878CAF60D5D}.Release|Any CPU.ActiveCfg = Release|Any CPU 153 | {3BA9EE2A-C046-4102-A26F-3878CAF60D5D}.Release|Any CPU.Build.0 = Release|Any CPU 154 | {B2CDC899-8C25-46E1-B03C-772C2485C73D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 155 | {B2CDC899-8C25-46E1-B03C-772C2485C73D}.Debug|Any CPU.Build.0 = Debug|Any CPU 156 | {B2CDC899-8C25-46E1-B03C-772C2485C73D}.Release|Any CPU.ActiveCfg = Release|Any CPU 157 | {B2CDC899-8C25-46E1-B03C-772C2485C73D}.Release|Any CPU.Build.0 = Release|Any CPU 158 | {312EBED8-38B5-4573-9F77-4A63AC6ED47D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 159 | {312EBED8-38B5-4573-9F77-4A63AC6ED47D}.Debug|Any CPU.Build.0 = Debug|Any CPU 160 | {312EBED8-38B5-4573-9F77-4A63AC6ED47D}.Release|Any CPU.ActiveCfg = Release|Any CPU 161 | {312EBED8-38B5-4573-9F77-4A63AC6ED47D}.Release|Any CPU.Build.0 = Release|Any CPU 162 | EndGlobalSection 163 | GlobalSection(SolutionProperties) = preSolution 164 | HideSolutionNode = FALSE 165 | EndGlobalSection 166 | GlobalSection(NestedProjects) = preSolution 167 | {89AF4B3E-1417-4C07-A5D4-4C9C41B41857} = {40E504AB-1483-4A57-882C-A736FF5B7E3C} 168 | {66CC9E63-BF43-4C5D-9902-5AB9F8345F5A} = {40E504AB-1483-4A57-882C-A736FF5B7E3C} 169 | {D57292CA-661A-41F0-9FB5-CAC3CC57AC23} = {40E504AB-1483-4A57-882C-A736FF5B7E3C} 170 | {04FE2827-1965-4A9F-807B-B96B6F9D0237} = {40E504AB-1483-4A57-882C-A736FF5B7E3C} 171 | {1FD2929A-7048-44FE-A365-AF70D85CE39E} = {40E504AB-1483-4A57-882C-A736FF5B7E3C} 172 | {97FB695E-9628-4C12-A1EE-E5196DBC04D7} = {40E504AB-1483-4A57-882C-A736FF5B7E3C} 173 | {77D3D55F-AABF-44D3-A312-784694EAE2EA} = {EB426AC4-F584-4997-9C32-BF01A110133F} 174 | {B13F961A-5B41-4F42-9FF3-104892EE5076} = {EB426AC4-F584-4997-9C32-BF01A110133F} 175 | {5617388E-09D3-4978-BEA5-FE3D0EE18639} = {EB426AC4-F584-4997-9C32-BF01A110133F} 176 | {10C86558-B165-4625-83E1-2F6BA14F35DD} = {EB426AC4-F584-4997-9C32-BF01A110133F} 177 | {24E81A12-7A22-43E6-8BFD-B57E2AAD5C09} = {EB426AC4-F584-4997-9C32-BF01A110133F} 178 | {B8E74FFE-1B61-4192-82D7-56F5062E5693} = {EB426AC4-F584-4997-9C32-BF01A110133F} 179 | {26B53C4A-165E-48BA-B6C8-0358DE3456A3} = {EB426AC4-F584-4997-9C32-BF01A110133F} 180 | {8D79904A-17FB-4201-830C-6219D7A4AD4C} = {E40E3345-7362-45AC-B8F9-DC8F1C16F22B} 181 | {B13F34F8-7A54-4752-9C7A-8690071C5A75} = {E40E3345-7362-45AC-B8F9-DC8F1C16F22B} 182 | {455F28EB-5E95-43CA-9CDD-B7E02780383E} = {E40E3345-7362-45AC-B8F9-DC8F1C16F22B} 183 | {04E11001-6581-411C-98CF-BD1D5E59FEA6} = {E40E3345-7362-45AC-B8F9-DC8F1C16F22B} 184 | {508EBD55-6B98-4EB9-A3E8-00907F232B7B} = {E40E3345-7362-45AC-B8F9-DC8F1C16F22B} 185 | {7C917440-EC62-49B5-A1BC-22722FD2A607} = {E40E3345-7362-45AC-B8F9-DC8F1C16F22B} 186 | {97F43C8B-2F15-4384-A865-D858C0453C78} = {E40E3345-7362-45AC-B8F9-DC8F1C16F22B} 187 | {8E4B4C5F-C73D-4D1F-B69E-4A2370B4BE7D} = {E40E3345-7362-45AC-B8F9-DC8F1C16F22B} 188 | {3BA9EE2A-C046-4102-A26F-3878CAF60D5D} = {E40E3345-7362-45AC-B8F9-DC8F1C16F22B} 189 | {B2CDC899-8C25-46E1-B03C-772C2485C73D} = {E40E3345-7362-45AC-B8F9-DC8F1C16F22B} 190 | {312EBED8-38B5-4573-9F77-4A63AC6ED47D} = {E40E3345-7362-45AC-B8F9-DC8F1C16F22B} 191 | EndGlobalSection 192 | GlobalSection(ExtensibilityGlobals) = postSolution 193 | SolutionGuid = {8DB17F74-9009-47D4-95E8-1FA7A13A3C5E} 194 | EndGlobalSection 195 | EndGlobal 196 | -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | net8.0 4 | Exe 5 | 6 | latest 7 | enable 8 | 9 | git 10 | https://github.com/WeihanLi/DesignPatterns 11 | WeihanLi 12 | Copyright 2017-2024 (c) WeihanLi 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Directory.Build.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017-2022 liweihan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Principles.md: -------------------------------------------------------------------------------- 1 | # 设计模式设计原则 2 | 3 | - 单一职责原则 4 | 5 | > 对于一个类而言,应该仅有一个引起它变化的原因 6 | > 7 | > 如果一个类承担的职责过多,就等于把这些职责耦合再一起,一个职责的变化可能会削弱或者抑制这个类完全其他职责的能力。这种耦合会导致脆弱的设计,当发生变化时,设计会遭受到意想不到的破坏。 8 | 9 | - 开放-封闭原则 10 | 11 | > 开放-封闭原则是说软件实体(类、模块、函数等等)应该可以扩展,但是不可修改。 12 | > 13 | > 对于扩展开放,对于更改封闭 14 | 15 | - 依赖倒转原则 16 | 17 | > - 高层模块不应该依赖低层模式,两个都应该依赖抽象。 18 | > - 抽象不应该依赖细节,细节应该依赖于抽象。基于接口编程。 19 | 20 | - 里氏代换原则 21 | 22 | > 子类型必须能够替换掉它们的父类型 23 | 24 | - 接口隔离原则 25 | 26 | > 使用多个隔离的接口,比使用单个接口好,建立最小的接口 27 | > 28 | > 一个接口只负责一个功能 29 | 30 | - 迪米特法则 31 | 32 | > 如果两个类不必彼此通信,那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法,可以通过第三者转发这个调用。 33 | > 34 | > 类的结构设计上,每一个类都应当尽量降低成员的访问权限 35 | > 36 | > 类之间的耦合越弱,越有利于复用,一个处在弱耦合的类别修改,不会对有关系的类造成波及 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DesignPatterns 2 | 3 | ## Intro 简介 4 | 5 | Design patterns from 《大话设计模式》 and some samples implemented by C#. 6 | 7 | 《大话设计模式》 中设计模式总结,示例代码是用 C# 写的,如果需要自己编译请[安装 .NET SDK](https://get.dot.net),[下载 PDF 点这里](大话设计模式.pdf) 8 | 9 | ## 设计模式设计原则 10 | 11 | - 单一职责原则 12 | 13 | > 对于一个类而言,应该仅有一个引起它变化的原因 14 | > 15 | > 如果一个类承担的职责过多,就等于把这些职责耦合再一起,一个职责的变化可能会削弱或者抑制这个类完全其他职责的能力。这种耦合会导致脆弱的设计,当发生变化时,设计会遭受到意想不到的破坏。 16 | 17 | - 开放-封闭原则 18 | 19 | > 开放-封闭原则是说软件实体(类、模块、函数等等)应该可以扩展,但是不可修改。 20 | > 21 | > 对于扩展开放,对于更改封闭 22 | 23 | - 依赖倒转原则 24 | 25 | > - 高层模块不应该依赖低层模式,两个都应该依赖抽象。 26 | > - 抽象不应该依赖细节,细节应该依赖于抽象。基于接口编程。 27 | 28 | - 里氏代换原则 29 | 30 | > 子类型必须能够替换掉它们的父类型 31 | 32 | - 接口隔离原则 33 | 34 | > 使用多个隔离的接口,比使用单个接口好,建立最小的接口 35 | > 36 | > 一个接口只负责一个功能 37 | 38 | - 迪米特法则 39 | 40 | > 如果两个类不必彼此通信,那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法,可以通过第三者转发这个调用。 41 | > 42 | > 类的结构设计上,每一个类都应当尽量降低成员的访问权限 43 | > 44 | > 类之间的耦合越弱,越有利于复用,一个处在弱耦合的类别修改,不会对有关系的类造成波及 45 | 46 | ## Overview 概览 47 | 48 | ![image](https://github.com/user-attachments/assets/b664a09b-1950-405a-9476-8ae721b62af9) 49 | 50 | 设计模式大体上可分为三类: 51 | 52 | - [创建型模式(Create)](./CreatePattern) 53 | 1. [简单工厂(SimpleFactory)](./CreatePattern/SimpleFactoryPattern) 54 | 1. [抽象工厂(AbstractFactory)](./CreatePattern/AbstractFactoryPattern) 55 | 1. [工厂方法(FactoryMethod)](./CreatePattern/FactoryMethodPattern) 56 | 1. [建造者模式(Builder)](./CreatePattern/BuilderPattern) 57 | 1. [原型模式(Prototype)](./CreatePattern/PrototypePattern) 58 | 1. [单例模式(Singleton)](./CreatePattern/SingletonPattern) 59 | 60 | - [结构型模式(Structure)](./StructurePattern) 61 | 1. [适配器模式(Adapter)](./StructurePattern/AdapterPattern) 62 | 1. [桥接模式(Bridge)](./StructurePattern/BridgePattern) 63 | 1. [组合模式(Composite)](./StructurePattern/CompositePattern) 64 | 1. [装饰(者/器)模式(Decorator)](./StructurePattern/DecoratorPattern) 65 | 1. [外观/门面模式(Facade)](./StructurePattern/FacadePattern) 66 | 1. [享元模式(Flyweight)](./StructurePattern/FlyweightPattern) 67 | 1. [代理模式(Proxy)](./StructurePattern/ProxyPattern) 68 | 69 | - [行为型模式(Behavior)](./BehaviorPattern) 70 | 1. [观察者模式(Observer)](./BehaviorPattern/ObserverPattern) 71 | 1. [模板方法(TemplateMethod)](./BehaviorPattern/TemplateMethodPattern) 72 | 1. [命令模式(Command)](./BehaviorPattern/CommandPattern) 73 | 1. [状态模式(State)](./BehaviorPattern/StatePattern) 74 | 1. [职责链模式(Chain of Responsibility)](./BehaviorPattern/ChainOfResponsibilityPattern) 75 | 1. [解释器模式(Interpreter)](./BehaviorPattern/InterpreterPattern) 76 | 1. [中介者模式(Mediator)](./BehaviorPattern/MediatorPattern) 77 | 1. [访问者模式(Visitor)](./BehaviorPattern/VisitorPattern) 78 | 1. [备忘录模式(Memento)](./BehaviorPattern/MementoPattern) 79 | 1. [迭代器模式(Iterator)](./BehaviorPattern/IteratorPattern) 80 | 1. [策略模式(Strategy)](./BehaviorPattern/StrategyPattern) 81 | 82 | -------------------------------------------------------------------------------- /StructurePattern/AdapterPattern/AdapterPattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /StructurePattern/AdapterPattern/Player.cs: -------------------------------------------------------------------------------- 1 | namespace AdapterPattern; 2 | 3 | internal abstract class Player 4 | { 5 | public abstract void Attact(); 6 | 7 | public abstract void Defend(); 8 | } 9 | 10 | internal class Forwards : Player 11 | { 12 | private readonly string _name; 13 | 14 | public Forwards(string name) => _name = name; 15 | 16 | public override void Attact() 17 | { 18 | Console.WriteLine($"前锋 {_name} attact"); 19 | } 20 | 21 | public override void Defend() 22 | { 23 | Console.WriteLine($"前锋 {_name} defend"); 24 | } 25 | } 26 | 27 | internal class Guards : Player 28 | { 29 | private readonly string _name; 30 | 31 | public Guards(string name) => _name = name; 32 | 33 | public override void Attact() 34 | { 35 | Console.WriteLine($"后卫 {_name} attact"); 36 | } 37 | 38 | public override void Defend() 39 | { 40 | Console.WriteLine($"后卫 {_name} defend"); 41 | } 42 | } 43 | 44 | internal class ForeignGuards 45 | { 46 | private readonly string _name; 47 | 48 | public ForeignGuards(string name) => _name = name; 49 | 50 | public void 进攻() 51 | { 52 | Console.WriteLine($"后卫 {_name} 进攻"); 53 | } 54 | 55 | public void 防守() 56 | { 57 | Console.WriteLine($"后卫 {_name} 防守"); 58 | } 59 | } 60 | 61 | internal class Translator : Player 62 | { 63 | private readonly ForeignGuards _foreignGuards; 64 | 65 | public Translator(string name) => _foreignGuards = new ForeignGuards(name); 66 | 67 | public override void Attact() => _foreignGuards.进攻(); 68 | 69 | public override void Defend() => _foreignGuards.防守(); 70 | } 71 | -------------------------------------------------------------------------------- /StructurePattern/AdapterPattern/Program.cs: -------------------------------------------------------------------------------- 1 | Target target = new TargetAdapter(); 2 | target.Request(); 3 | 4 | Player player1 = new Forwards("巴蒂尔"); 5 | player1.Attact(); 6 | Player player2 = new Guards("麦迪"); 7 | player2.Defend(); 8 | Player specialPlayer = new Translator("姚明"); 9 | specialPlayer.Attact(); 10 | specialPlayer.Defend(); 11 | 12 | Console.ReadLine(); 13 | -------------------------------------------------------------------------------- /StructurePattern/AdapterPattern/Prototype.cs: -------------------------------------------------------------------------------- 1 | namespace AdapterPattern; 2 | 3 | internal class Target 4 | { 5 | public virtual void Request() 6 | { 7 | Console.WriteLine("This is a common request"); 8 | } 9 | } 10 | 11 | internal class Adaptee 12 | { 13 | public void SpecialRequest() 14 | { 15 | Console.WriteLine("this is a special request"); 16 | } 17 | } 18 | 19 | internal class TargetAdapter : Target 20 | { 21 | private readonly Adaptee _adaptee = new(); 22 | 23 | public override void Request() 24 | { 25 | _adaptee.SpecialRequest(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /StructurePattern/AdapterPattern/README.md: -------------------------------------------------------------------------------- 1 | # 适配器模式 Adapter 2 | 3 | ## Intro 4 | 5 | 适配器模式,将一个类的接口适配成用户所期待的。一个适配允许通常因为接口不兼容而不能在一起工作的类工作在一起,做法是将类自己的接口包裹在一个已存在的类中。也被称为 Wrapper 模式。 6 | 7 | 通常这个类是外部的类,不能直接修改,所以需要做一层包装,以适配现有的接口。 8 | 9 | ## Prototype 10 | 11 | ``` csharp 12 | public class Target 13 | { 14 | public virtual void Request() 15 | { 16 | Console.WriteLine("This is a common request"); 17 | } 18 | } 19 | 20 | public class Adaptee 21 | { 22 | public void SpecialRequest() 23 | { 24 | Console.WriteLine("this is a special request"); 25 | } 26 | } 27 | 28 | public class TargetAdapter : Target 29 | { 30 | private readonly Adaptee _adaptee = new Adaptee(); 31 | 32 | public override void Request() 33 | { 34 | _adaptee.SpecialRequest(); 35 | } 36 | } 37 | ``` 38 | 39 | ## More 40 | 41 | 更多设计模式及示例代码 [传送门](https://github.com/WeihanLi/DesignPatterns) 42 | -------------------------------------------------------------------------------- /StructurePattern/BridgePattern/BridgePattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /StructurePattern/BridgePattern/HandsetBrand.cs: -------------------------------------------------------------------------------- 1 | namespace BridgePattern; 2 | 3 | internal abstract class HandsetBrand 4 | { 5 | protected HandsetSoft Soft; 6 | 7 | public void SetHandsetSoft(HandsetSoft soft) 8 | { 9 | Soft = soft; 10 | } 11 | 12 | public abstract void Run(); 13 | } 14 | 15 | internal class HandsetBrandM : HandsetBrand 16 | { 17 | public override void Run() 18 | { 19 | Soft.Run(); 20 | Console.WriteLine("running in brand M"); 21 | } 22 | } 23 | 24 | internal class HandsetBrandN : HandsetBrand 25 | { 26 | public override void Run() 27 | { 28 | Soft.Run(); 29 | Console.WriteLine("running in brand N"); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /StructurePattern/BridgePattern/HandsetSoft.cs: -------------------------------------------------------------------------------- 1 | namespace BridgePattern; 2 | 3 | internal abstract class HandsetSoft 4 | { 5 | public abstract void Run(); 6 | } 7 | 8 | internal class HandsetGame : HandsetSoft 9 | { 10 | public override void Run() 11 | { 12 | Console.WriteLine("Game is running..."); 13 | } 14 | } 15 | 16 | internal class HandsetMp3 : HandsetSoft 17 | { 18 | public override void Run() 19 | { 20 | Console.WriteLine("Mp3 is running..."); 21 | } 22 | } 23 | 24 | internal class HandsetAddressList : HandsetSoft 25 | { 26 | public override void Run() 27 | { 28 | Console.WriteLine("AddressList is running..."); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /StructurePattern/BridgePattern/Program.cs: -------------------------------------------------------------------------------- 1 | #region Prototype 2 | 3 | Abstraction ab = new RefinedAbstraction(); 4 | 5 | ab.SetImplementor(new ConcreteImplementorA()); 6 | ab.Operation(); 7 | 8 | ab.SetImplementor(new ConcreteImplementorB()); 9 | ab.Operation(); 10 | 11 | Console.WriteLine(); 12 | 13 | #endregion Prototype 14 | 15 | HandsetBrand handsetBrand = new HandsetBrandM(); 16 | handsetBrand.SetHandsetSoft(new HandsetMp3()); 17 | handsetBrand.Run(); 18 | handsetBrand.SetHandsetSoft(new HandsetGame()); 19 | handsetBrand.Run(); 20 | 21 | handsetBrand = new HandsetBrandN(); 22 | handsetBrand.SetHandsetSoft(new HandsetAddressList()); 23 | handsetBrand.Run(); 24 | 25 | Console.ReadLine(); 26 | -------------------------------------------------------------------------------- /StructurePattern/BridgePattern/Prototype.cs: -------------------------------------------------------------------------------- 1 | namespace BridgePattern; 2 | 3 | internal abstract class Implementor 4 | { 5 | public abstract void Operation(); 6 | } 7 | 8 | internal class ConcreteImplementorA : Implementor 9 | { 10 | public override void Operation() 11 | { 12 | Console.WriteLine("ImplementorA Operation"); 13 | } 14 | } 15 | 16 | internal class ConcreteImplementorB : Implementor 17 | { 18 | public override void Operation() 19 | { 20 | Console.WriteLine("ImplementorB Operation"); 21 | } 22 | } 23 | 24 | internal abstract class Abstraction 25 | { 26 | protected Implementor Implementor; 27 | 28 | public void SetImplementor(Implementor implementor) 29 | { 30 | Implementor = implementor; 31 | } 32 | 33 | public abstract void Operation(); 34 | } 35 | 36 | internal class RefinedAbstraction : Abstraction 37 | { 38 | public override void Operation() 39 | { 40 | Implementor.Operation(); 41 | Console.WriteLine("Invoke in RefinedAbstraction"); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /StructurePattern/BridgePattern/README.md: -------------------------------------------------------------------------------- 1 | # 桥接模式 Bridge 2 | 3 | ## Intro 4 | 5 | > 桥接模式,将抽象部分与它的实现部分分离,使得它们都可以独立地变化。 6 | > 7 | > 这里说到抽象与它的实现分离指的是抽象类和它的派生类用来实现自己的对象 8 | 9 | 10 | 还有另外一种理解方式,一个类存在两个(或多个)独立变化的维度,我们通过组合的方式,让这两个(或多个)维度可以独立进行扩展。 11 | 12 | 通过组合关系来替代继承关系,避免继承层次的指数级爆炸。这种理解方式非常类似于,我们之前讲过的“组合优于继承”设计原则。 13 | 14 | ## Sample 15 | 16 | ``` csharp 17 | internal abstract class Implementor 18 | { 19 | public abstract void Operation(); 20 | } 21 | 22 | internal class ConcreteImplementorA : Implementor 23 | { 24 | public override void Operation() 25 | { 26 | Console.WriteLine("ImplementorA Operation"); 27 | } 28 | } 29 | 30 | internal class ConcreteImplementorB : Implementor 31 | { 32 | public override void Operation() 33 | { 34 | Console.WriteLine("ImplementorB Operation"); 35 | } 36 | } 37 | 38 | internal abstract class Abstraction 39 | { 40 | protected Implementor Implementor; 41 | 42 | public void SetImplementor(Implementor implementor) 43 | { 44 | Implementor = implementor; 45 | } 46 | 47 | public abstract void Operation(); 48 | } 49 | 50 | internal class RefinedAbstraction : Abstraction 51 | { 52 | public override void Operation() 53 | { 54 | Implementor.Operation(); 55 | Console.WriteLine("Invoke in RefinedAbstraction"); 56 | } 57 | } 58 | 59 | 60 | Abstraction ab = new RefinedAbstraction(); 61 | 62 | ab.SetImplementor(new ConcreteImplementorA()); 63 | ab.Operation(); 64 | 65 | ab.SetImplementor(new ConcreteImplementorB()); 66 | ab.Operation(); 67 | ``` 68 | 69 | ## More 70 | 71 | 更多设计模式及示例代码 [传送门](https://github.com/WeihanLi/DesignPatterns) 72 | -------------------------------------------------------------------------------- /StructurePattern/CompositePattern/Company.cs: -------------------------------------------------------------------------------- 1 | namespace CompositePattern; 2 | 3 | internal abstract class Company 4 | { 5 | protected string Name; 6 | 7 | protected Company(string name) => Name = name; 8 | 9 | public abstract void Add(Company company); 10 | 11 | public abstract void Remove(Company company); 12 | 13 | public virtual void Display(int depth) 14 | { 15 | Console.WriteLine($"{new string('-', depth)} {Name}"); 16 | } 17 | 18 | public abstract void LineOfDuty(); 19 | } 20 | 21 | internal class ConcreteCompany : Company 22 | { 23 | private readonly List _children = new(); 24 | 25 | public ConcreteCompany(string name) : base(name) 26 | { 27 | } 28 | 29 | public override void Add(Company company) 30 | { 31 | _children.Add(company); 32 | } 33 | 34 | public override void Remove(Company company) 35 | { 36 | _children.Remove(company); 37 | } 38 | 39 | public override void Display(int depth) 40 | { 41 | Console.WriteLine($"{new string('-', depth)} {Name}"); 42 | foreach (var company in _children) 43 | { 44 | company.Display(depth + 2); 45 | } 46 | } 47 | 48 | public override void LineOfDuty() 49 | { 50 | foreach (var company in _children) 51 | { 52 | company.LineOfDuty(); 53 | } 54 | } 55 | } 56 | 57 | internal class HrDepartment : Company 58 | { 59 | public HrDepartment(string name) : base(name) 60 | { 61 | } 62 | 63 | public override void Add(Company company) 64 | { 65 | throw new NotImplementedException(); 66 | } 67 | 68 | public override void Remove(Company company) 69 | { 70 | throw new NotImplementedException(); 71 | } 72 | 73 | public override void LineOfDuty() 74 | { 75 | Console.WriteLine($"{Name} Hr comes."); 76 | } 77 | } 78 | 79 | internal class FinanceDepartment : Company 80 | { 81 | public FinanceDepartment(string name) : base(name) 82 | { 83 | } 84 | 85 | public override void Add(Company company) 86 | { 87 | throw new NotImplementedException(); 88 | } 89 | 90 | public override void Remove(Company company) 91 | { 92 | throw new NotImplementedException(); 93 | } 94 | 95 | public override void LineOfDuty() 96 | { 97 | Console.WriteLine($"{Name} Finance comes"); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /StructurePattern/CompositePattern/CompositePattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /StructurePattern/CompositePattern/Program.cs: -------------------------------------------------------------------------------- 1 | #region Tree 2 | 3 | var root = new Composite("root"); 4 | root.Add(new Leaf("Leaf A")); 5 | root.Add(new Leaf("Leaf B")); 6 | 7 | var co = new Composite("CompositeA"); 8 | co.Add(new Leaf("Leaf X")); 9 | co.Add(new Leaf("Leaf Y")); 10 | var co1 = new Composite("CompositeA"); 11 | co1.Add(new Leaf("Leaf P")); 12 | co1.Add(new Leaf("Leaf Q")); 13 | 14 | co.Add(co1); 15 | root.Add(co); 16 | root.Display(0); 17 | 18 | #endregion Tree 19 | 20 | #region Company 21 | 22 | Company company = new ConcreteCompany("华隆总公司"); 23 | var huaDongCompany = new ConcreteCompany("华隆华东分公司"); 24 | var huaBeiCompany = new ConcreteCompany("华隆华北分公司"); 25 | company.Add(huaDongCompany); 26 | company.Add(huaBeiCompany); 27 | 28 | huaDongCompany.Add(new HrDepartment("华隆华东分公司Hr部门")); 29 | huaDongCompany.Add(new FinanceDepartment("华隆华东分公司财务部门")); 30 | 31 | huaBeiCompany.Add(new HrDepartment("华隆华北分公司Hr部门")); 32 | huaBeiCompany.Add(new FinanceDepartment("华隆华北分公司财务部门")); 33 | 34 | company.Display(0); 35 | company.LineOfDuty(); 36 | 37 | #endregion Company 38 | 39 | Console.ReadLine(); 40 | -------------------------------------------------------------------------------- /StructurePattern/CompositePattern/Prototype.cs: -------------------------------------------------------------------------------- 1 | namespace CompositePattern; 2 | 3 | internal abstract class Component 4 | { 5 | protected string Name; 6 | 7 | protected Component(string name) 8 | { 9 | Name = name; 10 | } 11 | 12 | public abstract void Add(Component c); 13 | 14 | public abstract void Remove(Component c); 15 | 16 | public abstract void Display(int depth); 17 | } 18 | 19 | internal class Leaf : Component 20 | { 21 | public Leaf(string name) : base(name) 22 | { 23 | } 24 | 25 | public override void Add(Component c) 26 | { 27 | throw new System.NotImplementedException(); 28 | } 29 | 30 | public override void Remove(Component c) 31 | { 32 | throw new System.NotImplementedException(); 33 | } 34 | 35 | public override void Display(int depth) 36 | { 37 | Console.WriteLine($"{new string('-', depth)} {Name}"); 38 | } 39 | } 40 | 41 | internal class Composite : Component 42 | { 43 | private readonly List _children = new(); 44 | 45 | public Composite(string name) : base(name) 46 | { 47 | } 48 | 49 | public override void Add(Component c) 50 | { 51 | _children.Add(c); 52 | } 53 | 54 | public override void Remove(Component c) 55 | { 56 | _children.Remove(c); 57 | } 58 | 59 | public override void Display(int depth) 60 | { 61 | Console.WriteLine($"{new string('-', depth)} {Name}"); 62 | foreach (var component in _children) 63 | { 64 | component.Display(depth + 2); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /StructurePattern/CompositePattern/README.md: -------------------------------------------------------------------------------- 1 | # 组合模式 Composite 2 | 3 | ## Intro 4 | 5 | > 组合模式,将对象组合成树形结构以表示 “部分-整体” 的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。 6 | 7 | ## 使用场景 8 | 9 | 当你发现需求中是体现部分与整体层次的结构时,以及你希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑用组合模式了。 10 | 11 | ## Sample 12 | 13 | ``` csharp 14 | public abstract class Component 15 | { 16 | protected string Name; 17 | 18 | protected Component(string name) 19 | { 20 | Name = name; 21 | } 22 | 23 | public abstract void Add(Component c); 24 | 25 | public abstract void Remove(Component c); 26 | 27 | public abstract void Display(int depth); 28 | } 29 | 30 | public class Leaf : Component 31 | { 32 | public Leaf(string name) : base(name) 33 | { 34 | } 35 | 36 | public override void Add(Component c) 37 | { 38 | throw new System.NotImplementedException(); 39 | } 40 | 41 | public override void Remove(Component c) 42 | { 43 | throw new System.NotImplementedException(); 44 | } 45 | 46 | public override void Display(int depth) 47 | { 48 | Console.WriteLine($"{new string('-', depth)} {Name}"); 49 | } 50 | } 51 | 52 | public class Composite : Component 53 | { 54 | private readonly List _children = new List(); 55 | 56 | public Composite(string name) : base(name) 57 | { 58 | } 59 | 60 | public override void Add(Component c) 61 | { 62 | _children.Add(c); 63 | } 64 | 65 | public override void Remove(Component c) 66 | { 67 | _children.Remove(c); 68 | } 69 | 70 | public override void Display(int depth) 71 | { 72 | Console.WriteLine($"{new string('-', depth)} {Name}"); 73 | foreach (var component in _children) 74 | { 75 | component.Display(depth + 2); 76 | } 77 | } 78 | } 79 | 80 | 81 | var root = new Composite("root"); 82 | root.Add(new Leaf("Leaf A")); 83 | root.Add(new Leaf("Leaf B")); 84 | 85 | var co = new Composite("CompositeA"); 86 | co.Add(new Leaf("Leaf X")); 87 | co.Add(new Leaf("Leaf Y")); 88 | var co1 = new Composite("CompositeA"); 89 | co1.Add(new Leaf("Leaf P")); 90 | co1.Add(new Leaf("Leaf Q")); 91 | 92 | co.Add(co1); 93 | root.Add(co); 94 | root.Display(0); 95 | ``` 96 | 97 | ## More 98 | 99 | 更多设计模式及示例代码 [传送门](https://github.com/WeihanLi/DesignPatterns) 100 | -------------------------------------------------------------------------------- /StructurePattern/DecoratorPattern/DecoratorPattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /StructurePattern/DecoratorPattern/Finery.cs: -------------------------------------------------------------------------------- 1 | namespace DecoratorPattern; 2 | 3 | internal class Person 4 | { 5 | protected readonly string Name; 6 | 7 | public Person() 8 | { 9 | } 10 | 11 | public Person(string name) 12 | { 13 | Name = name; 14 | } 15 | 16 | public virtual void Show() 17 | { 18 | Console.WriteLine($"装扮的{Name}"); 19 | } 20 | } 21 | 22 | internal class Finery : Person 23 | { 24 | protected Person Person; 25 | 26 | public void Decorate(Person person) 27 | { 28 | Person = person; 29 | } 30 | 31 | public override void Show() 32 | { 33 | Person?.Show(); 34 | } 35 | } 36 | 37 | internal class Tshirts : Finery 38 | { 39 | public override void Show() 40 | { 41 | Console.WriteLine("Tshirts"); 42 | base.Show(); 43 | } 44 | } 45 | 46 | internal class Pants : Finery 47 | { 48 | public override void Show() 49 | { 50 | Console.WriteLine("Pants"); 51 | base.Show(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /StructurePattern/DecoratorPattern/Program.cs: -------------------------------------------------------------------------------- 1 | #region Prototype 2 | 3 | Component component = new ConcreteComponent(); 4 | Decorator decorator = new DecoratorA(); 5 | decorator.SetComponent(component); 6 | decorator.Operation(); 7 | 8 | Decorator decorator1 = new DecoratorB(); 9 | decorator1.SetComponent(decorator); 10 | decorator1.Operation(); 11 | 12 | #endregion Prototype 13 | 14 | var person = new Person("小明"); 15 | 16 | Console.WriteLine("\n第一种装扮:\n"); 17 | var pants = new Pants(); 18 | pants.Decorate(person); 19 | pants.Show(); 20 | 21 | Console.WriteLine("\n第二种装扮:\n"); 22 | var shirts = new Tshirts(); 23 | shirts.Decorate(pants); 24 | shirts.Show(); 25 | 26 | Console.ReadLine(); 27 | -------------------------------------------------------------------------------- /StructurePattern/DecoratorPattern/Prototype.cs: -------------------------------------------------------------------------------- 1 | namespace DecoratorPattern; 2 | 3 | internal abstract class Component 4 | { 5 | public abstract void Operation(); 6 | } 7 | 8 | internal class ConcreteComponent : Component 9 | { 10 | public override void Operation() 11 | { 12 | Console.WriteLine("Operation executed in ConcreteComponent"); 13 | } 14 | } 15 | 16 | internal abstract class Decorator : Component 17 | { 18 | protected Component Component; 19 | 20 | public void SetComponent(Component component) 21 | { 22 | Component = component; 23 | } 24 | 25 | public override void Operation() 26 | { 27 | Component?.Operation(); 28 | } 29 | } 30 | 31 | internal class DecoratorA : Decorator 32 | { 33 | private string _state; 34 | 35 | public override void Operation() 36 | { 37 | base.Operation(); 38 | _state = "executed"; 39 | Console.WriteLine($"operation in DecoratorA, state:{_state}"); 40 | } 41 | } 42 | 43 | internal class DecoratorB : Decorator 44 | { 45 | public override void Operation() 46 | { 47 | base.Operation(); 48 | Console.WriteLine("operation in DecoratorB"); 49 | AddBehavior(); 50 | } 51 | 52 | private void AddBehavior() 53 | { 54 | Console.WriteLine("another behavior"); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /StructurePattern/DecoratorPattern/README.md: -------------------------------------------------------------------------------- 1 | # 装饰模式 Decorator 2 | 3 | ## Intro 4 | 5 | > 装饰模式,动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活 6 | 7 | ## 使用场景 8 | 9 | 装饰模式是为已有功能动态地添加更多功能的一种方式 10 | 11 | 当系统需要新功能的时候,是向旧的类中添加新的代码,这些新加的代码通常装饰了原有类的核心职责或主要行为,但是往往会在主类中加入新的字段/方法/逻辑,从而增加了主类的复杂度, 12 | 而这些新加入的东西仅仅是为了满足一些只在某种特定情况下才会执行的特殊行为的需要 13 | 14 | 装饰模式提供了一个很好的方案,它把每个要装饰的功能放在单独的类中,并让这个类包装它要装饰的对象, 15 | 当需要执行特殊行为时,就可以在运行时根据需要有选择地、按顺序地使用装饰功能包装对象了。 16 | 17 | 装饰模式的优点时把类中的装饰功能从类中搬移去除,这样可以简化原有的类,这样做就有效地把类的核心职责和装饰功能区分开了,而且可以去除相关类中重复的装饰逻辑。 18 | 19 | ## Prototype 20 | 21 | - Component 定义一个对象的抽象,可以给这些对象动态的添加职责 22 | - ConcreteComponent 定义一个具体的对象,也可以给这个对象添加一些职责 23 | - Decorator 装饰抽象类,继承了 Component,从外类来扩展 Component 类的功能,但对于 Component 来说是无需知道 Decorator 的存在的 24 | - ConcreteDecorator 具体的装饰对象,起到给 Component 添加职责的功能 25 | 26 | ``` csharp 27 | internal abstract class Component 28 | { 29 | public abstract void Operation(); 30 | } 31 | internal class ConcreteComponent : Component 32 | { 33 | public override void Operation() 34 | { 35 | Console.WriteLine("Operation executed in ConcreteComponent"); 36 | } 37 | } 38 | 39 | internal abstract class Decorator : Component 40 | { 41 | protected Component Component; 42 | 43 | public void SetComponent(Component component) 44 | { 45 | Component = component; 46 | } 47 | 48 | public override void Operation() 49 | { 50 | Component?.Operation(); 51 | } 52 | } 53 | internal class DecoratorA : Decorator 54 | { 55 | private string _state; 56 | 57 | public override void Operation() 58 | { 59 | base.Operation(); 60 | _state = "executed"; 61 | Console.WriteLine($"operation in DecoratorA, state:{_state}"); 62 | } 63 | } 64 | internal class DecoratorB : Decorator 65 | { 66 | public override void Operation() 67 | { 68 | base.Operation(); 69 | Console.WriteLine("operation in DecoratorB"); 70 | AddBehavior(); 71 | } 72 | 73 | private void AddBehavior() 74 | { 75 | Console.WriteLine("another behavior"); 76 | } 77 | } 78 | ``` 79 | 80 | ## More 81 | 82 | 更多设计模式及示例代码 [传送门](https://github.com/WeihanLi/DesignPatterns) 83 | -------------------------------------------------------------------------------- /StructurePattern/FacadePattern/FacadePattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /StructurePattern/FacadePattern/Program.cs: -------------------------------------------------------------------------------- 1 | var facade = new Facade(); 2 | facade.MethodA(); 3 | facade.MethodB(); 4 | 5 | Console.ReadLine(); 6 | -------------------------------------------------------------------------------- /StructurePattern/FacadePattern/Prototype.cs: -------------------------------------------------------------------------------- 1 | namespace FacadePattern; 2 | 3 | public class SubSystem1 4 | { 5 | public void MethodA() 6 | { 7 | Console.WriteLine("MethodA in SubSystem1"); 8 | } 9 | 10 | public void MethodB() 11 | { 12 | Console.WriteLine("MethodB in SubSystem1"); 13 | } 14 | } 15 | 16 | public class SubSystem2 17 | { 18 | public void MethodA() 19 | { 20 | Console.WriteLine("MethodA in SubSystem2"); 21 | } 22 | 23 | public void MethodB() 24 | { 25 | Console.WriteLine("MethodB in SubSystem2"); 26 | } 27 | } 28 | 29 | public class SubSystem3 30 | { 31 | public void MethodA() 32 | { 33 | Console.WriteLine("MethodA in SubSystem3"); 34 | } 35 | 36 | public void MethodB() 37 | { 38 | Console.WriteLine("MethodB in SubSystem3"); 39 | } 40 | } 41 | 42 | public class Facade 43 | { 44 | private readonly SubSystem1 _subSystem1 = new(); 45 | private readonly SubSystem2 _subSystem2 = new(); 46 | private readonly SubSystem3 _subSystem3 = new(); 47 | 48 | public void MethodA() 49 | { 50 | _subSystem1.MethodA(); 51 | _subSystem2.MethodA(); 52 | _subSystem3.MethodA(); 53 | Console.WriteLine(); 54 | } 55 | 56 | public void MethodB() 57 | { 58 | _subSystem1.MethodB(); 59 | _subSystem2.MethodB(); 60 | _subSystem3.MethodB(); 61 | Console.WriteLine(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /StructurePattern/FacadePattern/README.md: -------------------------------------------------------------------------------- 1 | # 外观模式(门面模式) Facade 2 | 3 | ## Intro 4 | 5 | > 外观模式(Facade),为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用 6 | 7 | ## Prototype 8 | 9 | - Facade: 外观类,知道哪些子系统类负责处理请求,将请求代理给对应的子系统对象 10 | - SubSystem Classes,实现子系统中的功能,处理 Facade 指派的任务,和 Facade 没有关联关系,没有继承,也不会引用 Facade 11 | 12 | ``` csharp 13 | public class SubSystem1 14 | { 15 | public void MethodA() 16 | { 17 | Console.WriteLine("MethodA in SubSystem1"); 18 | } 19 | 20 | public void MethodB() 21 | { 22 | Console.WriteLine("MethodB in SubSystem1"); 23 | } 24 | } 25 | public class SubSystem2 26 | { 27 | public void MethodA() 28 | { 29 | Console.WriteLine("MethodA in SubSystem2"); 30 | } 31 | 32 | public void MethodB() 33 | { 34 | Console.WriteLine("MethodB in SubSystem2"); 35 | } 36 | } 37 | public class SubSystem3 38 | { 39 | public void MethodA() 40 | { 41 | Console.WriteLine("MethodA in SubSystem3"); 42 | } 43 | 44 | public void MethodB() 45 | { 46 | Console.WriteLine("MethodB in SubSystem3"); 47 | } 48 | } 49 | 50 | public class Facade 51 | { 52 | private readonly SubSystem1 _subSystem1 = new SubSystem1(); 53 | private readonly SubSystem2 _subSystem2 = new SubSystem2(); 54 | private readonly SubSystem3 _subSystem3 = new SubSystem3(); 55 | 56 | public void MethodA() 57 | { 58 | _subSystem1.MethodA(); 59 | _subSystem2.MethodA(); 60 | _subSystem3.MethodA(); 61 | Console.WriteLine(); 62 | } 63 | 64 | public void MethodB() 65 | { 66 | _subSystem1.MethodB(); 67 | _subSystem2.MethodB(); 68 | _subSystem3.MethodB(); 69 | Console.WriteLine(); 70 | } 71 | } 72 | 73 | var facade = new Facade(); 74 | facade.MethodA(); 75 | facade.MethodB(); 76 | ``` 77 | 78 | ## More 79 | 80 | 更多设计模式及示例代码 [传送门](https://github.com/WeihanLi/DesignPatterns) 81 | -------------------------------------------------------------------------------- /StructurePattern/FlyweightPattern/FlyweightPattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /StructurePattern/FlyweightPattern/Program.cs: -------------------------------------------------------------------------------- 1 | var counter = 20; 2 | 3 | var factory = new FlyWeightFactory(); 4 | factory.GetFlyweight("X").Operation(counter--); 5 | factory.GetFlyweight("Y").Operation(counter--); 6 | factory.GetFlyweight("X").Operation(counter--); 7 | factory.GetFlyweight("X").Operation(counter--); 8 | 9 | new UnsharedFlyweight().Operation(counter--); 10 | 11 | Console.WriteLine(counter); 12 | Console.ReadLine(); 13 | -------------------------------------------------------------------------------- /StructurePattern/FlyweightPattern/Prototype.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Concurrent; 2 | 3 | namespace FlyweightPattern; 4 | 5 | internal abstract class Flyweight 6 | { 7 | public abstract void Operation(int extrinsicstate); 8 | } 9 | 10 | internal class ConcreteFlyweight : Flyweight 11 | { 12 | public override void Operation(int extrinsicstate) 13 | { 14 | Console.WriteLine("operation in ConcreteFlyweight"); 15 | } 16 | } 17 | 18 | internal class UnsharedFlyweight : Flyweight 19 | { 20 | public override void Operation(int extrinsicstate) 21 | { 22 | Console.WriteLine("operation in UnsharedFlyweight"); 23 | } 24 | } 25 | 26 | internal class FlyWeightFactory 27 | { 28 | private readonly ConcurrentDictionary _flyweights = new(); 29 | 30 | public Flyweight GetFlyweight(string name) => _flyweights.GetOrAdd(name, n => new ConcreteFlyweight()); 31 | } 32 | -------------------------------------------------------------------------------- /StructurePattern/FlyweightPattern/README.md: -------------------------------------------------------------------------------- 1 | # 享元模式 Flyweight 2 | 3 | ## Intro 4 | 5 | 享元是指一个可复用的对象,通过复用这个享元来减少应用中的内存分配。 6 | 7 | 享元模式是为了减少内存占用,尽可能复用已有对象的设计模式,一般来说会把这个可复用的对象放到一个外部的数据结构中,当需要使用到的时候传给享元。 8 | 9 | ## Sample 10 | 11 | ``` csharp 12 | public abstract class Flyweight 13 | { 14 | public abstract void Operation(int extrinsicstate); 15 | } 16 | 17 | public class ConcreteFlyweight : Flyweight 18 | { 19 | public override void Operation(int extrinsicstate) 20 | { 21 | Console.WriteLine("operation in ConcreteFlyweight"); 22 | } 23 | } 24 | 25 | public class UnsharedFlyweight : Flyweight 26 | { 27 | public override void Operation(int extrinsicstate) 28 | { 29 | Console.WriteLine("operation in UnsharedFlyweight"); 30 | } 31 | } 32 | 33 | public class FlyWeightFactory 34 | { 35 | private readonly ConcurrentDictionary _flyweights = new ConcurrentDictionary(); 36 | 37 | public Flyweight GetFlyweight(string name) => _flyweights.GetOrAdd(name, n => new ConcreteFlyweight()); 38 | } 39 | 40 | public class Program 41 | { 42 | public static void Main(string[] args) 43 | { 44 | var counter = 20; 45 | 46 | var factory = new FlyWeightFactory(); 47 | factory.GetFlyweight("X").Operation(counter--); 48 | factory.GetFlyweight("Y").Operation(counter--); 49 | factory.GetFlyweight("X").Operation(counter--); 50 | 51 | new UnsharedFlyweight().Operation(counter--); 52 | 53 | factory.GetFlyweight("X").Operation(counter--); 54 | 55 | Console.WriteLine(counter); 56 | Console.ReadLine(); 57 | } 58 | } 59 | ``` 60 | 61 | ## More 62 | 63 | 更多设计模式及示例代码 [传送门](https://github.com/WeihanLi/DesignPatterns) 64 | -------------------------------------------------------------------------------- /StructurePattern/ProxyPattern/Program.cs: -------------------------------------------------------------------------------- 1 | Subject proxy = new Proxy(new RealSubject()); 2 | proxy.Request(); 3 | 4 | proxy = new Proxy0(); 5 | proxy.Request(); 6 | 7 | Console.ReadLine(); 8 | -------------------------------------------------------------------------------- /StructurePattern/ProxyPattern/Prototype.cs: -------------------------------------------------------------------------------- 1 | namespace ProxyPattern; 2 | 3 | internal abstract class Subject 4 | { 5 | public abstract void Request(); 6 | } 7 | 8 | internal class RealSubject : Subject 9 | { 10 | public override void Request() 11 | { 12 | Console.WriteLine("request from real subject"); 13 | } 14 | } 15 | 16 | internal class Proxy0 : Subject 17 | { 18 | private Subject _subject; 19 | 20 | public override void Request() 21 | { 22 | if (null == _subject) 23 | { 24 | _subject = new RealSubject(); 25 | } 26 | _subject.Request(); 27 | } 28 | } 29 | 30 | internal class Proxy : Subject 31 | { 32 | private readonly Subject _subject; 33 | 34 | public Proxy(Subject subject) => _subject = subject; 35 | 36 | public override void Request() 37 | { 38 | _subject.Request(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /StructurePattern/ProxyPattern/ProxyPattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /StructurePattern/ProxyPattern/README.md: -------------------------------------------------------------------------------- 1 | # 代理模式 Proxy 2 | 3 | ## Intro 4 | 5 | 代理模式,给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。 6 | 7 | 在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。 8 | 9 | 比如生活中常见的中介,VPN,网络代理等 10 | 11 | 利用代理模式,我们可以对实际的操作做一些额外的逻辑,比如加一些异常捕捉,缓存,日志记录或者耗时统计等等,基于动态代理的 AOP 模式也是代理模式的实际应用。 12 | 13 | ## Prototype 14 | 15 | ``` csharp 16 | public abstract class Subject 17 | { 18 | public abstract void Request(); 19 | } 20 | 21 | public class RealSubject : Subject 22 | { 23 | public override void Request() 24 | { 25 | Console.WriteLine("request from real subject"); 26 | } 27 | } 28 | 29 | public class Proxy0 : Subject 30 | { 31 | private Subject _subject; 32 | 33 | public override void Request() 34 | { 35 | if (null == _subject) 36 | { 37 | _subject = new RealSubject(); 38 | } 39 | _subject.Request(); 40 | } 41 | } 42 | 43 | public class Proxy : Subject 44 | { 45 | private readonly Subject _subject; 46 | 47 | public Proxy(Subject subject) => _subject = subject; 48 | 49 | public override void Request() 50 | { 51 | _subject.Request(); 52 | } 53 | } 54 | ``` 55 | 56 | ## More 57 | 58 | 更多设计模式及示例代码 [传送门](https://github.com/WeihanLi/DesignPatterns) 59 | -------------------------------------------------------------------------------- /StructurePattern/README.md: -------------------------------------------------------------------------------- 1 | # 结构型设计模式总结 2 | 3 | ## Intro 4 | 5 | 结构型设计模式主要总结了一些类或对象组合在一起的经典结构,这些经典的结构可以解决一些特定应用场景的问题。 6 | 7 | 结构型模式包括:代理模式、桥接模式、装饰器模式、适配器模式、外观(门面)模式、组合模式、享元模式。 8 | 9 | ## 总结 10 | 11 | ### 适配器模式(Adapter) 12 | 13 | 适配一下不兼容的接口,work together 14 | 15 | ### 桥接模式(Bridge) 16 | 17 | 将抽象部分与它的实现部分分离,使得它们都可以独立地变化。 18 | 19 | ### 组合模式(Composite) 20 | 21 | 将对象组合成树形结构以表示 “部分-整体” 的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性 22 | 23 | ### 装饰模式(Decorator) 24 | 25 | 动态地给一个对象添加一些额外的职责和功能 26 | 27 | ### 外观/门面模式(Facade) 28 | 29 | 定义一组高层接口让子系统更易用 30 | 31 | ### 享元模式(Flyweight) 32 | 33 | 复用对象,减少内存占用 34 | 35 | ### 代理模式(Proxy) 36 | 37 | 由代理对象控制对原对象的引用 38 | 39 | ## More 40 | 41 | 可以描述成树形结构的父子关系用组合 42 | 43 | 分离抽象和实现独立变化用桥接 44 | 45 | 增加额外功能职责用装饰 46 | 47 | 控制访问用代理 48 | 49 | 复用对象用享元 50 | 51 | 封装底层子系统接口用外观、门面 52 | 53 | 兼容老系统接口用适配器 54 | 55 | ## Reference 56 | 57 | - 58 | - [适配器模式](./AdapterPattern) 59 | - [桥接模式](./BridgePattern) 60 | - [组合模式](./CompositePattern) 61 | - [装饰模式](./DecoratorPattern) 62 | - [外观/门面模式](./FacadePattern) 63 | - [享元模式](./FlyweightPattern) 64 | - [代理模式](./ProxyPattern) 65 | -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | trigger: 2 | - '*' 3 | 4 | pool: 5 | vmImage: 'ubuntu-latest' 6 | 7 | variables: 8 | buildConfiguration: 'Release' 9 | 10 | steps: 11 | - task: UseDotNet@2 12 | displayName: 'Use .NET sdk' 13 | inputs: 14 | packageType: sdk 15 | version: 8.0.x 16 | 17 | - script: dotnet build --configuration $(buildConfiguration) 18 | displayName: 'dotnet build $(buildConfiguration)' 19 | -------------------------------------------------------------------------------- /大话设计模式.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeihanLi/DesignPatterns/01f316a78881dc162dcd3b2c6a71f55ba661d259/大话设计模式.pdf --------------------------------------------------------------------------------