5
\$\begingroup\$

I am working on going through "Head First Design Patterns" and I am trying to properly convert the Java code into C#. Here is what I have. Can you tell me if this is a good implementation/conversion so far?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Duck
{
    public abstract class Duck
    {
        public FlyBehavior flyBehavior;
        public QuackBehavior quackBehavior;
        public Duck(){

        }

        public abstract void display();

        public void performFly()
        {
            flyBehavior.fly();
        }

        public void performQuack()
        {
            quackBehavior.quack();
        }

        public void swim()
        {
            Console.WriteLine("All ducks float, even decoys!");
        }
    }

    public interface FlyBehavior
    {
        void fly();
    }

    public class FlyWithWings : FlyBehavior
    {
        public void fly()
        {
            Console.WriteLine("I'm flying!");
        }
    }

    public class FlyNoWay : FlyBehavior
    {
        public void fly()
        {
            Console.WriteLine("I can't fly!");
        }
    }

    public interface QuackBehavior
    {
        void quack();
    }

    public class Quack : QuackBehavior
    {
        public void quack()
        {
            Console.WriteLine("Quack");
        }
    }

    public class MuteQuack : QuackBehavior
    {
        public void quack()
        {
            Console.WriteLine("<<  Silence  >>");
        }
    }

    public class Squeak : QuackBehavior
    {
        public void quack()
        {
            Console.WriteLine("Squeak");
        }
    }

    public class MallardDuck : Duck
    {
        public MallardDuck()
        {
            quackBehavior = new Quack();
            flyBehavior = new FlyWithWings();
        }

        public override void display()
        {
            Console.WriteLine("I'm a real Mallard duck");
        }
    }

    public class MiniDuckSimulator
    {
        public static void Main(string[] args)
        {
            Duck mallard = new MallardDuck();
            mallard.performQuack();
            mallard.performFly();
            Console.ReadLine();
        }
    }
}
\$\endgroup\$
6
\$\begingroup\$

public fields are a bit of a no-no since that violates encapsulation. So I've changed the fields to private readonly and inject those dependencies via the constructor. Speaking of constructor, I made it protected as a public constructor on an abstract class doesn't make much sense. Also, make note of C# naming conventions which PascalCase's methods and that interfaces should start with "I":

using System;

namespace Duck
{
    public abstract class Duck
    {
        private readonly IFlyBehavior flyBehavior;
        private readonly IQuackBehavior quackBehavior;
        protected Duck(IFlyBehavior flyBehavior, IQuackBehavior quackBehavior)
        {
            this.flyBehavior = flyBehavior;
            this.quackBehavior = quackBehavior;
        }

        public abstract void Display();

        public void PerformFly()
        {
            this.flyBehavior.Fly();
        }

        public void PerformQuack()
        {
            this.quackBehavior.Quack();
        }

        public void Swim()
        {
            Console.WriteLine("All ducks float, even decoys!");
        }
    }

    public interface IFlyBehavior
    {
        void Fly();
    }

    public class FlyWithWings : IFlyBehavior
    {
        public void Fly()
        {
            Console.WriteLine("I'm flying!");
        }
    }

    public class FlyNoWay : IFlyBehavior
    {
        public void Fly()
        {
            Console.WriteLine("I can't fly!");
        }
    }

    public interface IQuackBehavior
    {
        void Quack();
    }

    public class Quack : IQuackBehavior
    {
        public void Quack()
        {
            Console.WriteLine("Quack");
        }
    }

    public class MuteQuack : IQuackBehavior
    {
        public void Quack()
        {
            Console.WriteLine("<<  Silence  >>");
        }
    }

    public class Squeak : IQuackBehavior
    {
        public void Quack()
        {
            Console.WriteLine("Squeak");
        }
    }

    public class MallardDuck : Duck
    {
        public MallardDuck() : base(new FlyWithWings(), new Quack())
        {
        }

        public override void Display()
        {
            Console.WriteLine("I'm a real Mallard duck");
        }
    }

    public class MiniDuckSimulator
    {
        public static void Main(string[] args)
        {
            Duck mallard = new MallardDuck();
            mallard.PerformQuack();
            mallard.PerformFly();
            Console.ReadLine();
        }
    }
}
\$\endgroup\$
  • \$\begingroup\$ Thanks guys! I am going to look over both your answers, but I really appreciate that you took the time to explain in such depth. I am working hard to learn these design patterns and input like this is going to just speed up the process. \$\endgroup\$ – Michael Mahony Aug 5 '13 at 16:21
  • 1
    \$\begingroup\$ Yes, I am aware that if this was a production application each class would be its own file, but since this is just to learn a strategy pattern in C# I have kept them all in the same file. The changes made by Jesse are perfect and make the code cleaner and safer, so thanks for that. I am studying it will get back to you guys if I have any questions. Thanks a million! \$\endgroup\$ – Michael Mahony Aug 5 '13 at 16:29
3
\$\begingroup\$

Oddly enough, in the Microsoft C# world, PascalCasing (as opposed to camelCasing) doesn't just apply to classes, but also to public fields, public methods, and public properties.

So maybe you might want to rename Duck.flyBehavior to Duck.FlyBehavior, Duck.quackBehavior to Duck.QuackBehavior, etc.

While you're at it, since those are public fields, you might also want to switch those to C# properties, instead, in case you ever needed the added functionality of sanitizing input.

before

public FlyBehavior FlyBahavior

after*

public FlyBehavior FlyBehavior { get; set; }

Although, I still write C# the old school way, but if things haven't changed, I think interfaces still are prefixed with a capital I. So your FlyBehavior interface will be named IFlyBehavior. Same thing for QuackBehavior; it will become IQuackBehavior.

Another pedantic remark: although I have a hunch that you already know this, but classes should be in their own file*. I'm just saying, in case my hunch was wrong, and you didn't know.

* Disclaimer: I'm not exactly sure why separating classes into files is considered important. And I am in no way saying that it isn't important, just that if you want to know why, I'm afraid I can only give you my own intuition as to why I think it's important to separate classes into their own file.

\$\endgroup\$
  • \$\begingroup\$ "Disclaimer: I'm not exactly sure why separating classes into files is considered important." Pretty certain it's purely organisational - it's easier to find public abstract class Duck when the file is called Duck.cs rather than if everything is in MyProgram.cs, or separated into Stuff1.cs, Stuff2.cs etc - easier to find the file and easier to find the location in the file where the class starts (the beginning). Edit: I think in Java each class has to be a separate file due to the way the compiler works (it expects Duck.java to contain Duck). Might be wrong on that though. \$\endgroup\$ – Kai Aug 5 '13 at 8:11
  • \$\begingroup\$ Although I personally employ an amount of flexibility in C# - if I've got small, related classes, I'll often dump them into the same file because they'll still be easy to find - in this case, I'd stick FlyBehaivour and its implementations in the same file because they're so small and tightly related. \$\endgroup\$ – Kai Aug 5 '13 at 8:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.