1. 先做一个不那么恰当的例子
//1.先做一个Duck class
public abstract class SimUDuck
{
void quack()
{
Console.WriteLine("鸭子都会嘎嘎叫");
}
void swim()
{
Console.WriteLine("鸭子都会游泳");
}
public abstract void display();//每个鸭子类型看起来都不一样,所以做成抽象方法
//这样写在父类里面,那么不能飞的鸭子也继承了飞的行为,如下写是不对的:
//void fly()
//{
// Console.WriteLine("新增的需求:让某些鸭子能飞");
//}
public abstract void fly();//让子类自己去判断能不能飞,但是这样代码量会变大,因为每一个继承它的子类都要复写一遍这个方法
}
class MallardDuck : SimUDuck
{
public override void display()
{
Console.WriteLine("看起来像绿头鸭");
}
public override void fly()
{
Console.WriteLine("绿头鸭会飞");
}
}
class RedHeadDuck : SimUDuck
{
public override void display()
{
Console.WriteLine("看起来像红头鸭");
}
public override void fly()
{
Console.WriteLine("红头鸭会飞");
}
}
class RubberDuck : SimUDuck
{
public override void display()
{
Console.WriteLine("看起来像橡皮鸭");
}
public override void fly()
{
Console.WriteLine("橡皮鸭会飞的方法写成空,表示橡皮鸭不能飞");//代码量会变大,因为每一个继承它的子类都要复写一遍这个方法,这样也是不行的
}
}
在上面的例子里面:
- 鸭子的叫声和游泳可能也是变化的,在父类中写定了是不行的
- 如果在父类中写定一个飞的实例方法,子类继承后,那么本来不应该会飞的子类也有了会飞的特性了。
- 如果父类方法全部做成抽象类,每一次子类的继承就要去重写一遍父类方法,就算有些鸭子不会飞,那也要重写为不会飞,这也是很低效的。
2. 用接口和算法簇实现
//1.先做一个Duck class
public abstract class SimUDuck
{
//声明接口的引用关联关系
public IFlyBehavior flyBehavior;
public IQuackBehavior quackBehavior;
public void performFly()//父类不具体实现飞的方法,委托给接口
{
flyBehavior.fly();
}
public void performQuack() //父类不具体实现叫的方法,委托给接口
{
quackBehavior.quack();
}
void swim()//所有父类和子类都一致的方法
{
Console.WriteLine("鸭子都会游泳");
}
public void setFlyBehavior(IFlyBehavior fb)//这两个方法用来动态实现具体的方法,而不是像原来一样写在构造函数里
{
flyBehavior = fb;
}
public void setQuackBehavior(IQuackBehavior qb)
{
quackBehavior = qb;
}
public abstract void display();//每个子类的都有的方法,但是每个子类的表现却不一样,所以做成抽象方法子类重写
}
class MallardDuck : SimUDuck
{
public MallardDuck()
{
base.quackBehavior = new Quack();//使用父类的字段
base.flyBehavior = new FlyWithWings();
}
public override void display()
{
Console.WriteLine("看起来像绿头鸭");
}
}
class RedHeadDuck : SimUDuck
{
public override void display()
{
Console.WriteLine("看起来像红头鸭");
}
}
class RubberDuck : SimUDuck
{
public override void display()
{
Console.WriteLine("看起来像橡皮鸭");
}
}
class DecoyDuck : SimUDuck
{
public override void display()
{
Console.WriteLine("看起来像诱饵鸭");
}
}
class FlyWithWings:IFlyBehavior
{
public void fly()
{
Console.WriteLine("有翅膀可以飞");
}
}
class FlyNoWay : IFlyBehavior
{
public void fly()
{
Console.WriteLine("没有翅膀不能飞");
}
}
class Quack: IQuackBehavior
{
public void quack()
{
Console.WriteLine("嘎嘎叫");
}
}
class Squeack: IQuackBehavior
{
public void quack()
{
Console.WriteLine("吱吱叫");
}
}
class MuteQuack: IQuackBehavior
{
public void quack()
{
Console.WriteLine("不会叫");
}
}
public interface IFlyBehavior//把变化的飞行行为做成接口
{
void fly();
}
public interface IQuackBehavior//把变化的叫声行为做成接口
{
void quack();
}
- 实现写在具体的类里面
- 父类关联具体的接口,实现算法的具体类关联接口
- 接口的方法被具体的类实现
- 策略模式