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();
}
- 實現寫在具體的類裡面
- 父類關聯具體的介面,實現演算法的具體類關聯介面
- 介面的方法被具體的類實現
- 策略模式