- Strategy Pattern SimUDuck Introduction
- SimUDuck WPF Code
This post follows chapter one Intro to Design Patterns of the book called Head First Design Patterns. I will write the code in C# using Visual Studio Community 2019 in a Windows Presentation Foundation project. The code in the book is Java, but the languages are so similar that I was able to write it in C# quite easily. This post just gets the code started. In the next post, I will finish the chapter by writing the rest of the code in C#. If you want to work in Java you can download the code from the book’s website.
Design Patters are not the basics of programming. Suppose you know the basics of OO programming: abstraction, encapsulation, polymorphism, and inheritance. You’re certainly not an expert, but you’ve written at least some code that uses these class techniques. If you also know a bit about OO principles such as “encapsulate what varies”, “favor composition over inheritance” and “program to interfaces, not implementations”, then you are ready for OO design patterns. Code the SimUDuck application and therefore discover your first design pattern: Strategy.
Here is what the WPF program looks like.
Here is the XAML code. Feel free to copy it to your own C# project. The code below is a WPF project, but you could create a console project and adopt the code for that if you wish. That’s a lot of TextBlocks. Look at Decorator Starbuzz Code to see how we just used TxtBlk2.Text to simply append the output.
<Window x:Class="SimUDuck.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:SimUDuck" mc:Ignorable="d" Title="SimUDuck HeadFirst Design Patterns" Height="350" Width="500"> <StackPanel Margin="10"> <TextBlock>Welcome.</TextBlock> <TextBlock x:Name="txtBlk"></TextBlock> <TextBlock x:Name="txtBlk2"></TextBlock> <TextBlock x:Name="txtBlk3"></TextBlock> <TextBlock x:Name="txtBlk4"></TextBlock> <TextBlock x:Name="txtBlk5"></TextBlock> <TextBlock x:Name="txtBlk6"></TextBlock> <TextBlock x:Name="txtBlk7"></TextBlock> <TextBlock x:Name="txtBlk8"></TextBlock> <TextBlock x:Name="txtBlk9"></TextBlock> <TextBlock x:Name="txtBlk10"></TextBlock> <TextBlock x:Name="txtBlk11"></TextBlock> <TextBlock x:Name="txtBlk12"></TextBlock> </StackPanel> </Window>
Below is the C# code behind. It site behind the XAML listed above.
using System.Windows; namespace SimUDuck { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); Duck duck = new Duck(); txtBlk.Text = duck.quack(); txtBlk.Text += duck.swim(); MallardDuck mallard = new MallardDuck(); txtBlk3.Text = mallard.display(); txtBlk4.Text = mallard.quack(); RubberDuck rubber = new RubberDuck(); txtBlk7.Text = rubber.display(); txtBlk8.Text = rubber.swim(); txtBlk9.Text = rubber.fly(); // override txtBlk10.Text = rubber.quack(); // override } } }
We know that each type of duck looks different, so the display method is part of each derived class, not the parent/base class. The quack sounds will be the same so the quack() method will be part of the base class, along with the swim() method. Also, the fly() method is always the same so the fly() method will be part of the base/parent class. The subclasses will inherit from the base class. Our subclasses will be MallardDuck and RedheadDuck. Things work great until we have some unexpected changes to the specifications. We must add a RubberDuck. The problem is that rubber ducks don’t. Below is our code in C#.
namespace SimUDuck { public class Duck { public virtual string quack() { return " quack quack quacking..."; } public string swim() { return " duck is swim swim swimming..."; } public virtual string fly() { return " swoosh swoosh flying... "; } } }
Below is our subclass MallardDuck that inherits from Duck. This duck can display, quack, swim, and fly. That’s good.
namespace SimUDuck { class MallardDuck : Duck { public string display() { return " displaying Mallard Duck... "; } } }
Below is our RubberDuck class. It inherits from Duck and because of that it can fly and quack. The problem is that rubber ducks cannot fly or quack. They can squeak instead of quack. We’ve added the virtual keyword into our Duck class so that we can override the code quack and fly. What if we later need to add a DecoyDuck that does absolutely nothing. All we need to do is display it. It doesn’t even swim. It floats because it’s wooden. We have a maintenance problem. We’ve got ducks inheriting behavior that they should not have. Each time we add a new duck we’ve got to check to see if we need to override something. Even worst than that, what if all ducks fly in their own way. Some are better flyers than others.
namespace SimUDuck { class RubberDuck : Duck { public string display() { return " showing Rubber Ducks... "; } public override string quack() { return squeak(); } private string squeak() { return " squeak squeak squeak... "; } public override string fly() { return ""; // rubber ducks don't fly } } }