├── .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