设计模式-入门
本文为HeadFirst读书笔记
需求
设计一个鸭子模拟游戏,其中有各种不同类型的鸭子,有不同行为,如呱呱叫,游泳。
public abstract class Duck
{
public abstract void Display();
public void Quack()
{
Console.WriteLine("quack");
}
public void Swim()
{
Console.WriteLine("I'm swiming");
}
}
需求变更:新增功能,让鸭子飞
- 思路一:在基类
Duck
中新增Fly()
方法。
在Duck
基类中增加Fly()
方法,所有鸭子都会继承Fly()
方法。但是并不是所有的鸭子都会飞,比如橡皮鸭子。 - 思路二:把
Fly()
从基类中抽取出来,放进一个Flyable
接口中,这么一来,只有会飞的鸭子才会实现此接口。但是这并不是一个好办法,这回导致重复代码变多。比如有48个Duck的子类都需要修改一下飞行行为,那如何处理?
继承并不能很好的解决此问题,因为鸭子的行为在子类中不断改变,并且让所有的子类都有这些行为是不恰当的。
Flyable
接口一开始似乎是很不错,解决了问题(只有会飞的鸭子才能继承Flyable
)。但是C#中接口不具代码实现,所以实现接口无法达到代码的服用。这就是说,假如你修改了某个行为,比如飞行行为,你必须在每一个类中跟踪修改飞行行为。
设计原则1
找出应用中可能需要变化之处,把他们独立出来,不要和那些不需要变化的代码混在一起。换言之,每次新需求一来,都会使某些方面的代码发生变化,那么此时就需要把这部分代码抽出来,和其他稳定部分有所区别。
分开变化和不会变化的部分
变化部分:Fly
,Quack
。为了分开变化部分和不会变化部分,鸭子的Fly
和Quack
会随鸭子的不同而改变。因此我们准备建立两组类,一个实现飞行,一个实现叫声。
设计原则2
针对接口编程,而不是针对实现编程。
我们利用接口代表每个行为,比如FlyBehavior
表示飞行行为,QuackBehavior
表示鸭子叫的行为。所以鸭子类不会实现这两个接口,而有其他行为类实现这俩接口。以前的做法是:行为来自Duck的基类的具体实现,或者基类继承某个接口然后又子类实现。这两种做法都依赖于实现。如下:
飞行行为接口及实现
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 class FlyRocketPowered : FlyBehavior
{
public void Fly()
{
Console.WriteLine("I'm flying with a rocket!");
}
}
叫声行为接口及实现
public interface QuackBehavior
{
void Quack();
}
public class CommonQuack : 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 abstract class Duck
{
protected FlyBehavior flyBehavior;
protected QuackBehavior quackBehavior;
public Duck()
{
}
public abstract void Display();
public void performFly()
{
flyBehavior.Fly();
}
public void performQuack()
{
quackBehavior.Quack();
}
public void Swim()
{
Console.WriteLine("swiming");
}
public void SetFlyBehavior(FlyBehavior fb)
{
flyBehavior = fb;
}
public void SetQuackBehavior(QuackBehavior qb)
{
quackBehavior = qb;
}
}
鸭子子类:绿头鸭
public class MallardDuck : Duck
{
public MallardDuck()
{
flyBehavior = new FlyWithWings();
quackBehavior = new CommonQuack();
}
public override void Display()
{
Console.WriteLine("I'm a real Mallard duck");
}
}
鸭子子类:模型鸭
public class ModelDuck : Duck
{
public ModelDuck()
{
flyBehavior = new FlyNoWay();
quackBehavior = new CommonQuack();
}
public override void Display()
{
Console.WriteLine("I'm a model duck");
}
}