├── .gitattributes ├── .gitignore ├── CommandPattern ├── CommandPattern.csproj ├── Program.cs └── RemoteControl │ ├── Commands │ ├── CeilingFanCommands │ │ ├── CeilingFan.cs │ │ ├── CeilingFanOffCommand.cs │ │ └── CeilingFanOnCommand.cs │ ├── GarageDoorCommands │ │ ├── GarageDoor.cs │ │ ├── GarageDoorCloseCommand.cs │ │ └── GarageDoorOpenCommand.cs │ ├── ICommand.cs │ ├── LightCommands │ │ ├── Light.cs │ │ ├── LightOffCommand.cs │ │ └── LightOnCommand.cs │ ├── NoCommand.cs │ └── Stereo │ │ ├── Stereo.cs │ │ ├── StereoOffCommand.cs │ │ └── StereoOnWithCDCommand.cs │ ├── RemoteControl.cs │ ├── RemoteLoader.cs │ ├── SimpleRemoteControl.cs │ └── SimpleRemoteControlTest.cs ├── CompositePattern ├── CompositePattern.csproj ├── MenuComponent │ ├── IMenuComponent.cs │ ├── Menu.cs │ └── MenuItem.cs ├── Program.cs └── Waitress │ └── Waitress.cs ├── CompoundPattern ├── CompoundPattern.csproj ├── CounterDecorator │ └── QuackCounter.cs ├── DuckFactory │ ├── AbstractDuckFactory.cs │ ├── CountingDuckFactory.cs │ └── DuckFactory.cs ├── DuckSimulator.cs ├── Flock │ └── Flock.cs ├── IQuackable.cs ├── Observable │ ├── IObserver.cs │ ├── IQuackObservable.cs │ ├── QuackObservable.cs │ └── Quackologist.cs ├── Program.cs ├── SomeDucks │ ├── DuckCall.cs │ ├── MallardDuck.cs │ ├── RedheadDuck.cs │ └── RubberDuck.cs └── SomeGeese │ ├── Goose.cs │ └── GooseAdapter.cs ├── DecoratorPattern ├── Coffee │ ├── Beverages │ │ ├── Beverage.cs │ │ ├── DarkRoast.cs │ │ ├── Decaf.cs │ │ ├── Espresso.cs │ │ └── HouseBlend.cs │ ├── Condiments │ │ ├── CondimentDecorator.cs │ │ ├── Milk.cs │ │ ├── Mocha.cs │ │ ├── Soy.cs │ │ └── Whip.cs │ └── Sizes │ │ ├── Grande.cs │ │ ├── SizeDecorator.cs │ │ ├── Tall.cs │ │ └── Venti.cs ├── DecoratorPattern.csproj └── Program.cs ├── FactoryPattern ├── FactoryPattern.csproj ├── PizzaIngredient │ ├── ChicagoPizzaIngredientFactory.cs │ ├── IPizzaIngredientFactory.cs │ ├── Ingredients │ │ ├── Cheese.cs │ │ ├── Clams.cs │ │ ├── Dough.cs │ │ ├── Pepperoni.cs │ │ ├── Sauce.cs │ │ └── Veggie.cs │ └── NYPizzaIngredientFactory.cs ├── PizzaProduct │ ├── CheesePizza.cs │ ├── ClamPizza.cs │ ├── PepperoniPizza.cs │ ├── Pizza.cs │ ├── PizzaType.cs │ └── VeggiePizza.cs ├── PizzaStore │ ├── ChicagoStylePizzaStore.cs │ ├── NYStylePizzaStore.cs │ └── PizzaStore.cs └── Program.cs ├── HeadFirstDesignPattern.sln ├── HeadFirstDesignPattern.sln.DotSettings ├── IteratorPattern ├── Iterator │ ├── DinnerMenuIterator.cs │ ├── IIterator.cs │ └── PancakeHouseMenuIterator.cs ├── IteratorPattern.csproj ├── Menu │ ├── DinerMenu.cs │ ├── IMenu.cs │ ├── MenuItem.cs │ └── PancakeHouseMenu.cs ├── Program.cs └── Waitress │ └── Waitress.cs ├── LICENSE.md ├── ObserverPattern ├── CurrentConditionDisplay.cs ├── ForecastDisplay.cs ├── IDisplayElement.cs ├── IObserver.cs ├── ISubject.cs ├── ObserverPattern.csproj ├── Program.cs ├── StatisticsDisplay.cs └── Weatherdata.cs ├── ProxyPattern ├── Castle │ └── CastleDynamicProxy.cs ├── Program.cs ├── ProxyPattern.csproj └── SimpleProxyPattern │ └── SimpleImplementation.cs ├── README.md ├── SingletonPattern ├── ChocolateBoiler.cs ├── Program.cs └── SingletonPattern.csproj ├── StatePattern ├── GumballMachines │ └── GumballMachine.cs ├── Program.cs ├── StatePattern.csproj └── States │ ├── HasQuarterState.cs │ ├── IState.cs │ ├── NoQuarterState.cs │ ├── SoldOutState.cs │ ├── SoldState.cs │ └── WinnerState.cs └── StrategyPattern ├── Duck ├── Duck.cs ├── Fly.cs ├── MallardDuck.cs ├── ModelDuck.cs └── Quack.cs ├── Program.cs └── StrategyPattern.csproj /.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 | -------------------------------------------------------------------------------- /.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 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Aa][Rr][Mm]/ 27 | [Aa][Rr][Mm]64/ 28 | bld/ 29 | [Bb]in/ 30 | [Oo]bj/ 31 | [Ll]og/ 32 | 33 | # Visual Studio 2015/2017 cache/options directory 34 | .vs/ 35 | # Uncomment if you have tasks that create the project's static files in wwwroot 36 | #wwwroot/ 37 | 38 | # Visual Studio 2017 auto generated files 39 | Generated\ Files/ 40 | 41 | # MSTest test Results 42 | [Tt]est[Rr]esult*/ 43 | [Bb]uild[Ll]og.* 44 | 45 | # NUnit 46 | *.VisualState.xml 47 | TestResult.xml 48 | nunit-*.xml 49 | 50 | # Build Results of an ATL Project 51 | [Dd]ebugPS/ 52 | [Rr]eleasePS/ 53 | dlldata.c 54 | 55 | # Benchmark Results 56 | BenchmarkDotNet.Artifacts/ 57 | 58 | # .NET Core 59 | project.lock.json 60 | project.fragment.lock.json 61 | artifacts/ 62 | 63 | # StyleCop 64 | StyleCopReport.xml 65 | 66 | # Files built by Visual Studio 67 | *_i.c 68 | *_p.c 69 | *_h.h 70 | *.ilk 71 | *.meta 72 | *.obj 73 | *.iobj 74 | *.pch 75 | *.pdb 76 | *.ipdb 77 | *.pgc 78 | *.pgd 79 | *.rsp 80 | *.sbr 81 | *.tlb 82 | *.tli 83 | *.tlh 84 | *.tmp 85 | *.tmp_proj 86 | *_wpftmp.csproj 87 | *.log 88 | *.vspscc 89 | *.vssscc 90 | .builds 91 | *.pidb 92 | *.svclog 93 | *.scc 94 | 95 | # Chutzpah Test files 96 | _Chutzpah* 97 | 98 | # Visual C++ cache files 99 | ipch/ 100 | *.aps 101 | *.ncb 102 | *.opendb 103 | *.opensdf 104 | *.sdf 105 | *.cachefile 106 | *.VC.db 107 | *.VC.VC.opendb 108 | 109 | # Visual Studio profiler 110 | *.psess 111 | *.vsp 112 | *.vspx 113 | *.sap 114 | 115 | # Visual Studio Trace Files 116 | *.e2e 117 | 118 | # TFS 2012 Local Workspace 119 | $tf/ 120 | 121 | # Guidance Automation Toolkit 122 | *.gpState 123 | 124 | # ReSharper is a .NET coding add-in 125 | _ReSharper*/ 126 | *.[Rr]e[Ss]harper 127 | *.DotSettings.user 128 | 129 | # JustCode is a .NET coding add-in 130 | .JustCode 131 | 132 | # TeamCity is a build add-in 133 | _TeamCity* 134 | 135 | # DotCover is a Code Coverage Tool 136 | *.dotCover 137 | 138 | # AxoCover is a Code Coverage Tool 139 | .axoCover/* 140 | !.axoCover/settings.json 141 | 142 | # Visual Studio code coverage results 143 | *.coverage 144 | *.coveragexml 145 | 146 | # NCrunch 147 | _NCrunch_* 148 | .*crunch*.local.xml 149 | nCrunchTemp_* 150 | 151 | # MightyMoose 152 | *.mm.* 153 | AutoTest.Net/ 154 | 155 | # Web workbench (sass) 156 | .sass-cache/ 157 | 158 | # Installshield output folder 159 | [Ee]xpress/ 160 | 161 | # DocProject is a documentation generator add-in 162 | DocProject/buildhelp/ 163 | DocProject/Help/*.HxT 164 | DocProject/Help/*.HxC 165 | DocProject/Help/*.hhc 166 | DocProject/Help/*.hhk 167 | DocProject/Help/*.hhp 168 | DocProject/Help/Html2 169 | DocProject/Help/html 170 | 171 | # Click-Once directory 172 | publish/ 173 | 174 | # Publish Web Output 175 | *.[Pp]ublish.xml 176 | *.azurePubxml 177 | # Note: Comment the next line if you want to checkin your web deploy settings, 178 | # but database connection strings (with potential passwords) will be unencrypted 179 | *.pubxml 180 | *.publishproj 181 | 182 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 183 | # checkin your Azure Web App publish settings, but sensitive information contained 184 | # in these scripts will be unencrypted 185 | PublishScripts/ 186 | 187 | # NuGet Packages 188 | *.nupkg 189 | # NuGet Symbol Packages 190 | *.snupkg 191 | # The packages folder can be ignored because of Package Restore 192 | **/[Pp]ackages/* 193 | # except build/, which is used as an MSBuild target. 194 | !**/[Pp]ackages/build/ 195 | # Uncomment if necessary however generally it will be regenerated when needed 196 | #!**/[Pp]ackages/repositories.config 197 | # NuGet v3's project.json files produces more ignorable files 198 | *.nuget.props 199 | *.nuget.targets 200 | 201 | # Microsoft Azure Build Output 202 | csx/ 203 | *.build.csdef 204 | 205 | # Microsoft Azure Emulator 206 | ecf/ 207 | rcf/ 208 | 209 | # Windows Store app package directories and files 210 | AppPackages/ 211 | BundleArtifacts/ 212 | Package.StoreAssociation.xml 213 | _pkginfo.txt 214 | *.appx 215 | *.appxbundle 216 | *.appxupload 217 | 218 | # Visual Studio cache files 219 | # files ending in .cache can be ignored 220 | *.[Cc]ache 221 | # but keep track of directories ending in .cache 222 | !?*.[Cc]ache/ 223 | 224 | # Others 225 | ClientBin/ 226 | ~$* 227 | *~ 228 | *.dbmdl 229 | *.dbproj.schemaview 230 | *.jfm 231 | *.pfx 232 | *.publishsettings 233 | orleans.codegen.cs 234 | 235 | # Including strong name files can present a security risk 236 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 237 | #*.snk 238 | 239 | # Since there are multiple workflows, uncomment next line to ignore bower_components 240 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 241 | #bower_components/ 242 | 243 | # RIA/Silverlight projects 244 | Generated_Code/ 245 | 246 | # Backup & report files from converting an old project file 247 | # to a newer Visual Studio version. Backup files are not needed, 248 | # because we have git ;-) 249 | _UpgradeReport_Files/ 250 | Backup*/ 251 | UpgradeLog*.XML 252 | UpgradeLog*.htm 253 | ServiceFabricBackup/ 254 | *.rptproj.bak 255 | 256 | # SQL Server files 257 | *.mdf 258 | *.ldf 259 | *.ndf 260 | 261 | # Business Intelligence projects 262 | *.rdl.data 263 | *.bim.layout 264 | *.bim_*.settings 265 | *.rptproj.rsuser 266 | *- [Bb]ackup.rdl 267 | *- [Bb]ackup ([0-9]).rdl 268 | *- [Bb]ackup ([0-9][0-9]).rdl 269 | 270 | # Microsoft Fakes 271 | FakesAssemblies/ 272 | 273 | # GhostDoc plugin setting file 274 | *.GhostDoc.xml 275 | 276 | # Node.js Tools for Visual Studio 277 | .ntvs_analysis.dat 278 | node_modules/ 279 | 280 | # Visual Studio 6 build log 281 | *.plg 282 | 283 | # Visual Studio 6 workspace options file 284 | *.opt 285 | 286 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 287 | *.vbw 288 | 289 | # Visual Studio LightSwitch build output 290 | **/*.HTMLClient/GeneratedArtifacts 291 | **/*.DesktopClient/GeneratedArtifacts 292 | **/*.DesktopClient/ModelManifest.xml 293 | **/*.Server/GeneratedArtifacts 294 | **/*.Server/ModelManifest.xml 295 | _Pvt_Extensions 296 | 297 | # Paket dependency manager 298 | .paket/paket.exe 299 | paket-files/ 300 | 301 | # FAKE - F# Make 302 | .fake/ 303 | 304 | # CodeRush personal settings 305 | .cr/personal 306 | 307 | # Python Tools for Visual Studio (PTVS) 308 | __pycache__/ 309 | *.pyc 310 | 311 | # Cake - Uncomment if you are using it 312 | # tools/** 313 | # !tools/packages.config 314 | 315 | # Tabs Studio 316 | *.tss 317 | 318 | # Telerik's JustMock configuration file 319 | *.jmconfig 320 | 321 | # BizTalk build output 322 | *.btp.cs 323 | *.btm.cs 324 | *.odx.cs 325 | *.xsd.cs 326 | 327 | # OpenCover UI analysis results 328 | OpenCover/ 329 | 330 | # Azure Stream Analytics local run output 331 | ASALocalRun/ 332 | 333 | # MSBuild Binary and Structured Log 334 | *.binlog 335 | 336 | # NVidia Nsight GPU debugger configuration file 337 | *.nvuser 338 | 339 | # MFractors (Xamarin productivity tool) working folder 340 | .mfractor/ 341 | 342 | # Local History for Visual Studio 343 | .localhistory/ 344 | 345 | # BeatPulse healthcheck temp database 346 | healthchecksdb 347 | 348 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 349 | MigrationBackup/ 350 | -------------------------------------------------------------------------------- /CommandPattern/CommandPattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /CommandPattern/Program.cs: -------------------------------------------------------------------------------- 1 | using CommandPattern.RemoteControl; 2 | 3 | SimpleRemoteControlTest.Test(); 4 | 5 | RemoteLoader.Test(); 6 | Console.ReadKey(); -------------------------------------------------------------------------------- /CommandPattern/RemoteControl/Commands/CeilingFanCommands/CeilingFan.cs: -------------------------------------------------------------------------------- 1 | namespace CommandPattern.RemoteControl.Commands.CeilingFanCommands; 2 | 3 | public class CeilingFan(string name = "") 4 | { 5 | public void On() 6 | { 7 | Console.WriteLine($"{name} Fan is On."); 8 | } 9 | 10 | public void Off() 11 | { 12 | Console.WriteLine($"{name} Fan is Off"); 13 | } 14 | } -------------------------------------------------------------------------------- /CommandPattern/RemoteControl/Commands/CeilingFanCommands/CeilingFanOffCommand.cs: -------------------------------------------------------------------------------- 1 | namespace CommandPattern.RemoteControl.Commands.CeilingFanCommands; 2 | 3 | public class CeilingFanOffCommand(CeilingFan ceilingFan) : ICommand 4 | { 5 | public void Execute() 6 | { 7 | ceilingFan.Off(); 8 | } 9 | 10 | public void Undo() 11 | { 12 | ceilingFan.On(); 13 | } 14 | } -------------------------------------------------------------------------------- /CommandPattern/RemoteControl/Commands/CeilingFanCommands/CeilingFanOnCommand.cs: -------------------------------------------------------------------------------- 1 | namespace CommandPattern.RemoteControl.Commands.CeilingFanCommands; 2 | 3 | public class CeilingFanOnCommand(CeilingFan ceilingFan) : ICommand 4 | { 5 | public void Execute() 6 | { 7 | ceilingFan.On(); 8 | } 9 | 10 | public void Undo() 11 | { 12 | ceilingFan.Off(); 13 | } 14 | } -------------------------------------------------------------------------------- /CommandPattern/RemoteControl/Commands/GarageDoorCommands/GarageDoor.cs: -------------------------------------------------------------------------------- 1 | namespace CommandPattern.RemoteControl.Commands.GarageDoorCommands; 2 | 3 | public class GarageDoor 4 | { 5 | public void Open() 6 | { 7 | Console.WriteLine("Garage Door is opened."); 8 | } 9 | 10 | public void Close() 11 | { 12 | Console.WriteLine("Garage Door is closed."); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /CommandPattern/RemoteControl/Commands/GarageDoorCommands/GarageDoorCloseCommand.cs: -------------------------------------------------------------------------------- 1 | namespace CommandPattern.RemoteControl.Commands.GarageDoorCommands; 2 | 3 | public class GarageDoorCloseCommand(GarageDoor garageDoor) : ICommand 4 | { 5 | public void Execute() 6 | { 7 | garageDoor.Close(); 8 | } 9 | 10 | public void Undo() 11 | { 12 | garageDoor.Open(); 13 | } 14 | } -------------------------------------------------------------------------------- /CommandPattern/RemoteControl/Commands/GarageDoorCommands/GarageDoorOpenCommand.cs: -------------------------------------------------------------------------------- 1 | namespace CommandPattern.RemoteControl.Commands.GarageDoorCommands; 2 | 3 | public class GarageDoorOpenCommand(GarageDoor garageDoor) : ICommand 4 | { 5 | public void Execute() 6 | { 7 | garageDoor.Open(); 8 | } 9 | 10 | public void Undo() 11 | { 12 | garageDoor.Close(); 13 | } 14 | } -------------------------------------------------------------------------------- /CommandPattern/RemoteControl/Commands/ICommand.cs: -------------------------------------------------------------------------------- 1 | namespace CommandPattern.RemoteControl.Commands; 2 | 3 | public interface ICommand 4 | { 5 | void Execute(); 6 | void Undo(); 7 | } -------------------------------------------------------------------------------- /CommandPattern/RemoteControl/Commands/LightCommands/Light.cs: -------------------------------------------------------------------------------- 1 | namespace CommandPattern.RemoteControl.Commands.LightCommands; 2 | 3 | public class Light(string name = "") 4 | { 5 | public void On() 6 | { 7 | Console.WriteLine($"{name} Light is On."); 8 | } 9 | 10 | public void Off() 11 | { 12 | Console.WriteLine($"{name} Light is Off."); 13 | } 14 | } -------------------------------------------------------------------------------- /CommandPattern/RemoteControl/Commands/LightCommands/LightOffCommand.cs: -------------------------------------------------------------------------------- 1 | namespace CommandPattern.RemoteControl.Commands.LightCommands; 2 | 3 | public class LightOffCommand(Light light) : ICommand 4 | { 5 | public void Execute() 6 | { 7 | light.Off(); 8 | } 9 | 10 | public void Undo() 11 | { 12 | light.On(); 13 | } 14 | } -------------------------------------------------------------------------------- /CommandPattern/RemoteControl/Commands/LightCommands/LightOnCommand.cs: -------------------------------------------------------------------------------- 1 | namespace CommandPattern.RemoteControl.Commands.LightCommands; 2 | 3 | public class LightOnCommand(Light light) : ICommand 4 | { 5 | public void Execute() 6 | { 7 | light.On(); 8 | } 9 | 10 | public void Undo() 11 | { 12 | light.Off(); 13 | } 14 | } -------------------------------------------------------------------------------- /CommandPattern/RemoteControl/Commands/NoCommand.cs: -------------------------------------------------------------------------------- 1 | namespace CommandPattern.RemoteControl.Commands; 2 | 3 | public class NoCommand : ICommand 4 | { 5 | public void Execute() 6 | { 7 | } 8 | 9 | public void Undo() 10 | { 11 | } 12 | } -------------------------------------------------------------------------------- /CommandPattern/RemoteControl/Commands/Stereo/Stereo.cs: -------------------------------------------------------------------------------- 1 | namespace CommandPattern.RemoteControl.Commands.Stereo; 2 | 3 | public class Stereo(string name = "") 4 | { 5 | public void On() 6 | { 7 | Console.WriteLine($"{name} Stereo is On."); 8 | } 9 | 10 | public void Off() 11 | { 12 | Console.WriteLine($"{name} Stereo is Off."); 13 | } 14 | 15 | public void SetCd() 16 | { 17 | Console.WriteLine($"{name} Stereo mode is CD."); 18 | } 19 | 20 | public void SetVolume(int level) 21 | { 22 | Console.WriteLine($"{name} Stereo volume is {level}."); 23 | } 24 | } -------------------------------------------------------------------------------- /CommandPattern/RemoteControl/Commands/Stereo/StereoOffCommand.cs: -------------------------------------------------------------------------------- 1 | namespace CommandPattern.RemoteControl.Commands.Stereo; 2 | 3 | public class StereoOffCommand(Stereo stereo) : ICommand 4 | { 5 | public void Execute() 6 | { 7 | stereo.Off(); 8 | } 9 | 10 | public void Undo() 11 | { 12 | stereo.On(); 13 | } 14 | } -------------------------------------------------------------------------------- /CommandPattern/RemoteControl/Commands/Stereo/StereoOnWithCDCommand.cs: -------------------------------------------------------------------------------- 1 | namespace CommandPattern.RemoteControl.Commands.Stereo; 2 | 3 | public class StereoOnWithCdCommand(Stereo stereo) : ICommand 4 | { 5 | public void Execute() 6 | { 7 | stereo.On(); 8 | stereo.SetCd(); 9 | stereo.SetVolume(11); 10 | } 11 | 12 | public void Undo() 13 | { 14 | stereo.Off(); 15 | } 16 | } -------------------------------------------------------------------------------- /CommandPattern/RemoteControl/RemoteControl.cs: -------------------------------------------------------------------------------- 1 | using CommandPattern.RemoteControl.Commands; 2 | using System.Text; 3 | 4 | namespace CommandPattern.RemoteControl; 5 | 6 | public class RemoteControl 7 | { 8 | private readonly ICommand[] _onCommands; 9 | private readonly ICommand[] _offCommands; 10 | private ICommand _undoCommand; 11 | 12 | public RemoteControl() 13 | { 14 | _onCommands = new ICommand[7]; 15 | _offCommands = new ICommand[7]; 16 | 17 | ICommand noCommand = new NoCommand(); 18 | 19 | for (var i = 0; i < 7; i++) 20 | { 21 | _onCommands[i] = noCommand; 22 | _offCommands[i] = noCommand; 23 | } 24 | _undoCommand = noCommand; 25 | } 26 | 27 | public void SetCommand(int slot, ICommand onCommand, ICommand offCommand) 28 | { 29 | if (slot is < 0 or > 6) 30 | { 31 | throw new ArgumentException("Slot number is out of range."); 32 | } 33 | _onCommands[slot] = onCommand; 34 | _offCommands[slot] = offCommand; 35 | } 36 | 37 | public void OnButtonWasPushed(int slot) 38 | { 39 | _onCommands[slot].Execute(); 40 | _undoCommand = _onCommands[slot]; 41 | } 42 | 43 | public void OffButtonWasPushed(int slot) 44 | { 45 | _offCommands[slot].Execute(); 46 | _undoCommand = _offCommands[slot]; 47 | } 48 | 49 | public void UndoButtonWasPushed() 50 | { 51 | _undoCommand.Undo(); 52 | } 53 | 54 | public override string ToString() 55 | { 56 | var sb = new StringBuilder(); 57 | sb.AppendLine("\n------ Remote Control ------\n"); 58 | for (var i = 0; i < _onCommands.Length; i++) 59 | { 60 | sb.AppendLine($"[slot {i}]\t {_onCommands[i].GetType().Name}\t{_offCommands[i].GetType().Name}"); 61 | } 62 | return sb.ToString(); 63 | } 64 | } -------------------------------------------------------------------------------- /CommandPattern/RemoteControl/RemoteLoader.cs: -------------------------------------------------------------------------------- 1 | using CommandPattern.RemoteControl.Commands.CeilingFanCommands; 2 | using CommandPattern.RemoteControl.Commands.GarageDoorCommands; 3 | using CommandPattern.RemoteControl.Commands.LightCommands; 4 | using CommandPattern.RemoteControl.Commands.Stereo; 5 | 6 | namespace CommandPattern.RemoteControl 7 | { 8 | public static class RemoteLoader 9 | { 10 | public static void Test() 11 | { 12 | var remoteControl = new RemoteControl(); 13 | var livingRoomLight = new Light("Living Room"); 14 | var kitchenLight = new Light("Kitchen"); 15 | var ceilingFan = new CeilingFan("Living Room"); 16 | var garageDoor = new GarageDoor(); 17 | var stereo = new Stereo("Living Room"); 18 | 19 | var livingRoomLightOn = new LightOnCommand(livingRoomLight); 20 | var livingRoomLightOff = new LightOffCommand(livingRoomLight); 21 | var kitchenLightOn = new LightOnCommand(kitchenLight); 22 | var kitchenLightOff = new LightOffCommand(kitchenLight); 23 | 24 | var ceilingFanOn = new CeilingFanOnCommand(ceilingFan); 25 | var ceilingFanOff = new CeilingFanOffCommand(ceilingFan); 26 | 27 | var garageDoorUp = new GarageDoorOpenCommand(garageDoor); 28 | var garageDoorDown = new GarageDoorCloseCommand(garageDoor); 29 | 30 | var stereoOnWithCd = new StereoOnWithCdCommand(stereo); 31 | var stereoOff = new StereoOffCommand(stereo); 32 | 33 | remoteControl.SetCommand(0, livingRoomLightOn, livingRoomLightOff); 34 | remoteControl.SetCommand(1, kitchenLightOn, kitchenLightOff); 35 | remoteControl.SetCommand(2, ceilingFanOn, ceilingFanOff); 36 | remoteControl.SetCommand(3, garageDoorUp, garageDoorDown); 37 | remoteControl.SetCommand(4, stereoOnWithCd, stereoOff); 38 | 39 | Console.WriteLine(remoteControl); 40 | 41 | remoteControl.OnButtonWasPushed(0); 42 | remoteControl.OffButtonWasPushed(0); 43 | remoteControl.UndoButtonWasPushed(); 44 | remoteControl.OnButtonWasPushed(1); 45 | remoteControl.OffButtonWasPushed(1); 46 | remoteControl.OnButtonWasPushed(2); 47 | remoteControl.OffButtonWasPushed(2); 48 | remoteControl.OnButtonWasPushed(3); 49 | remoteControl.OffButtonWasPushed(3); 50 | remoteControl.OnButtonWasPushed(4); 51 | remoteControl.OffButtonWasPushed(4); 52 | 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /CommandPattern/RemoteControl/SimpleRemoteControl.cs: -------------------------------------------------------------------------------- 1 | using CommandPattern.RemoteControl.Commands; 2 | 3 | namespace CommandPattern.RemoteControl 4 | { 5 | public class SimpleRemoteControl 6 | { 7 | private ICommand _slot = null!; 8 | 9 | public void SetCommand(ICommand command) 10 | { 11 | _slot = command; 12 | } 13 | 14 | public void ButtonWasPressed() 15 | { 16 | _slot.Execute(); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /CommandPattern/RemoteControl/SimpleRemoteControlTest.cs: -------------------------------------------------------------------------------- 1 | using CommandPattern.RemoteControl.Commands.GarageDoorCommands; 2 | using CommandPattern.RemoteControl.Commands.LightCommands; 3 | 4 | namespace CommandPattern.RemoteControl 5 | { 6 | public static class SimpleRemoteControlTest 7 | { 8 | public static void Test() 9 | { 10 | var remote = new SimpleRemoteControl(); 11 | var light = new Light(); 12 | var lightOn = new LightOnCommand(light); 13 | var garageDoor = new GarageDoor(); 14 | var garageDoorOpenCommand = new GarageDoorOpenCommand(garageDoor); 15 | 16 | remote.SetCommand(lightOn); 17 | remote.ButtonWasPressed(); 18 | remote.SetCommand(garageDoorOpenCommand); 19 | remote.ButtonWasPressed(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /CompositePattern/CompositePattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /CompositePattern/MenuComponent/IMenuComponent.cs: -------------------------------------------------------------------------------- 1 | namespace CompositePattern.MenuComponent; 2 | 3 | public interface IMenuComponent 4 | { 5 | void Add(IMenuComponent menuComponent); 6 | void Remove(IMenuComponent menuComponent); 7 | IMenuComponent GetChild(int i); 8 | void Print(); 9 | } -------------------------------------------------------------------------------- /CompositePattern/MenuComponent/Menu.cs: -------------------------------------------------------------------------------- 1 | namespace CompositePattern.MenuComponent; 2 | 3 | public class Menu(string description, string name) : IMenuComponent 4 | { 5 | public string Name { get; } = name; 6 | public string Description { get; } = description; 7 | private readonly List _menuComponents = new(); 8 | 9 | 10 | public void Add(IMenuComponent menuComponent) 11 | { 12 | _menuComponents.Add(menuComponent); 13 | } 14 | 15 | public void Remove(IMenuComponent menuComponent) 16 | { 17 | _menuComponents.Remove(menuComponent); 18 | } 19 | 20 | public IMenuComponent GetChild(int i) 21 | { 22 | return _menuComponents[i]; 23 | } 24 | 25 | public void Print() 26 | { 27 | Console.WriteLine("\n" + Name + ", " + Description); 28 | Console.WriteLine("-----------------------------"); 29 | using var iterator = _menuComponents.GetEnumerator(); 30 | while (iterator.MoveNext()) 31 | { 32 | iterator.Current?.Print(); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /CompositePattern/MenuComponent/MenuItem.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | namespace CompositePattern.MenuComponent; 4 | 5 | public class MenuItem(string name, string description, bool isVegetarian, decimal price) 6 | : IMenuComponent 7 | { 8 | public string Name { get; } = name; 9 | public string Description { get; } = description; 10 | public bool IsVegetarian { get; } = isVegetarian; 11 | public decimal Price { get; } = price; 12 | 13 | public void Add(IMenuComponent menuComponent) 14 | { 15 | throw new NotImplementedException(); 16 | } 17 | 18 | public void Remove(IMenuComponent menuComponent) 19 | { 20 | throw new NotImplementedException(); 21 | } 22 | 23 | public IMenuComponent GetChild(int i) 24 | { 25 | throw new NotImplementedException(); 26 | } 27 | 28 | public void Print() 29 | { 30 | var sb = new StringBuilder(); 31 | sb.Append(" " + Name); 32 | sb.Append(IsVegetarian ? "(v)" : ""); 33 | sb.Append(Price); 34 | sb.Append("\t--- " + Description); 35 | Console.WriteLine(sb.ToString()); 36 | } 37 | } -------------------------------------------------------------------------------- /CompositePattern/Program.cs: -------------------------------------------------------------------------------- 1 | using CompositePattern.MenuComponent; 2 | 3 | IMenuComponent pancakeHouseMenu = new Menu("PANCAKE HOUSE MENU", "Breakfast"); 4 | IMenuComponent dinerMenu = new Menu("DINER MENU", "Lunch"); 5 | IMenuComponent cafeMenu = new Menu("CAFE MENU", "Dinner"); 6 | IMenuComponent dessertMenu = new Menu("DESSERT MENU", "Dessert of course!"); 7 | 8 | IMenuComponent allMenus = new Menu("ALL MENUS", "All menus combined."); 9 | 10 | allMenus.Add(pancakeHouseMenu); 11 | allMenus.Add(dinerMenu); 12 | allMenus.Add(cafeMenu); 13 | 14 | dinerMenu.Add(new MenuItem("Pasta", 15 | "Spaghetti with Marinara Sauce, and a slice of sourdough bread", 16 | true, 3.89m)); 17 | dinerMenu.Add(dessertMenu); 18 | dessertMenu.Add(new MenuItem("Apple Pie", 19 | "Apple pie with a flaky crust, topped with vanilla ice cream", 20 | true, 1.59m)); 21 | 22 | var waitress = new CompositePattern.Waitress.Waitress(allMenus); 23 | waitress.PrintMenu(); 24 | 25 | Console.ReadKey(); -------------------------------------------------------------------------------- /CompositePattern/Waitress/Waitress.cs: -------------------------------------------------------------------------------- 1 | using CompositePattern.MenuComponent; 2 | 3 | namespace CompositePattern.Waitress; 4 | 5 | public class Waitress(IMenuComponent allMenus) 6 | { 7 | public void PrintMenu() 8 | { 9 | allMenus.Print(); 10 | } 11 | } -------------------------------------------------------------------------------- /CompoundPattern/CompoundPattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /CompoundPattern/CounterDecorator/QuackCounter.cs: -------------------------------------------------------------------------------- 1 | using CompoundPattern.Observable; 2 | 3 | namespace CompoundPattern.CounterDecorator; 4 | 5 | public class QuackCounter : IQuackable 6 | { 7 | private readonly IQuackable _duck; 8 | private static int _totalNumberOfQuacks; 9 | private readonly IQuackObservable _observable; 10 | 11 | public QuackCounter(IQuackable duck) 12 | { 13 | _duck = duck; 14 | _observable = new QuackObservable(this); 15 | } 16 | 17 | public void Quack() 18 | { 19 | _duck.Quack(); 20 | NotifyObservers(); 21 | _totalNumberOfQuacks++; 22 | } 23 | 24 | public static int GetQuacksCount() 25 | { 26 | return _totalNumberOfQuacks; 27 | } 28 | 29 | public void RegisterObserver(IObserver observer) 30 | { 31 | _observable.RegisterObserver(observer); 32 | } 33 | 34 | public void NotifyObservers() 35 | { 36 | _observable.NotifyObservers(); 37 | } 38 | 39 | public override string ToString() 40 | { 41 | return _duck.ToString() ?? string.Empty; 42 | } 43 | } -------------------------------------------------------------------------------- /CompoundPattern/DuckFactory/AbstractDuckFactory.cs: -------------------------------------------------------------------------------- 1 | namespace CompoundPattern.DuckFactory; 2 | 3 | public abstract class AbstractDuckFactory 4 | { 5 | public abstract IQuackable CreateMallardDuck { get; } 6 | public abstract IQuackable CreateRedheadDuck { get; } 7 | public abstract IQuackable CreateDuckCall { get; } 8 | public abstract IQuackable CreateRubberDuck { get; } 9 | } -------------------------------------------------------------------------------- /CompoundPattern/DuckFactory/CountingDuckFactory.cs: -------------------------------------------------------------------------------- 1 | using CompoundPattern.CounterDecorator; 2 | using CompoundPattern.SomeDucks; 3 | 4 | namespace CompoundPattern.DuckFactory; 5 | 6 | public class CountingDuckFactory : AbstractDuckFactory 7 | { 8 | public override IQuackable CreateMallardDuck => new QuackCounter(new MallardDuck()); 9 | public override IQuackable CreateRedheadDuck => new QuackCounter(new RedheadDuck()); 10 | public override IQuackable CreateDuckCall => new QuackCounter(new DuckCall()); 11 | public override IQuackable CreateRubberDuck => new QuackCounter(new RubberDuck()); 12 | } -------------------------------------------------------------------------------- /CompoundPattern/DuckFactory/DuckFactory.cs: -------------------------------------------------------------------------------- 1 | using CompoundPattern.SomeDucks; 2 | 3 | namespace CompoundPattern.DuckFactory; 4 | 5 | public class DuckFactory : AbstractDuckFactory 6 | { 7 | public override IQuackable CreateMallardDuck => new MallardDuck(); 8 | public override IQuackable CreateRedheadDuck => new RedheadDuck(); 9 | public override IQuackable CreateDuckCall => new DuckCall(); 10 | public override IQuackable CreateRubberDuck => new RubberDuck(); 11 | } -------------------------------------------------------------------------------- /CompoundPattern/DuckSimulator.cs: -------------------------------------------------------------------------------- 1 | using CompoundPattern.CounterDecorator; 2 | using CompoundPattern.DuckFactory; 3 | using CompoundPattern.Observable; 4 | using CompoundPattern.SomeDucks; 5 | using CompoundPattern.SomeGeese; 6 | 7 | namespace CompoundPattern; 8 | 9 | public class DuckSimulator 10 | { 11 | public void Simulate() 12 | { 13 | var mallardDuck = new MallardDuck(); 14 | var redheadDuck = new RedheadDuck(); 15 | var duckCall = new DuckCall(); 16 | var rubberDuck = new RubberDuck(); 17 | var gooseDuck = new GooseAdapter(new Goose()); 18 | 19 | Console.WriteLine("\nDuck Simulator"); 20 | Simulate(mallardDuck); 21 | Simulate(redheadDuck); 22 | Simulate(duckCall); 23 | Simulate(rubberDuck); 24 | Simulate(gooseDuck); 25 | } 26 | 27 | public void SimulateWithCounter() 28 | { 29 | var mallardDuck = new QuackCounter(new MallardDuck()); 30 | var redheadDuck = new QuackCounter(new RedheadDuck()); 31 | var duckCall = new QuackCounter(new DuckCall()); 32 | var rubberDuck = new QuackCounter(new RubberDuck()); 33 | var gooseDuck = new GooseAdapter(new Goose()); 34 | 35 | Console.WriteLine("\nDuck Simulator: With Decorator"); 36 | Simulate(mallardDuck); 37 | Simulate(redheadDuck); 38 | Simulate(duckCall); 39 | Simulate(rubberDuck); 40 | Simulate(gooseDuck); 41 | 42 | Console.WriteLine($"The ducks quacked {QuackCounter.GetQuacksCount()} times."); 43 | } 44 | 45 | public void SimulateUsingFactory(AbstractDuckFactory duckFactory) 46 | { 47 | var mallardDuck = duckFactory.CreateMallardDuck; 48 | var redheadDuck = duckFactory.CreateRedheadDuck; 49 | var duckCall = duckFactory.CreateDuckCall; 50 | var rubberDuck = duckFactory.CreateRubberDuck; 51 | var gooseDuck = new GooseAdapter(new Goose()); 52 | 53 | Console.WriteLine("\nDuck Simulator: With Abstract Factory"); 54 | Simulate(mallardDuck); 55 | Simulate(redheadDuck); 56 | Simulate(duckCall); 57 | Simulate(rubberDuck); 58 | Simulate(gooseDuck); 59 | 60 | Console.WriteLine($"The ducks quacked {QuackCounter.GetQuacksCount()} times."); 61 | } 62 | 63 | public void SimulateFlock(AbstractDuckFactory duckFactory) 64 | { 65 | var mallardDuck = duckFactory.CreateMallardDuck; 66 | var redheadDuck = duckFactory.CreateRedheadDuck; 67 | var duckCall = duckFactory.CreateDuckCall; 68 | var rubberDuck = duckFactory.CreateRubberDuck; 69 | var gooseDuck = new GooseAdapter(new Goose()); 70 | 71 | Console.WriteLine("\nDuck Simulator: With Composite - Flocks"); 72 | 73 | var flockOfDucks = new Flock.Flock(); 74 | flockOfDucks.Add(mallardDuck); 75 | flockOfDucks.Add(redheadDuck); 76 | flockOfDucks.Add(duckCall); 77 | flockOfDucks.Add(rubberDuck); 78 | flockOfDucks.Add(gooseDuck); 79 | 80 | var flockOfMallardDucks = new Flock.Flock(); 81 | var mallard1 = duckFactory.CreateMallardDuck; 82 | var mallard2 = duckFactory.CreateMallardDuck; 83 | var mallard3 = duckFactory.CreateMallardDuck; 84 | var mallard4 = duckFactory.CreateMallardDuck; 85 | flockOfMallardDucks.Add(mallard1); 86 | flockOfMallardDucks.Add(mallard2); 87 | flockOfMallardDucks.Add(mallard3); 88 | flockOfMallardDucks.Add(mallard4); 89 | flockOfDucks.Add(flockOfMallardDucks); 90 | 91 | Console.WriteLine("\nDuck Simulator: Whole Flock Simulation"); 92 | Simulate(flockOfDucks); 93 | Console.WriteLine("\nDuck Simulator: Mallard Flock Simulation"); 94 | Simulate(flockOfMallardDucks); 95 | 96 | Console.WriteLine($"The ducks quacked {QuackCounter.GetQuacksCount()} times."); 97 | } 98 | 99 | public void SimulateFlockWithObserver(AbstractDuckFactory duckFactory) 100 | { 101 | var mallardDuck = duckFactory.CreateMallardDuck; 102 | var redheadDuck = duckFactory.CreateRedheadDuck; 103 | var duckCall = duckFactory.CreateDuckCall; 104 | var rubberDuck = duckFactory.CreateRubberDuck; 105 | var gooseDuck = new GooseAdapter(new Goose()); 106 | 107 | Console.WriteLine("\nDuck Simulator: With Observer"); 108 | 109 | var flockOfDucks = new Flock.Flock(); 110 | flockOfDucks.Add(mallardDuck); 111 | flockOfDucks.Add(redheadDuck); 112 | flockOfDucks.Add(duckCall); 113 | flockOfDucks.Add(rubberDuck); 114 | flockOfDucks.Add(gooseDuck); 115 | 116 | var flockOfMallardDucks = new Flock.Flock(); 117 | var mallard1 = duckFactory.CreateMallardDuck; 118 | var mallard2 = duckFactory.CreateMallardDuck; 119 | var mallard3 = duckFactory.CreateMallardDuck; 120 | var mallard4 = duckFactory.CreateMallardDuck; 121 | flockOfMallardDucks.Add(mallard1); 122 | flockOfMallardDucks.Add(mallard2); 123 | flockOfMallardDucks.Add(mallard3); 124 | flockOfMallardDucks.Add(mallard4); 125 | flockOfDucks.Add(flockOfMallardDucks); 126 | 127 | var quackologist = new Quackologist(); 128 | flockOfDucks.RegisterObserver(quackologist); 129 | Console.WriteLine("\nDuck Simulator: Whole Flock Simulation"); 130 | Simulate(flockOfDucks); 131 | Console.WriteLine("\nDuck Simulator: Mallard Flock Simulation"); 132 | Simulate(flockOfMallardDucks); 133 | 134 | Console.WriteLine($"The ducks quacked {QuackCounter.GetQuacksCount()} times."); 135 | } 136 | 137 | private void Simulate(IQuackable duck) 138 | { 139 | duck.Quack(); 140 | } 141 | } -------------------------------------------------------------------------------- /CompoundPattern/Flock/Flock.cs: -------------------------------------------------------------------------------- 1 | using CompoundPattern.Observable; 2 | 3 | namespace CompoundPattern.Flock 4 | { 5 | public class Flock : IQuackable 6 | { 7 | private readonly List _quackers = new(); 8 | 9 | public void Add(IQuackable quacker) 10 | { 11 | _quackers.Add(quacker); 12 | } 13 | 14 | public void Quack() 15 | { 16 | foreach (var quacker in _quackers) 17 | { 18 | quacker.Quack(); 19 | } 20 | } 21 | 22 | public void RegisterObserver(IObserver observer) 23 | { 24 | foreach (var quacker in _quackers) 25 | { 26 | quacker.RegisterObserver(observer); 27 | } 28 | } 29 | 30 | public void NotifyObservers() 31 | { 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /CompoundPattern/IQuackable.cs: -------------------------------------------------------------------------------- 1 | using CompoundPattern.Observable; 2 | 3 | namespace CompoundPattern; 4 | 5 | public interface IQuackable : IQuackObservable 6 | { 7 | void Quack(); 8 | } -------------------------------------------------------------------------------- /CompoundPattern/Observable/IObserver.cs: -------------------------------------------------------------------------------- 1 | namespace CompoundPattern.Observable; 2 | 3 | public interface IObserver 4 | { 5 | void Update(IQuackObservable duck); 6 | } -------------------------------------------------------------------------------- /CompoundPattern/Observable/IQuackObservable.cs: -------------------------------------------------------------------------------- 1 | namespace CompoundPattern.Observable; 2 | 3 | public interface IQuackObservable 4 | { 5 | void RegisterObserver(IObserver observer); 6 | void NotifyObservers(); 7 | } -------------------------------------------------------------------------------- /CompoundPattern/Observable/QuackObservable.cs: -------------------------------------------------------------------------------- 1 | namespace CompoundPattern.Observable; 2 | 3 | public class QuackObservable(IQuackObservable duck) : IQuackObservable 4 | { 5 | private readonly List _observers = new(); 6 | 7 | public void RegisterObserver(IObserver observer) 8 | { 9 | _observers.Add(observer); 10 | } 11 | 12 | public void NotifyObservers() 13 | { 14 | foreach (var observer in _observers) 15 | { 16 | observer.Update(duck); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /CompoundPattern/Observable/Quackologist.cs: -------------------------------------------------------------------------------- 1 | namespace CompoundPattern.Observable; 2 | 3 | public class Quackologist : IObserver 4 | { 5 | public void Update(IQuackObservable duck) 6 | { 7 | Console.WriteLine($"Quackologist: {duck} just quacked."); 8 | } 9 | } -------------------------------------------------------------------------------- /CompoundPattern/Program.cs: -------------------------------------------------------------------------------- 1 | using CompoundPattern; 2 | using CompoundPattern.DuckFactory; 3 | 4 | var simulator = new DuckSimulator(); 5 | simulator.Simulate(); 6 | simulator.SimulateWithCounter(); 7 | simulator.SimulateUsingFactory(new CountingDuckFactory()); 8 | simulator.SimulateFlock(new CountingDuckFactory()); 9 | simulator.SimulateFlockWithObserver(new CountingDuckFactory()); 10 | Console.ReadKey(); 11 | -------------------------------------------------------------------------------- /CompoundPattern/SomeDucks/DuckCall.cs: -------------------------------------------------------------------------------- 1 | using CompoundPattern.Observable; 2 | 3 | namespace CompoundPattern.SomeDucks; 4 | 5 | public class DuckCall : IQuackable 6 | { 7 | private readonly IQuackObservable _observable; 8 | 9 | public DuckCall() 10 | { 11 | _observable = new QuackObservable(this); 12 | } 13 | 14 | public void Quack() 15 | { 16 | Console.WriteLine("Kwak."); 17 | NotifyObservers(); 18 | } 19 | 20 | public void RegisterObserver(IObserver observer) 21 | { 22 | _observable.RegisterObserver(observer); 23 | } 24 | 25 | public void NotifyObservers() 26 | { 27 | _observable.NotifyObservers(); 28 | } 29 | 30 | public override string ToString() 31 | { 32 | return "DuckCall"; 33 | } 34 | } -------------------------------------------------------------------------------- /CompoundPattern/SomeDucks/MallardDuck.cs: -------------------------------------------------------------------------------- 1 | using CompoundPattern.Observable; 2 | 3 | namespace CompoundPattern.SomeDucks; 4 | 5 | public class MallardDuck : IQuackable 6 | { 7 | private readonly IQuackObservable _observable; 8 | 9 | public MallardDuck() 10 | { 11 | _observable = new QuackObservable(this); 12 | } 13 | 14 | public void Quack() 15 | { 16 | Console.WriteLine("Quack."); 17 | NotifyObservers(); 18 | } 19 | 20 | public void RegisterObserver(IObserver observer) 21 | { 22 | _observable.RegisterObserver(observer); 23 | } 24 | 25 | public void NotifyObservers() 26 | { 27 | _observable.NotifyObservers(); 28 | } 29 | 30 | public override string ToString() 31 | { 32 | return "MallardDuck"; 33 | } 34 | } -------------------------------------------------------------------------------- /CompoundPattern/SomeDucks/RedheadDuck.cs: -------------------------------------------------------------------------------- 1 | using CompoundPattern.Observable; 2 | 3 | namespace CompoundPattern.SomeDucks; 4 | 5 | public class RedheadDuck : IQuackable 6 | { 7 | private readonly IQuackObservable _observable; 8 | 9 | public RedheadDuck() 10 | { 11 | _observable = new QuackObservable(this); 12 | } 13 | 14 | public void Quack() 15 | { 16 | Console.WriteLine("Quack."); 17 | NotifyObservers(); 18 | } 19 | 20 | public void RegisterObserver(IObserver observer) 21 | { 22 | _observable.RegisterObserver(observer); 23 | } 24 | 25 | public void NotifyObservers() 26 | { 27 | _observable.NotifyObservers(); 28 | } 29 | 30 | public override string ToString() 31 | { 32 | return "Redhead Duck"; 33 | } 34 | } -------------------------------------------------------------------------------- /CompoundPattern/SomeDucks/RubberDuck.cs: -------------------------------------------------------------------------------- 1 | using CompoundPattern.Observable; 2 | 3 | namespace CompoundPattern.SomeDucks; 4 | 5 | public class RubberDuck : IQuackable 6 | { 7 | private readonly IQuackObservable _observable; 8 | 9 | public RubberDuck() 10 | { 11 | _observable = new QuackObservable(this); 12 | } 13 | 14 | public void Quack() 15 | { 16 | Console.WriteLine("Squeak."); 17 | NotifyObservers(); 18 | } 19 | 20 | public void RegisterObserver(IObserver observer) 21 | { 22 | _observable.RegisterObserver(observer); 23 | } 24 | 25 | public void NotifyObservers() 26 | { 27 | _observable.NotifyObservers(); 28 | } 29 | 30 | public override string ToString() 31 | { 32 | return "RubberDuck"; 33 | } 34 | } -------------------------------------------------------------------------------- /CompoundPattern/SomeGeese/Goose.cs: -------------------------------------------------------------------------------- 1 | namespace CompoundPattern.SomeGeese; 2 | 3 | public class Goose 4 | { 5 | public void Honk() 6 | { 7 | Console.WriteLine("Honk."); 8 | } 9 | } -------------------------------------------------------------------------------- /CompoundPattern/SomeGeese/GooseAdapter.cs: -------------------------------------------------------------------------------- 1 | using CompoundPattern.Observable; 2 | 3 | namespace CompoundPattern.SomeGeese; 4 | 5 | public class GooseAdapter : IQuackable 6 | { 7 | private readonly Goose _goose; 8 | private readonly IQuackObservable _observable; 9 | 10 | public GooseAdapter(Goose goose) 11 | { 12 | _goose = goose; 13 | _observable = new QuackObservable(this); 14 | } 15 | 16 | public void Quack() 17 | { 18 | _goose.Honk(); 19 | NotifyObservers(); 20 | } 21 | 22 | public void RegisterObserver(IObserver observer) 23 | { 24 | _observable.RegisterObserver(observer); 25 | } 26 | 27 | public void NotifyObservers() 28 | { 29 | _observable.NotifyObservers(); 30 | } 31 | 32 | public override string ToString() 33 | { 34 | return "Goose"; 35 | } 36 | } -------------------------------------------------------------------------------- /DecoratorPattern/Coffee/Beverages/Beverage.cs: -------------------------------------------------------------------------------- 1 | namespace DecoratorPattern.Coffee.Beverages; 2 | 3 | public abstract class Beverage 4 | { 5 | public abstract string GetDescription(); 6 | 7 | public abstract decimal Cost(); 8 | } -------------------------------------------------------------------------------- /DecoratorPattern/Coffee/Beverages/DarkRoast.cs: -------------------------------------------------------------------------------- 1 | namespace DecoratorPattern.Coffee.Beverages; 2 | 3 | public class DarkRoast : Beverage 4 | { 5 | public override string GetDescription() 6 | { 7 | return "Dark Roast Coffee"; 8 | } 9 | 10 | public override decimal Cost() 11 | { 12 | return 0.99m; 13 | } 14 | } -------------------------------------------------------------------------------- /DecoratorPattern/Coffee/Beverages/Decaf.cs: -------------------------------------------------------------------------------- 1 | namespace DecoratorPattern.Coffee.Beverages; 2 | 3 | public class Decaf : Beverage 4 | { 5 | public override string GetDescription() 6 | { 7 | return "Decaf Coffee"; 8 | } 9 | 10 | public override decimal Cost() 11 | { 12 | return 1.05m; 13 | } 14 | } -------------------------------------------------------------------------------- /DecoratorPattern/Coffee/Beverages/Espresso.cs: -------------------------------------------------------------------------------- 1 | namespace DecoratorPattern.Coffee.Beverages; 2 | 3 | public class Espresso : Beverage 4 | { 5 | public override string GetDescription() 6 | { 7 | return "Espresso"; 8 | } 9 | 10 | public override decimal Cost() 11 | { 12 | return 1.99m; 13 | } 14 | } -------------------------------------------------------------------------------- /DecoratorPattern/Coffee/Beverages/HouseBlend.cs: -------------------------------------------------------------------------------- 1 | namespace DecoratorPattern.Coffee.Beverages; 2 | 3 | public class HouseBlend : Beverage 4 | { 5 | public override string GetDescription() 6 | { 7 | return "House Blend Coffee"; 8 | } 9 | 10 | public override decimal Cost() 11 | { 12 | return 0.89m; 13 | } 14 | } -------------------------------------------------------------------------------- /DecoratorPattern/Coffee/Condiments/CondimentDecorator.cs: -------------------------------------------------------------------------------- 1 | using DecoratorPattern.Coffee.Beverages; 2 | 3 | namespace DecoratorPattern.Coffee.Condiments; 4 | 5 | public abstract class CondimentDecorator(Beverage beverage) : Beverage 6 | { 7 | protected Beverage Beverage = beverage; 8 | } -------------------------------------------------------------------------------- /DecoratorPattern/Coffee/Condiments/Milk.cs: -------------------------------------------------------------------------------- 1 | using DecoratorPattern.Coffee.Beverages; 2 | 3 | namespace DecoratorPattern.Coffee.Condiments; 4 | 5 | public class Milk(Beverage beverage) : CondimentDecorator(beverage) 6 | { 7 | public override string GetDescription() 8 | { 9 | return Beverage.GetDescription() + ", Milk"; 10 | } 11 | 12 | public override decimal Cost() 13 | { 14 | return Beverage.Cost() + 0.10m; 15 | } 16 | } -------------------------------------------------------------------------------- /DecoratorPattern/Coffee/Condiments/Mocha.cs: -------------------------------------------------------------------------------- 1 | using DecoratorPattern.Coffee.Beverages; 2 | 3 | namespace DecoratorPattern.Coffee.Condiments; 4 | 5 | public class Mocha(Beverage beverage) : CondimentDecorator(beverage) 6 | { 7 | public override string GetDescription() 8 | { 9 | return Beverage.GetDescription() + ", Mocha"; 10 | } 11 | 12 | public override decimal Cost() 13 | { 14 | return 0.20m + Beverage.Cost(); 15 | } 16 | } -------------------------------------------------------------------------------- /DecoratorPattern/Coffee/Condiments/Soy.cs: -------------------------------------------------------------------------------- 1 | using DecoratorPattern.Coffee.Beverages; 2 | 3 | namespace DecoratorPattern.Coffee.Condiments; 4 | 5 | public class Soy(Beverage beverage) : CondimentDecorator(beverage) 6 | { 7 | public override string GetDescription() 8 | { 9 | return Beverage.GetDescription() + ", Soy"; 10 | } 11 | 12 | public override decimal Cost() 13 | { 14 | return Beverage.Cost() + 0.15m; 15 | } 16 | } -------------------------------------------------------------------------------- /DecoratorPattern/Coffee/Condiments/Whip.cs: -------------------------------------------------------------------------------- 1 | using DecoratorPattern.Coffee.Beverages; 2 | 3 | namespace DecoratorPattern.Coffee.Condiments; 4 | 5 | public class Whip(Beverage beverage) : CondimentDecorator(beverage) 6 | { 7 | public override string GetDescription() 8 | { 9 | return Beverage.GetDescription() + ", Whip"; 10 | } 11 | 12 | public override decimal Cost() 13 | { 14 | return Beverage.Cost() + 0.10m; 15 | } 16 | } -------------------------------------------------------------------------------- /DecoratorPattern/Coffee/Sizes/Grande.cs: -------------------------------------------------------------------------------- 1 | using DecoratorPattern.Coffee.Beverages; 2 | 3 | namespace DecoratorPattern.Coffee.Sizes; 4 | 5 | public class Grande(Beverage beverage) : SizeDecorator(beverage) 6 | { 7 | public override string GetDescription() 8 | { 9 | return Beverage.GetDescription() + ", Grande"; 10 | } 11 | 12 | public override decimal Cost() 13 | { 14 | return Beverage.Cost() + 0.15m; 15 | } 16 | } -------------------------------------------------------------------------------- /DecoratorPattern/Coffee/Sizes/SizeDecorator.cs: -------------------------------------------------------------------------------- 1 | using DecoratorPattern.Coffee.Beverages; 2 | 3 | namespace DecoratorPattern.Coffee.Sizes; 4 | 5 | public abstract class SizeDecorator(Beverage beverage) : Beverage 6 | { 7 | protected Beverage Beverage = beverage; 8 | } -------------------------------------------------------------------------------- /DecoratorPattern/Coffee/Sizes/Tall.cs: -------------------------------------------------------------------------------- 1 | using DecoratorPattern.Coffee.Beverages; 2 | 3 | namespace DecoratorPattern.Coffee.Sizes; 4 | 5 | public class Tall(Beverage beverage) : SizeDecorator(beverage) 6 | { 7 | public override string GetDescription() 8 | { 9 | return Beverage.GetDescription() + ", Tall"; 10 | } 11 | 12 | public override decimal Cost() 13 | { 14 | return Beverage.Cost() + 0.10m; 15 | } 16 | } -------------------------------------------------------------------------------- /DecoratorPattern/Coffee/Sizes/Venti.cs: -------------------------------------------------------------------------------- 1 | using DecoratorPattern.Coffee.Beverages; 2 | 3 | namespace DecoratorPattern.Coffee.Sizes; 4 | 5 | public class Venti(Beverage beverage) : SizeDecorator(beverage) 6 | { 7 | public override string GetDescription() 8 | { 9 | return Beverage.GetDescription() + ", Venti"; 10 | } 11 | 12 | public override decimal Cost() 13 | { 14 | return Beverage.Cost() + 0.20m; 15 | } 16 | } -------------------------------------------------------------------------------- /DecoratorPattern/DecoratorPattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /DecoratorPattern/Program.cs: -------------------------------------------------------------------------------- 1 | using DecoratorPattern.Coffee.Beverages; 2 | using DecoratorPattern.Coffee.Condiments; 3 | using DecoratorPattern.Coffee.Sizes; 4 | 5 | Beverage beverage = new Espresso(); 6 | Console.WriteLine(beverage.GetDescription() + " $" + beverage.Cost()); 7 | beverage = new Venti(beverage); 8 | Console.WriteLine(beverage.GetDescription() + " $" + beverage.Cost()); 9 | 10 | Beverage beverage2 = new HouseBlend(); 11 | beverage2 = new Mocha(beverage2); 12 | beverage2 = new Soy(beverage2); 13 | beverage2 = new Whip(beverage2); 14 | Console.WriteLine(beverage2.GetDescription() + " $" + beverage2.Cost()); 15 | beverage2 = new Tall(beverage2); 16 | Console.WriteLine(beverage2.GetDescription() + " $" + beverage2.Cost()); 17 | 18 | Beverage beverage3 = new DarkRoast(); 19 | beverage3 = new Mocha(beverage3); 20 | beverage3 = new Mocha(beverage3); 21 | beverage3 = new Whip(beverage3); 22 | Console.WriteLine(beverage3.GetDescription() + " $" + beverage3.Cost()); 23 | beverage3 = new Grande(beverage3); 24 | Console.WriteLine(beverage3.GetDescription() + " $" + beverage3.Cost()); 25 | 26 | Console.ReadKey(); -------------------------------------------------------------------------------- /FactoryPattern/FactoryPattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /FactoryPattern/PizzaIngredient/ChicagoPizzaIngredientFactory.cs: -------------------------------------------------------------------------------- 1 | using FactoryPattern.PizzaIngredient.Ingredients; 2 | 3 | namespace FactoryPattern.PizzaIngredient; 4 | 5 | public class ChicagoPizzaIngredientFactory : IPizzaIngredientFactory 6 | { 7 | public IDough CreateDough() 8 | { 9 | return new ThickCrustDough(); 10 | } 11 | 12 | public ISauce CreateSauce() 13 | { 14 | return new PlumTomatoSauce(); 15 | } 16 | 17 | public ICheese CreateCheese() 18 | { 19 | return new Mozzarella(); 20 | } 21 | 22 | public List CreateVeggies() 23 | { 24 | return new List 25 | { 26 | new BlackOlives(), 27 | new EggPlant(), 28 | new Spinach() 29 | }; 30 | } 31 | 32 | public IPepperoni CreatePepperoni() 33 | { 34 | return new SlicedPepperoni(); 35 | } 36 | 37 | public IClams CreateClams() 38 | { 39 | return new FrozenClams(); 40 | } 41 | } -------------------------------------------------------------------------------- /FactoryPattern/PizzaIngredient/IPizzaIngredientFactory.cs: -------------------------------------------------------------------------------- 1 | using FactoryPattern.PizzaIngredient.Ingredients; 2 | 3 | namespace FactoryPattern.PizzaIngredient; 4 | 5 | public interface IPizzaIngredientFactory 6 | { 7 | IDough CreateDough(); 8 | ISauce CreateSauce(); 9 | ICheese CreateCheese(); 10 | List CreateVeggies(); 11 | IPepperoni CreatePepperoni(); 12 | IClams CreateClams(); 13 | } -------------------------------------------------------------------------------- /FactoryPattern/PizzaIngredient/Ingredients/Cheese.cs: -------------------------------------------------------------------------------- 1 | namespace FactoryPattern.PizzaIngredient.Ingredients; 2 | 3 | public interface ICheese 4 | { 5 | string Name { get; } 6 | } 7 | 8 | public class ReggianoCheese : ICheese 9 | { 10 | public string Name => "Reggiano Cheese"; 11 | } 12 | 13 | public class Mozzarella : ICheese 14 | { 15 | public string Name => "Mozzarella Cheese"; 16 | } -------------------------------------------------------------------------------- /FactoryPattern/PizzaIngredient/Ingredients/Clams.cs: -------------------------------------------------------------------------------- 1 | namespace FactoryPattern.PizzaIngredient.Ingredients; 2 | 3 | public interface IClams 4 | { 5 | string Name { get; } 6 | } 7 | 8 | public class FreshClams : IClams 9 | { 10 | public string Name => "Fresh Clams"; 11 | } 12 | 13 | public class FrozenClams : IClams 14 | { 15 | public string Name => "Frozen Clams"; 16 | } -------------------------------------------------------------------------------- /FactoryPattern/PizzaIngredient/Ingredients/Dough.cs: -------------------------------------------------------------------------------- 1 | namespace FactoryPattern.PizzaIngredient.Ingredients; 2 | 3 | public interface IDough 4 | { 5 | string Name { get; } 6 | } 7 | 8 | public class ThinCrustDough : IDough 9 | { 10 | public string Name => "Thin Crust Dough"; 11 | } 12 | 13 | public class ThickCrustDough : IDough 14 | { 15 | public string Name => "Thick Crust Dough"; 16 | } -------------------------------------------------------------------------------- /FactoryPattern/PizzaIngredient/Ingredients/Pepperoni.cs: -------------------------------------------------------------------------------- 1 | namespace FactoryPattern.PizzaIngredient.Ingredients; 2 | 3 | public interface IPepperoni 4 | { 5 | string Name { get; } 6 | } 7 | 8 | public class SlicedPepperoni : IPepperoni 9 | { 10 | public string Name => "Sliced Pepperoni"; 11 | } -------------------------------------------------------------------------------- /FactoryPattern/PizzaIngredient/Ingredients/Sauce.cs: -------------------------------------------------------------------------------- 1 | namespace FactoryPattern.PizzaIngredient.Ingredients; 2 | 3 | public interface ISauce 4 | { 5 | string Name { get; } 6 | } 7 | 8 | public class MarinaraSauce : ISauce 9 | { 10 | public string Name => "Marinara Sauce"; 11 | } 12 | 13 | public class PlumTomatoSauce : ISauce 14 | { 15 | public string Name => "Plum Tomato Sauce"; 16 | } -------------------------------------------------------------------------------- /FactoryPattern/PizzaIngredient/Ingredients/Veggie.cs: -------------------------------------------------------------------------------- 1 | namespace FactoryPattern.PizzaIngredient.Ingredients; 2 | 3 | public interface IVeggie 4 | { 5 | string Name { get; } 6 | } 7 | 8 | public class Garlic : IVeggie 9 | { 10 | public string Name => "Garlic"; 11 | } 12 | 13 | public class Onion : IVeggie 14 | { 15 | public string Name => "Onion"; 16 | } 17 | 18 | public class Mushroom : IVeggie 19 | { 20 | public string Name => "Mushroom"; 21 | } 22 | 23 | public class RedPepper : IVeggie 24 | { 25 | public string Name => "Red Pepper"; 26 | } 27 | 28 | public class Spinach : IVeggie 29 | { 30 | public string Name => "Spinach"; 31 | } 32 | 33 | public class BlackOlives : IVeggie 34 | { 35 | public string Name => "Black Olives"; 36 | } 37 | 38 | public class EggPlant : IVeggie 39 | { 40 | public string Name => "Eggplant"; 41 | } -------------------------------------------------------------------------------- /FactoryPattern/PizzaIngredient/NYPizzaIngredientFactory.cs: -------------------------------------------------------------------------------- 1 | using FactoryPattern.PizzaIngredient.Ingredients; 2 | 3 | namespace FactoryPattern.PizzaIngredient; 4 | 5 | public class NyPizzaIngredientFactory : IPizzaIngredientFactory 6 | { 7 | public IDough CreateDough() 8 | { 9 | return new ThinCrustDough(); 10 | } 11 | 12 | public ISauce CreateSauce() 13 | { 14 | return new MarinaraSauce(); 15 | } 16 | 17 | public ICheese CreateCheese() 18 | { 19 | return new ReggianoCheese(); 20 | } 21 | 22 | public List CreateVeggies() 23 | { 24 | return new List 25 | { 26 | new Garlic(), 27 | new Onion(), 28 | new Mushroom(), 29 | new RedPepper() 30 | }; 31 | } 32 | 33 | public IPepperoni CreatePepperoni() 34 | { 35 | return new SlicedPepperoni(); 36 | } 37 | 38 | public IClams CreateClams() 39 | { 40 | return new FreshClams(); 41 | } 42 | } -------------------------------------------------------------------------------- /FactoryPattern/PizzaProduct/CheesePizza.cs: -------------------------------------------------------------------------------- 1 | using FactoryPattern.PizzaIngredient; 2 | 3 | namespace FactoryPattern.PizzaProduct; 4 | 5 | public class CheesePizza(IPizzaIngredientFactory ingredientFactory) : Pizza(ingredientFactory) 6 | { 7 | public override void Prepare() 8 | { 9 | Console.WriteLine("Preparing " + Name); 10 | Dough = IngredientFactory.CreateDough(); 11 | Sauce = IngredientFactory.CreateSauce(); 12 | Cheese = IngredientFactory.CreateCheese(); 13 | } 14 | } -------------------------------------------------------------------------------- /FactoryPattern/PizzaProduct/ClamPizza.cs: -------------------------------------------------------------------------------- 1 | using FactoryPattern.PizzaIngredient; 2 | 3 | namespace FactoryPattern.PizzaProduct; 4 | 5 | public class ClamPizza(IPizzaIngredientFactory ingredientFactory) : Pizza(ingredientFactory) 6 | { 7 | public override void Prepare() 8 | { 9 | Console.WriteLine("Preparing " + Name); 10 | Dough = IngredientFactory.CreateDough(); 11 | Sauce = IngredientFactory.CreateSauce(); 12 | Cheese = IngredientFactory.CreateCheese(); 13 | Clams = IngredientFactory.CreateClams(); 14 | } 15 | } -------------------------------------------------------------------------------- /FactoryPattern/PizzaProduct/PepperoniPizza.cs: -------------------------------------------------------------------------------- 1 | using FactoryPattern.PizzaIngredient; 2 | 3 | namespace FactoryPattern.PizzaProduct; 4 | 5 | public class PepperoniPizza(IPizzaIngredientFactory ingredientFactory) : Pizza(ingredientFactory) 6 | { 7 | public override void Prepare() 8 | { 9 | Console.WriteLine("Preparing " + Name); 10 | Dough = IngredientFactory.CreateDough(); 11 | Sauce = IngredientFactory.CreateSauce(); 12 | Cheese = IngredientFactory.CreateCheese(); 13 | Pepperoni = IngredientFactory.CreatePepperoni(); 14 | } 15 | } -------------------------------------------------------------------------------- /FactoryPattern/PizzaProduct/Pizza.cs: -------------------------------------------------------------------------------- 1 | using FactoryPattern.PizzaIngredient; 2 | using FactoryPattern.PizzaIngredient.Ingredients; 3 | 4 | namespace FactoryPattern.PizzaProduct; 5 | 6 | public abstract class Pizza(IPizzaIngredientFactory ingredientFactory) 7 | { 8 | public string Name { get; protected set; } = string.Empty; 9 | public IDough Dough { get; protected set; } = null!; 10 | public ISauce Sauce { get; protected set; } = null!; 11 | public List Veggies { get; protected set; } = new(); 12 | public ICheese Cheese { get; protected set; } = null!; 13 | public IPepperoni Pepperoni { get; protected set; } = null!; 14 | public IClams Clams { get; protected set; } = null!; 15 | protected readonly IPizzaIngredientFactory IngredientFactory = ingredientFactory; 16 | 17 | public abstract void Prepare(); 18 | 19 | public void Bake() 20 | { 21 | Console.WriteLine("Bake for 25 minutes at 350 degree"); 22 | } 23 | 24 | public void Cut() 25 | { 26 | Console.WriteLine("Cutting the pizza into diagonal slices."); 27 | } 28 | 29 | public void Box() 30 | { 31 | Console.WriteLine("Place pizza in official PizzaStore box."); 32 | } 33 | 34 | public void SetName(string name) 35 | { 36 | Name = name; 37 | } 38 | } -------------------------------------------------------------------------------- /FactoryPattern/PizzaProduct/PizzaType.cs: -------------------------------------------------------------------------------- 1 | namespace FactoryPattern.PizzaProduct; 2 | 3 | public enum PizzaType 4 | { 5 | Cheese = 0, 6 | Pepperoni, 7 | Clam, 8 | Veggie 9 | } -------------------------------------------------------------------------------- /FactoryPattern/PizzaProduct/VeggiePizza.cs: -------------------------------------------------------------------------------- 1 | using FactoryPattern.PizzaIngredient; 2 | 3 | namespace FactoryPattern.PizzaProduct; 4 | 5 | public class VeggiePizza(IPizzaIngredientFactory ingredientFactory) : Pizza(ingredientFactory) 6 | { 7 | public override void Prepare() 8 | { 9 | Console.WriteLine("Preparing " + Name); 10 | Dough = IngredientFactory.CreateDough(); 11 | Sauce = IngredientFactory.CreateSauce(); 12 | Cheese = IngredientFactory.CreateCheese(); 13 | Veggies = IngredientFactory.CreateVeggies(); 14 | } 15 | } -------------------------------------------------------------------------------- /FactoryPattern/PizzaStore/ChicagoStylePizzaStore.cs: -------------------------------------------------------------------------------- 1 | using FactoryPattern.PizzaIngredient; 2 | using FactoryPattern.PizzaProduct; 3 | 4 | namespace FactoryPattern.PizzaStore; 5 | 6 | public class ChicagoStylePizzaStore : PizzaStore 7 | { 8 | private readonly ChicagoPizzaIngredientFactory _ingredientFactory = new(); 9 | 10 | protected override Pizza? CreatePizza(PizzaType type) 11 | { 12 | Pizza pizza; 13 | 14 | switch (type) 15 | { 16 | case PizzaType.Cheese: 17 | pizza = new CheesePizza(_ingredientFactory); 18 | pizza.SetName("Chicago Style Cheese Pizza"); 19 | break; 20 | case PizzaType.Pepperoni: 21 | pizza = new PepperoniPizza(_ingredientFactory); 22 | pizza.SetName("Chicago Style Pepperoni Pizza"); 23 | break; 24 | case PizzaType.Clam: 25 | pizza = new ClamPizza(_ingredientFactory); 26 | pizza.SetName("Chicago Style Clam Pizza"); 27 | break; 28 | case PizzaType.Veggie: 29 | pizza = new VeggiePizza(_ingredientFactory); 30 | pizza.SetName("Chicago Style Veggie Pizza"); 31 | break; 32 | default: 33 | return null; 34 | } 35 | 36 | return pizza; 37 | } 38 | } -------------------------------------------------------------------------------- /FactoryPattern/PizzaStore/NYStylePizzaStore.cs: -------------------------------------------------------------------------------- 1 | using FactoryPattern.PizzaIngredient; 2 | using FactoryPattern.PizzaProduct; 3 | 4 | namespace FactoryPattern.PizzaStore; 5 | 6 | public class NyStylePizzaStore : PizzaStore 7 | { 8 | private readonly NyPizzaIngredientFactory _ingredientFactory = new(); 9 | 10 | protected override Pizza? CreatePizza(PizzaType type) 11 | { 12 | Pizza pizza; 13 | 14 | switch (type) 15 | { 16 | case PizzaType.Cheese: 17 | pizza = new CheesePizza(_ingredientFactory); 18 | pizza.SetName("New York Style Cheese Pizza"); 19 | break; 20 | case PizzaType.Pepperoni: 21 | pizza = new PepperoniPizza(_ingredientFactory); 22 | pizza.SetName("New York Style Pepperoni Pizza"); 23 | break; 24 | case PizzaType.Clam: 25 | pizza = new ClamPizza(_ingredientFactory); 26 | pizza.SetName("New York Style Clam Pizza"); 27 | break; 28 | case PizzaType.Veggie: 29 | pizza = new VeggiePizza(_ingredientFactory); 30 | pizza.SetName("New York Style Veggie Pizza"); 31 | break; 32 | default: 33 | return null; 34 | } 35 | 36 | return pizza; 37 | } 38 | 39 | 40 | } -------------------------------------------------------------------------------- /FactoryPattern/PizzaStore/PizzaStore.cs: -------------------------------------------------------------------------------- 1 | using FactoryPattern.PizzaProduct; 2 | 3 | namespace FactoryPattern.PizzaStore 4 | { 5 | public abstract class PizzaStore 6 | { 7 | public Pizza OrderPizza(PizzaType type) 8 | { 9 | var pizza = CreatePizza(type); 10 | pizza.Prepare(); 11 | pizza.Bake(); 12 | pizza.Cut(); 13 | pizza.Box(); 14 | 15 | return pizza; 16 | } 17 | 18 | protected abstract Pizza? CreatePizza(PizzaType type); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /FactoryPattern/Program.cs: -------------------------------------------------------------------------------- 1 | using FactoryPattern.PizzaProduct; 2 | using FactoryPattern.PizzaStore; 3 | 4 | var nyStore = new NyStylePizzaStore(); 5 | var pizza = nyStore.OrderPizza(PizzaType.Cheese); 6 | Console.WriteLine($"You ordered a {pizza.Name}\n"); 7 | 8 | var chicagoStore = new ChicagoStylePizzaStore(); 9 | pizza = chicagoStore.OrderPizza(PizzaType.Cheese); 10 | Console.WriteLine($"You ordered a {pizza.Name}\n"); 11 | 12 | Console.ReadKey(); -------------------------------------------------------------------------------- /HeadFirstDesignPattern.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29318.209 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommandPattern", "CommandPattern\CommandPattern.csproj", "{436D52D2-3C18-43A4-9AB9-EAD8A50F7129}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CompositePattern", "CompositePattern\CompositePattern.csproj", "{78D7C952-781B-4217-983B-61BFE24D6638}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CompoundPattern", "CompoundPattern\CompoundPattern.csproj", "{9644F793-A390-4040-8DFF-F24DA9678DD7}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DecoratorPattern", "DecoratorPattern\DecoratorPattern.csproj", "{87852DF3-3E55-46E5-B007-FE0941C14054}" 13 | EndProject 14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FactoryPattern", "FactoryPattern\FactoryPattern.csproj", "{8375EAF9-DFEB-4D31-B917-A39FE0E88E36}" 15 | EndProject 16 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IteratorPattern", "IteratorPattern\IteratorPattern.csproj", "{39D62115-867C-4AEA-B3EE-C4066F6249CE}" 17 | EndProject 18 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ObserverPattern", "ObserverPattern\ObserverPattern.csproj", "{C6295C55-D696-43BA-A901-AF1CE832AB8A}" 19 | EndProject 20 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProxyPattern", "ProxyPattern\ProxyPattern.csproj", "{8F8E972F-CEDA-4E61-9B0D-DC5FFD2D91E6}" 21 | EndProject 22 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SingletonPattern", "SingletonPattern\SingletonPattern.csproj", "{881302A9-72D4-460C-B03B-DB48E64AE17D}" 23 | EndProject 24 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StatePattern", "StatePattern\StatePattern.csproj", "{A405DC37-1DE8-455D-8254-5036963D0F11}" 25 | EndProject 26 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StrategyPattern", "StrategyPattern\StrategyPattern.csproj", "{FF43CC32-48F0-4537-81E5-BD66699DA003}" 27 | EndProject 28 | Global 29 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 30 | Debug|Any CPU = Debug|Any CPU 31 | Release|Any CPU = Release|Any CPU 32 | EndGlobalSection 33 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 34 | {436D52D2-3C18-43A4-9AB9-EAD8A50F7129}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 35 | {436D52D2-3C18-43A4-9AB9-EAD8A50F7129}.Debug|Any CPU.Build.0 = Debug|Any CPU 36 | {436D52D2-3C18-43A4-9AB9-EAD8A50F7129}.Release|Any CPU.ActiveCfg = Release|Any CPU 37 | {436D52D2-3C18-43A4-9AB9-EAD8A50F7129}.Release|Any CPU.Build.0 = Release|Any CPU 38 | {78D7C952-781B-4217-983B-61BFE24D6638}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 39 | {78D7C952-781B-4217-983B-61BFE24D6638}.Debug|Any CPU.Build.0 = Debug|Any CPU 40 | {78D7C952-781B-4217-983B-61BFE24D6638}.Release|Any CPU.ActiveCfg = Release|Any CPU 41 | {78D7C952-781B-4217-983B-61BFE24D6638}.Release|Any CPU.Build.0 = Release|Any CPU 42 | {9644F793-A390-4040-8DFF-F24DA9678DD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 43 | {9644F793-A390-4040-8DFF-F24DA9678DD7}.Debug|Any CPU.Build.0 = Debug|Any CPU 44 | {9644F793-A390-4040-8DFF-F24DA9678DD7}.Release|Any CPU.ActiveCfg = Release|Any CPU 45 | {9644F793-A390-4040-8DFF-F24DA9678DD7}.Release|Any CPU.Build.0 = Release|Any CPU 46 | {87852DF3-3E55-46E5-B007-FE0941C14054}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 47 | {87852DF3-3E55-46E5-B007-FE0941C14054}.Debug|Any CPU.Build.0 = Debug|Any CPU 48 | {87852DF3-3E55-46E5-B007-FE0941C14054}.Release|Any CPU.ActiveCfg = Release|Any CPU 49 | {87852DF3-3E55-46E5-B007-FE0941C14054}.Release|Any CPU.Build.0 = Release|Any CPU 50 | {8375EAF9-DFEB-4D31-B917-A39FE0E88E36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 51 | {8375EAF9-DFEB-4D31-B917-A39FE0E88E36}.Debug|Any CPU.Build.0 = Debug|Any CPU 52 | {8375EAF9-DFEB-4D31-B917-A39FE0E88E36}.Release|Any CPU.ActiveCfg = Release|Any CPU 53 | {8375EAF9-DFEB-4D31-B917-A39FE0E88E36}.Release|Any CPU.Build.0 = Release|Any CPU 54 | {39D62115-867C-4AEA-B3EE-C4066F6249CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 55 | {39D62115-867C-4AEA-B3EE-C4066F6249CE}.Debug|Any CPU.Build.0 = Debug|Any CPU 56 | {39D62115-867C-4AEA-B3EE-C4066F6249CE}.Release|Any CPU.ActiveCfg = Release|Any CPU 57 | {39D62115-867C-4AEA-B3EE-C4066F6249CE}.Release|Any CPU.Build.0 = Release|Any CPU 58 | {C6295C55-D696-43BA-A901-AF1CE832AB8A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 59 | {C6295C55-D696-43BA-A901-AF1CE832AB8A}.Debug|Any CPU.Build.0 = Debug|Any CPU 60 | {C6295C55-D696-43BA-A901-AF1CE832AB8A}.Release|Any CPU.ActiveCfg = Release|Any CPU 61 | {C6295C55-D696-43BA-A901-AF1CE832AB8A}.Release|Any CPU.Build.0 = Release|Any CPU 62 | {8F8E972F-CEDA-4E61-9B0D-DC5FFD2D91E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 63 | {8F8E972F-CEDA-4E61-9B0D-DC5FFD2D91E6}.Debug|Any CPU.Build.0 = Debug|Any CPU 64 | {8F8E972F-CEDA-4E61-9B0D-DC5FFD2D91E6}.Release|Any CPU.ActiveCfg = Release|Any CPU 65 | {8F8E972F-CEDA-4E61-9B0D-DC5FFD2D91E6}.Release|Any CPU.Build.0 = Release|Any CPU 66 | {881302A9-72D4-460C-B03B-DB48E64AE17D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 67 | {881302A9-72D4-460C-B03B-DB48E64AE17D}.Debug|Any CPU.Build.0 = Debug|Any CPU 68 | {881302A9-72D4-460C-B03B-DB48E64AE17D}.Release|Any CPU.ActiveCfg = Release|Any CPU 69 | {881302A9-72D4-460C-B03B-DB48E64AE17D}.Release|Any CPU.Build.0 = Release|Any CPU 70 | {A405DC37-1DE8-455D-8254-5036963D0F11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 71 | {A405DC37-1DE8-455D-8254-5036963D0F11}.Debug|Any CPU.Build.0 = Debug|Any CPU 72 | {A405DC37-1DE8-455D-8254-5036963D0F11}.Release|Any CPU.ActiveCfg = Release|Any CPU 73 | {A405DC37-1DE8-455D-8254-5036963D0F11}.Release|Any CPU.Build.0 = Release|Any CPU 74 | {FF43CC32-48F0-4537-81E5-BD66699DA003}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 75 | {FF43CC32-48F0-4537-81E5-BD66699DA003}.Debug|Any CPU.Build.0 = Debug|Any CPU 76 | {FF43CC32-48F0-4537-81E5-BD66699DA003}.Release|Any CPU.ActiveCfg = Release|Any CPU 77 | {FF43CC32-48F0-4537-81E5-BD66699DA003}.Release|Any CPU.Build.0 = Release|Any CPU 78 | EndGlobalSection 79 | GlobalSection(SolutionProperties) = preSolution 80 | HideSolutionNode = FALSE 81 | EndGlobalSection 82 | GlobalSection(ExtensibilityGlobals) = postSolution 83 | SolutionGuid = {194FB780-2E7D-4DEB-A944-B2C7C51F00C7} 84 | EndGlobalSection 85 | EndGlobal 86 | -------------------------------------------------------------------------------- /HeadFirstDesignPattern.sln.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | True 3 | True 4 | True 5 | True 6 | True 7 | True 8 | True 9 | True 10 | True 11 | True -------------------------------------------------------------------------------- /IteratorPattern/Iterator/DinnerMenuIterator.cs: -------------------------------------------------------------------------------- 1 | using IteratorPattern.Menu; 2 | 3 | namespace IteratorPattern.Iterator; 4 | 5 | public class DinnerMenuIterator(MenuItem[] items) : IIterator 6 | { 7 | private int _index = 0; 8 | 9 | public bool HasNext() 10 | { 11 | return _index < items.Length; 12 | } 13 | 14 | public object Next() 15 | { 16 | var menuItem = items[_index]; 17 | _index++; 18 | return menuItem; 19 | } 20 | } -------------------------------------------------------------------------------- /IteratorPattern/Iterator/IIterator.cs: -------------------------------------------------------------------------------- 1 | namespace IteratorPattern.Iterator; 2 | 3 | public interface IIterator 4 | { 5 | bool HasNext(); 6 | object Next(); 7 | } -------------------------------------------------------------------------------- /IteratorPattern/Iterator/PancakeHouseMenuIterator.cs: -------------------------------------------------------------------------------- 1 | using IteratorPattern.Menu; 2 | 3 | namespace IteratorPattern.Iterator; 4 | 5 | internal class PancakeHouseMenuIterator(List menuItems) : IIterator 6 | { 7 | private int _index = 0; 8 | 9 | public bool HasNext() 10 | { 11 | return _index + 1 <= menuItems.Count; 12 | } 13 | 14 | public object Next() 15 | { 16 | var menuItem = menuItems[_index]; 17 | _index++; 18 | return menuItem; 19 | } 20 | } -------------------------------------------------------------------------------- /IteratorPattern/IteratorPattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /IteratorPattern/Menu/DinerMenu.cs: -------------------------------------------------------------------------------- 1 | using IteratorPattern.Iterator; 2 | 3 | namespace IteratorPattern.Menu; 4 | 5 | public class DinerMenu : IMenu 6 | { 7 | public static readonly int MaxItems = 6; 8 | private int _numberOfItems; 9 | private readonly MenuItem[] _menuItems = new MenuItem[MaxItems]; 10 | 11 | public DinerMenu() 12 | { 13 | _numberOfItems = 0; 14 | AddItem("Vegetarian BLT", "(Fakin') Bacon with lettuce & tomato on whole wheat", true, 2.99m); 15 | AddItem("BLT", "Bacon with lettuce & tomato on whole wheat", false, 2.99m); 16 | AddItem("Soup of the day", "Soup of the day, with a side of potato salad", false, 3.29m); 17 | AddItem("Hotdog", "A hot dog, with saurkraut, relish, onions, topped with cheese", false, 3.05m); 18 | } 19 | 20 | public void AddItem(string name, string description, bool vegetarian, decimal price) 21 | { 22 | if (_numberOfItems >= MaxItems) 23 | { 24 | Console.WriteLine("Sorry, menu is full! Can't add new item to menu."); 25 | } 26 | _menuItems[_numberOfItems] = new MenuItem(name, description, vegetarian, price); 27 | _numberOfItems++; 28 | } 29 | 30 | public IIterator CreateIterator() 31 | { 32 | return new DinnerMenuIterator(_menuItems); 33 | } 34 | } -------------------------------------------------------------------------------- /IteratorPattern/Menu/IMenu.cs: -------------------------------------------------------------------------------- 1 | using IteratorPattern.Iterator; 2 | 3 | namespace IteratorPattern.Menu; 4 | 5 | public interface IMenu 6 | { 7 | IIterator CreateIterator(); 8 | } -------------------------------------------------------------------------------- /IteratorPattern/Menu/MenuItem.cs: -------------------------------------------------------------------------------- 1 | namespace IteratorPattern.Menu; 2 | 3 | public class MenuItem(string name, string description, bool isVegetarian, decimal price) 4 | { 5 | public string Name { get; } = name; 6 | public string Description { get; } = description; 7 | public bool IsVegetarian { get; } = isVegetarian; 8 | public decimal Price { get; } = price; 9 | } -------------------------------------------------------------------------------- /IteratorPattern/Menu/PancakeHouseMenu.cs: -------------------------------------------------------------------------------- 1 | using IteratorPattern.Iterator; 2 | 3 | namespace IteratorPattern.Menu; 4 | 5 | public class PancakeHouseMenu : IMenu 6 | { 7 | private readonly List _menuItems = new(); 8 | 9 | public PancakeHouseMenu() 10 | { 11 | AddItem("K&B's Pancake Breakfast", "Pancake with scrambled eggs, and toast", true, 2.99m); 12 | AddItem("Regular Pancake Breakfast", "Pancakes with fried eggs, sausage", false, 2.99m); 13 | AddItem("Blueberry Pancakes", "Pancakes made with fresh blueberries", true, 3.49m); 14 | AddItem("Waffles", "Waffles, with your choice of blueberries or strawberries", true, 3.59m); 15 | } 16 | 17 | public void AddItem(string name, string description, bool vegetarian, decimal price) 18 | { 19 | _menuItems.Add(new MenuItem(name, description, vegetarian, price)); 20 | } 21 | 22 | public IIterator CreateIterator() 23 | { 24 | return new PancakeHouseMenuIterator(_menuItems); 25 | } 26 | } -------------------------------------------------------------------------------- /IteratorPattern/Program.cs: -------------------------------------------------------------------------------- 1 | using IteratorPattern.Menu; 2 | using IteratorPattern.Waitress; 3 | 4 | var pancakeHouseMenu = new PancakeHouseMenu(); 5 | var dinerMenu = new DinerMenu(); 6 | var waitress = new Waitress(pancakeHouseMenu, dinerMenu); 7 | waitress.PrintMenu(); 8 | Console.ReadKey(); 9 | -------------------------------------------------------------------------------- /IteratorPattern/Waitress/Waitress.cs: -------------------------------------------------------------------------------- 1 | using IteratorPattern.Iterator; 2 | using IteratorPattern.Menu; 3 | 4 | namespace IteratorPattern.Waitress; 5 | 6 | public class Waitress(IMenu pancakeHouseMenu, IMenu dinerMenu) 7 | { 8 | public void PrintMenu() 9 | { 10 | var pancakeIterator = pancakeHouseMenu.CreateIterator(); 11 | var dinerIterator = dinerMenu.CreateIterator(); 12 | Console.WriteLine("MENU\n------\nBREAKFAST"); 13 | PrintMenu(pancakeIterator); 14 | Console.WriteLine("\nLUNCH"); 15 | PrintMenu(dinerIterator); 16 | } 17 | 18 | private static void PrintMenu(IIterator iterator) 19 | { 20 | while (iterator.HasNext()) 21 | { 22 | var menuItem = (MenuItem?)iterator.Next(); 23 | if (menuItem == null) 24 | { 25 | break; 26 | } 27 | Console.WriteLine(menuItem.Name + ", " + menuItem.Price + ", " + menuItem.Description); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | 2 | Copyright (c) 2019, Changhui Xu 3 | 4 | Permission to use, copy, modify, and/or distribute this software for any 5 | purpose with or without fee is hereby granted, provided that the above 6 | copyright notice and this permission notice appear in all copies. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | -------------------------------------------------------------------------------- /ObserverPattern/CurrentConditionDisplay.cs: -------------------------------------------------------------------------------- 1 | namespace ObserverPattern; 2 | 3 | public class CurrentConditionDisplay : IObserver, IDisplayElement 4 | { 5 | private float _temperature; 6 | private float _humidity; 7 | 8 | public CurrentConditionDisplay(ISubject weatherData) 9 | { 10 | weatherData.RegisterObserver(this); 11 | } 12 | 13 | public void Update(float temp, float humidity, float pressure) 14 | { 15 | _temperature = temp; 16 | _humidity = humidity; 17 | Display(); 18 | } 19 | 20 | public void Display() 21 | { 22 | Console.WriteLine($"Current conditions: {_temperature}F degrees and {_humidity}% humidity"); 23 | } 24 | } -------------------------------------------------------------------------------- /ObserverPattern/ForecastDisplay.cs: -------------------------------------------------------------------------------- 1 | namespace ObserverPattern; 2 | 3 | public class ForecastDisplay : IObserver, IDisplayElement 4 | { 5 | private float _temperature; 6 | 7 | public ForecastDisplay(ISubject weatherData) 8 | { 9 | weatherData.RegisterObserver(this); 10 | } 11 | 12 | public void Update(float temp, float humidity, float pressure) 13 | { 14 | _temperature = temp; 15 | Display(); 16 | } 17 | 18 | public void Display() 19 | { 20 | Console.WriteLine($"Average temperature: {_temperature + 1}F degrees."); 21 | } 22 | } -------------------------------------------------------------------------------- /ObserverPattern/IDisplayElement.cs: -------------------------------------------------------------------------------- 1 | namespace ObserverPattern; 2 | 3 | public interface IDisplayElement 4 | { 5 | void Display(); 6 | } -------------------------------------------------------------------------------- /ObserverPattern/IObserver.cs: -------------------------------------------------------------------------------- 1 | namespace ObserverPattern; 2 | 3 | public interface IObserver 4 | { 5 | void Update(float temp, float humidity, float pressure); 6 | } -------------------------------------------------------------------------------- /ObserverPattern/ISubject.cs: -------------------------------------------------------------------------------- 1 | namespace ObserverPattern; 2 | 3 | public interface ISubject 4 | { 5 | void RegisterObserver(IObserver o); 6 | void RemoveObserver(IObserver o); 7 | void NotifyObservers(); 8 | } -------------------------------------------------------------------------------- /ObserverPattern/ObserverPattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ObserverPattern/Program.cs: -------------------------------------------------------------------------------- 1 | using ObserverPattern; 2 | 3 | var weatherData = new WeatherData(); 4 | var currentDisplay = new CurrentConditionDisplay(weatherData); 5 | var statisticsDisplay = new StatisticsDisplay(weatherData); 6 | var forecastDisplay = new ForecastDisplay(weatherData); 7 | 8 | weatherData.SetMeasurements(80, 65, 30.4f); 9 | weatherData.SetMeasurements(82, 70, 29.4f); 10 | weatherData.SetMeasurements(78, 80, 29.2f); 11 | 12 | Console.ReadKey(); 13 | -------------------------------------------------------------------------------- /ObserverPattern/StatisticsDisplay.cs: -------------------------------------------------------------------------------- 1 | namespace ObserverPattern; 2 | 3 | public class StatisticsDisplay : IObserver, IDisplayElement 4 | { 5 | private float _temperature; 6 | 7 | public StatisticsDisplay(ISubject weatherData) 8 | { 9 | weatherData.RegisterObserver(this); 10 | } 11 | 12 | public void Update(float temp, float humidity, float pressure) 13 | { 14 | _temperature = temp; 15 | Display(); 16 | } 17 | 18 | public void Display() 19 | { 20 | Console.WriteLine($"Average temperature: {_temperature}F degrees."); 21 | } 22 | } -------------------------------------------------------------------------------- /ObserverPattern/Weatherdata.cs: -------------------------------------------------------------------------------- 1 | namespace ObserverPattern; 2 | 3 | public class WeatherData : ISubject 4 | { 5 | private readonly List _observers = new(); 6 | private float _temperature; 7 | private float _humidity; 8 | private float _pressure; 9 | 10 | public void RegisterObserver(IObserver o) 11 | { 12 | _observers.Add(o); 13 | } 14 | 15 | public void RemoveObserver(IObserver o) 16 | { 17 | _observers.Remove(o); 18 | } 19 | 20 | public void NotifyObservers() 21 | { 22 | foreach (var observer in _observers) 23 | { 24 | observer.Update(_temperature, _humidity, _pressure); 25 | } 26 | } 27 | 28 | public void MeasurementsChanged() 29 | { 30 | NotifyObservers(); 31 | } 32 | 33 | public void SetMeasurements(float temperature, float humidity, float pressure) 34 | { 35 | _temperature = temperature; 36 | _humidity = humidity; 37 | _pressure = pressure; 38 | MeasurementsChanged(); 39 | } 40 | } -------------------------------------------------------------------------------- /ProxyPattern/Castle/CastleDynamicProxy.cs: -------------------------------------------------------------------------------- 1 | using Castle.DynamicProxy; 2 | 3 | namespace ProxyPattern.Castle; 4 | 5 | public class MyInterceptorAspect : IInterceptor 6 | { 7 | public void Intercept(IInvocation invocation) 8 | { 9 | var methodName = invocation.Method.Name; 10 | Console.WriteLine($"Before {methodName}"); 11 | invocation.Proceed(); 12 | Console.WriteLine($"After {methodName}"); 13 | } 14 | } 15 | 16 | public class CastleDynamicProxy 17 | { 18 | public virtual void DoStuff() 19 | { 20 | Console.WriteLine("Inside of DoStuff()"); 21 | } 22 | } 23 | 24 | public class MyOtherClass 25 | { 26 | public virtual void DoOtherStuff() 27 | { 28 | Console.WriteLine("Inside of DoOtherStuff()"); 29 | } 30 | } 31 | 32 | public static class CastleDynamicProxyTest 33 | { 34 | public static void Test() 35 | { 36 | var generator = new ProxyGenerator(); 37 | var myObject = generator.CreateClassProxy(new MyInterceptorAspect()); 38 | var myOtherObject = generator.CreateClassProxy(new MyInterceptorAspect()); 39 | 40 | myObject.DoStuff(); 41 | Console.WriteLine(); 42 | myOtherObject.DoOtherStuff(); 43 | } 44 | } -------------------------------------------------------------------------------- /ProxyPattern/Program.cs: -------------------------------------------------------------------------------- 1 | using ProxyPattern.Castle; 2 | 3 | CastleDynamicProxyTest.Test(); 4 | Console.ReadKey(); -------------------------------------------------------------------------------- /ProxyPattern/ProxyPattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /ProxyPattern/SimpleProxyPattern/SimpleImplementation.cs: -------------------------------------------------------------------------------- 1 | namespace ProxyPattern.SimpleProxyPattern; 2 | 3 | internal class ProxyContainer 4 | { 5 | private class ComplexProtectedExpensiveResource 6 | { 7 | internal void DoWork() 8 | { 9 | //do some heavy lifting 10 | } 11 | } 12 | 13 | // The Proxy 14 | public class SimpleProxy(string password) 15 | { 16 | private ComplexProtectedExpensiveResource? _complexProtectedResource; 17 | 18 | public void DoWork() 19 | { 20 | if (Authenticate()) 21 | { 22 | _complexProtectedResource?.DoWork(); 23 | } 24 | } 25 | 26 | bool Authenticate() 27 | { 28 | //authenticate request 29 | if (password == "password") 30 | { 31 | //create expensive object if authenticated 32 | _complexProtectedResource ??= new ComplexProtectedExpensiveResource(); 33 | return true; 34 | } 35 | return false; 36 | } 37 | } 38 | } 39 | 40 | // The Client 41 | internal class ProxyPattern : ProxyContainer 42 | { 43 | public static void DoWork() 44 | { 45 | var simpleProxy = new SimpleProxy("password"); 46 | simpleProxy.DoWork(); 47 | } 48 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HeadFirstDesignPattern Head First Design Pattern: my notes taken from the book and exercises that I practiced. --- Table of contents =========== {:toc} ## 1 Strategy Pattern ### 1 Strategy Strategy defines a family of algorithms, encapsulates each one, and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it. ### 2 Shared language Patterns provide a shared language that can maximize the value of your communication with other developers. ## 2 Observer Pattern ### Design Principles * Identify the aspects of your application that vary and separate them from what stays the same. * The thing that varies in the Observer Pattern is the state of the Subject and the number and types of Observers. With this pattern, you can vary the objects that are dependent on the state of the Subject, without having to change that Subject. That's called planning ahead. * Program to an interface, not an implementation. * Both the Subject and Observer use interfaces. The Subject keeps track of objects implementing the Observer interface, while the observers register with and get notified by, the Subject interface. This keeps things nice and loosely coupled. * Favor composition over inheritance. * The Observer Pattern uses composition to compose any number of Observers with their Subjects. These relationships aren't set up by some kind of inheritance hierarchy. No, they are set up at runtime by composition. ## 3 Factory Pattern ### The Factory Method Pattern *The Factory Method Pattern* defines an interface for creating an object, but lets subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses. ### Design Principle * *Dependency Inversion Principle*: Depend upon abstractions. Do not depend upon concrete classes. ### The Abstract Factory Pattern *The Abstract Factory Pattern* provides an interface for creating families of related or dependent objects without specifying their concrete classes. ## 4 Singleton Pattern *The Singleton Pattern* ensures a class has only one instance, and provides a global point of access of it. ## 5 Command Pattern *The Command Pattern* encapsulates a request as an object, thereby letting you parameterize other objects with different requests, queue or log requests, and support undoable operations. ## 6 Adapter Pattern *The Adapter Pattern* converts the interface of a class into another interface the clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces. *The Façade Pattern* provides a unified interface to a set of interfaces in a subsystem. Façade defines a higher-level interface that makes the subsystem easier to use. ## 7 Template Method Pattern *The Template Method Pattern* defines the steps of an algorithm and allows subclasses to provide the implementation for one or more steps. *The Template Method Pattern* defines the skeleton of an algorithm in a method, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure. ## 8 Iterator Pattern *The Iterator Pattern* provides a way to access the elements of an aggregate object sequentially without exposing its underlying representation. ## 9 Composite Pattern *The Composite Pattern* allows you to compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly. ## 10 State Pattern *The State Pattern* allows an object to alter its behavior when its internal state changes. The object will appear to change its class. ## 11 Proxy Pattern *The Proxy Pattern* provides a surrogate or placeholder for another object to control access to it. Use the Proxy Pattern to create a representative object that controls access to another object, which may be remote, expensive to create or in need of securing. ## 12 Compound Pattern Patterns are often used together and combined within the same design solution. A *compound pattern* combines two or more patterns into a solution that solves a recurring or general problem. ## Summary **A Pattern** is a solution to a problem in a context. The *context* is the situation in which the pattern applies. This should be a recurring situation. The *problem* refers to the goal you are trying to achieve in this context, but it also refers to any constraints that occur in the context. The *solution* is what you're after: a general design that anyone can apply which resolves the goal and set of constraints. -------------------------------------------------------------------------------- /SingletonPattern/ChocolateBoiler.cs: -------------------------------------------------------------------------------- 1 | namespace SingletonPattern; 2 | 3 | public class ChocolateBoiler 4 | { 5 | private static readonly Lazy Lazy = new(() => new ChocolateBoiler()); 6 | 7 | public static ChocolateBoiler Instance => Lazy.Value; 8 | 9 | private ChocolateBoiler() 10 | { 11 | Empty = true; 12 | Boiled = false; 13 | } 14 | 15 | private bool Empty { get; set; } 16 | private bool Boiled { get; set; } 17 | 18 | public void Fill() 19 | { 20 | if (!Empty) 21 | { 22 | Console.WriteLine(); 23 | return; 24 | } 25 | Empty = false; 26 | Boiled = false; 27 | Console.WriteLine("Fill the boiler with a milk/chocolate mixture."); 28 | } 29 | 30 | public void Drain() 31 | { 32 | if (Empty || !Boiled) 33 | { 34 | Console.WriteLine(); 35 | return; 36 | } 37 | Console.WriteLine("Drain the boiled milk and chocolate."); 38 | Empty = true; 39 | } 40 | 41 | public void Boil() 42 | { 43 | if (Empty || Boiled) 44 | { 45 | Console.WriteLine(); 46 | return; 47 | } 48 | Console.WriteLine("Bring the contents to a boil."); 49 | Boiled = true; 50 | } 51 | } -------------------------------------------------------------------------------- /SingletonPattern/Program.cs: -------------------------------------------------------------------------------- 1 | using SingletonPattern; 2 | 3 | var boiler1 = ChocolateBoiler.Instance; 4 | var boiler2 = ChocolateBoiler.Instance; 5 | var boiler3 = ChocolateBoiler.Instance; 6 | Console.Write("boiler1\n\t"); 7 | boiler1.Fill(); 8 | Console.Write("boiler3\n\t"); 9 | boiler3.Fill(); 10 | Console.Write("boiler1\n\t"); 11 | boiler1.Boil(); 12 | Console.Write("boiler2\n\t"); 13 | boiler2.Fill(); 14 | Console.Write("boiler2\n\t"); 15 | boiler2.Drain(); 16 | Console.Write("boiler2\n\t"); 17 | boiler2.Fill(); 18 | Console.Write("boiler1\n\t"); 19 | boiler1.Drain(); 20 | Console.Write("boiler1\n\t"); 21 | boiler1.Boil(); 22 | Console.Write("boiler2\n\t"); 23 | boiler2.Drain(); 24 | 25 | Console.ReadKey(); -------------------------------------------------------------------------------- /SingletonPattern/SingletonPattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /StatePattern/GumballMachines/GumballMachine.cs: -------------------------------------------------------------------------------- 1 | using StatePattern.States; 2 | using System.Text; 3 | 4 | namespace StatePattern.GumballMachines; 5 | 6 | public class GumballMachine 7 | { 8 | private readonly IState _soldOutState; 9 | private readonly IState _noQuarterState; 10 | private readonly IState _hasQuarterState; 11 | private readonly IState _soldState; 12 | private readonly IState _winnerState; 13 | private IState _state = null!; 14 | public int Count { get; private set; } 15 | 16 | public GumballMachine(int numberOfGumballs) 17 | { 18 | _soldOutState = new SoldOutState(this); 19 | _noQuarterState = new NoQuarterState(this); 20 | _hasQuarterState = new HasQuarterState(this); 21 | _soldState = new SoldState(this); 22 | _winnerState = new WinnerState(this); 23 | Count = numberOfGumballs; 24 | if (numberOfGumballs > 0) 25 | { 26 | _state = _noQuarterState; 27 | } 28 | } 29 | 30 | public void SetState(IState state) 31 | { 32 | _state = state; 33 | } 34 | 35 | public IState GetHasQuarterState() 36 | { 37 | return _hasQuarterState; 38 | } 39 | 40 | public IState GetSoldOutState() 41 | { 42 | return _soldOutState; 43 | } 44 | 45 | public IState GetSoldState() 46 | { 47 | return _soldState; 48 | } 49 | 50 | public IState GetNoQuarterState() 51 | { 52 | return _noQuarterState; 53 | } 54 | 55 | public IState GetWinnerState() 56 | { 57 | return _winnerState; 58 | } 59 | 60 | public void InsertQuarter() 61 | { 62 | _state.InsertQuarter(); 63 | } 64 | 65 | public void EjectQuarter() 66 | { 67 | _state.EjectQuarter(); 68 | } 69 | 70 | public void TurnCrank() 71 | { 72 | _state.TurnCrank(); 73 | _state.Dispense(); 74 | } 75 | 76 | public void ReleaseBall() 77 | { 78 | Console.WriteLine("A gumball comes rolling out the slot..."); 79 | if (Count != 0) 80 | { 81 | Count--; 82 | } 83 | } 84 | 85 | public override string ToString() 86 | { 87 | var sb = new StringBuilder(); 88 | sb.AppendLine("\nMighty Gumball, Inc."); 89 | sb.AppendLine($"Inventory: {Count} gumballs."); 90 | sb.AppendLine(_state == _soldOutState ? "Machine is sold out." : "Machine is waiting for quarter."); 91 | return sb.ToString(); 92 | } 93 | } -------------------------------------------------------------------------------- /StatePattern/Program.cs: -------------------------------------------------------------------------------- 1 | using StatePattern.GumballMachines; 2 | 3 | var gumballMachine = new GumballMachine(5); 4 | Console.WriteLine(gumballMachine); 5 | 6 | gumballMachine.InsertQuarter(); 7 | gumballMachine.TurnCrank(); 8 | Console.WriteLine(gumballMachine); 9 | 10 | gumballMachine.InsertQuarter(); 11 | gumballMachine.TurnCrank(); 12 | gumballMachine.InsertQuarter(); 13 | gumballMachine.TurnCrank(); 14 | Console.WriteLine(gumballMachine); 15 | 16 | Console.ReadKey(); -------------------------------------------------------------------------------- /StatePattern/StatePattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /StatePattern/States/HasQuarterState.cs: -------------------------------------------------------------------------------- 1 | using StatePattern.GumballMachines; 2 | 3 | namespace StatePattern.States; 4 | 5 | public class HasQuarterState(GumballMachine gumballMachine) : IState 6 | { 7 | private readonly Random _randomWinner = new(); 8 | 9 | public void InsertQuarter() 10 | { 11 | Console.WriteLine("You can't insert another quarter."); 12 | } 13 | 14 | public void EjectQuarter() 15 | { 16 | Console.WriteLine("Quarter returned."); 17 | gumballMachine.SetState(gumballMachine.GetNoQuarterState()); 18 | } 19 | 20 | public void TurnCrank() 21 | { 22 | Console.WriteLine("You turned..."); 23 | var winner = _randomWinner.Next(10); 24 | if (winner == 0 && gumballMachine.Count > 1) 25 | { 26 | gumballMachine.SetState(gumballMachine.GetWinnerState()); 27 | } 28 | else 29 | { 30 | gumballMachine.SetState(gumballMachine.GetSoldState()); 31 | } 32 | } 33 | 34 | public void Dispense() 35 | { 36 | Console.WriteLine("No gumball dispensed."); 37 | } 38 | } -------------------------------------------------------------------------------- /StatePattern/States/IState.cs: -------------------------------------------------------------------------------- 1 | namespace StatePattern.States; 2 | 3 | public interface IState 4 | { 5 | void InsertQuarter(); 6 | void EjectQuarter(); 7 | void TurnCrank(); 8 | void Dispense(); 9 | } -------------------------------------------------------------------------------- /StatePattern/States/NoQuarterState.cs: -------------------------------------------------------------------------------- 1 | using StatePattern.GumballMachines; 2 | 3 | namespace StatePattern.States; 4 | 5 | public class NoQuarterState(GumballMachine gumballMachine) : IState 6 | { 7 | public void InsertQuarter() 8 | { 9 | Console.WriteLine("You inserted a quarter."); 10 | gumballMachine.SetState(gumballMachine.GetHasQuarterState()); 11 | } 12 | 13 | public void EjectQuarter() 14 | { 15 | Console.WriteLine("You haven't inserted a quarter."); 16 | } 17 | 18 | public void TurnCrank() 19 | { 20 | Console.WriteLine("You turned, but there's no quarter."); 21 | } 22 | 23 | public void Dispense() 24 | { 25 | Console.WriteLine("You need to pay first."); 26 | } 27 | } -------------------------------------------------------------------------------- /StatePattern/States/SoldOutState.cs: -------------------------------------------------------------------------------- 1 | using StatePattern.GumballMachines; 2 | 3 | namespace StatePattern.States; 4 | 5 | public class SoldOutState(GumballMachine gumballMachine) : IState 6 | { 7 | private readonly GumballMachine _gumballMachine = gumballMachine; 8 | 9 | public void InsertQuarter() 10 | { 11 | Console.WriteLine("You cannot insert a quarter, the machine is sold out."); 12 | } 13 | 14 | public void EjectQuarter() 15 | { 16 | Console.WriteLine("You cannot eject, you haven't inserted a quarter yet."); 17 | } 18 | 19 | public void TurnCrank() 20 | { 21 | Console.WriteLine("You turned, but there are no gumballs."); 22 | } 23 | 24 | public void Dispense() 25 | { 26 | Console.WriteLine("No gumball dispensed."); 27 | } 28 | } -------------------------------------------------------------------------------- /StatePattern/States/SoldState.cs: -------------------------------------------------------------------------------- 1 | using StatePattern.GumballMachines; 2 | 3 | namespace StatePattern.States; 4 | 5 | public class SoldState(GumballMachine gumballMachine) : IState 6 | { 7 | public void InsertQuarter() 8 | { 9 | Console.WriteLine("Please wait, we're already giving you a gumball."); 10 | } 11 | 12 | public void EjectQuarter() 13 | { 14 | Console.WriteLine("Sorry, you already turned the crank."); 15 | } 16 | 17 | public void TurnCrank() 18 | { 19 | Console.WriteLine("Turning twice doesn't get you another gumball."); 20 | } 21 | 22 | public void Dispense() 23 | { 24 | gumballMachine.ReleaseBall(); 25 | if (gumballMachine.Count > 0) 26 | { 27 | gumballMachine.SetState(gumballMachine.GetNoQuarterState()); 28 | } 29 | else 30 | { 31 | Console.WriteLine("Oops, out of gumballs!"); 32 | gumballMachine.SetState(gumballMachine.GetSoldOutState()); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /StatePattern/States/WinnerState.cs: -------------------------------------------------------------------------------- 1 | using StatePattern.GumballMachines; 2 | 3 | namespace StatePattern.States; 4 | 5 | public class WinnerState(GumballMachine gumballMachine) : IState 6 | { 7 | public void InsertQuarter() 8 | { 9 | Console.WriteLine("Please wait, we're already giving you a gumball."); 10 | } 11 | 12 | public void EjectQuarter() 13 | { 14 | Console.WriteLine("Sorry, you already turned the crank."); 15 | } 16 | 17 | public void TurnCrank() 18 | { 19 | Console.WriteLine("Turning twice doesn't get you another gumball."); 20 | } 21 | 22 | public void Dispense() 23 | { 24 | Console.WriteLine("You are a WINNER! You get two gumballs for your quarter."); 25 | gumballMachine.ReleaseBall(); 26 | if (gumballMachine.Count > 0) 27 | { 28 | gumballMachine.ReleaseBall(); 29 | if (gumballMachine.Count > 0) 30 | { 31 | gumballMachine.SetState(gumballMachine.GetNoQuarterState()); 32 | } 33 | else 34 | { 35 | Console.WriteLine("Oops, out of gumballs!"); 36 | gumballMachine.SetState(gumballMachine.GetSoldOutState()); 37 | 38 | } 39 | } 40 | else 41 | { 42 | gumballMachine.SetState(gumballMachine.GetSoldOutState()); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /StrategyPattern/Duck/Duck.cs: -------------------------------------------------------------------------------- 1 | namespace StrategyPattern.Duck; 2 | 3 | public abstract class Duck(IFly flyBehavior, IQuack quackBehavior) 4 | { 5 | protected IFly FlyBehavior = flyBehavior; 6 | protected IQuack QuackBehavior = quackBehavior; 7 | 8 | public void Swim() 9 | { 10 | Console.WriteLine("All ducks float, even decoys."); 11 | } 12 | 13 | public abstract void Display(); 14 | 15 | public void PerformFly() 16 | { 17 | FlyBehavior.Fly(); 18 | } 19 | 20 | public void PerformQuack() 21 | { 22 | QuackBehavior.Quack(); 23 | } 24 | 25 | public void SetFlyBehavior(IFly fb) 26 | { 27 | FlyBehavior = fb; 28 | } 29 | 30 | public void SetQuackBehavior(IQuack qb) 31 | { 32 | QuackBehavior = qb; 33 | } 34 | } -------------------------------------------------------------------------------- /StrategyPattern/Duck/Fly.cs: -------------------------------------------------------------------------------- 1 | namespace StrategyPattern.Duck; 2 | 3 | public interface IFly 4 | { 5 | void Fly(); 6 | } 7 | 8 | public class FlyWithWings : IFly 9 | { 10 | public void Fly() 11 | { 12 | Console.WriteLine("I'm flying."); 13 | } 14 | } 15 | 16 | public class FlyNoWay : IFly 17 | { 18 | public void Fly() 19 | { 20 | Console.WriteLine("I can't fly."); 21 | } 22 | } 23 | 24 | public class FlyRocketPowered : IFly 25 | { 26 | public void Fly() 27 | { 28 | Console.WriteLine("I'm flying with a rocket."); 29 | } 30 | } 31 | 32 | public readonly record struct SimpleValueChange(string PropertyName, string OldValue, string NewValue); -------------------------------------------------------------------------------- /StrategyPattern/Duck/MallardDuck.cs: -------------------------------------------------------------------------------- 1 | namespace StrategyPattern.Duck; 2 | 3 | public class MallardDuck() : Duck(new FlyWithWings(), new CanQuack()) 4 | { 5 | public override void Display() 6 | { 7 | Console.WriteLine("I'm a real Mallard duck"); 8 | } 9 | } -------------------------------------------------------------------------------- /StrategyPattern/Duck/ModelDuck.cs: -------------------------------------------------------------------------------- 1 | namespace StrategyPattern.Duck; 2 | 3 | public class ModelDuck() : Duck(new FlyNoWay(), new Squeak()) 4 | { 5 | public override void Display() 6 | { 7 | Console.WriteLine("I'm a model duck"); 8 | } 9 | } -------------------------------------------------------------------------------- /StrategyPattern/Duck/Quack.cs: -------------------------------------------------------------------------------- 1 | namespace StrategyPattern.Duck; 2 | 3 | public interface IQuack 4 | { 5 | void Quack(); 6 | } 7 | 8 | public class CanQuack : IQuack 9 | { 10 | public void Quack() 11 | { 12 | Console.WriteLine("Quack."); 13 | } 14 | } 15 | 16 | public class MuteQuack : IQuack 17 | { 18 | public void Quack() 19 | { 20 | Console.WriteLine("<>"); 21 | } 22 | } 23 | 24 | public class Squeak : IQuack 25 | { 26 | public void Quack() 27 | { 28 | Console.WriteLine("Squeak"); 29 | } 30 | } -------------------------------------------------------------------------------- /StrategyPattern/Program.cs: -------------------------------------------------------------------------------- 1 | using StrategyPattern.Duck; 2 | 3 | var b = true.ToString(); 4 | Console.WriteLine(b); 5 | var a = bool.TrueString; 6 | Console.WriteLine(a); 7 | if (a == b) 8 | { 9 | 10 | } 11 | var mallard = new MallardDuck(); 12 | mallard.Display(); 13 | mallard.PerformFly(); 14 | mallard.PerformQuack(); 15 | 16 | var model = new ModelDuck(); 17 | model.Display(); 18 | model.PerformFly(); 19 | model.PerformQuack(); 20 | Console.WriteLine("---------\r\n>>> powered by rocket."); 21 | model.SetFlyBehavior(new FlyRocketPowered()); 22 | model.PerformFly(); 23 | 24 | Console.ReadKey(); -------------------------------------------------------------------------------- /StrategyPattern/StrategyPattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | --------------------------------------------------------------------------------