序言
情景设计
设计一款模拟鸭子的游戏,游戏中出现各种鸭子,一边游泳戏水,一边呱呱叫。所用的鸭子会呱呱叫,也会游泳,所以基类负责实现。但是每一款鸭子外观不一样,所以这是抽象行为。由子类实现。
-
前期设计及思路
根据情景的设计,首先我们想到这是一些列的鸭子,便会想到利用继承的手段,进行解决。其UML图型为:
后续设计:需要让有的鸭子飞,有的鸭子不能飞。 -
后续设计
问题:
1、在调用中是通过抽象类进行操作的,所以新功能在超类有所体现,
但是下载超类中实现,就所有的鸭子会飞。
2、在超类中是飞的行为是抽象函数,这样每个子类都要实现,代码重写太复杂。
3、用接口,只让飞的鸭子继承实现飞的行为接口,这样在超类中进行初始化接口。
4、但是用接口后,让飞的行为进行修改,那个每个子类中飞的行为也要修改,这样改动也是很大。
经过分析,利用组合的原则,将变化部分进行提取,封装一个新类,所以我们见fly这个行为提取出来,行为上肯定是接口,同时这个接口由行为类实现,而不是具体鸭子类实现,这样就实现策略模式。
这里的接口就是所谓的概念,针对“利用接口编程”,关键在于多态。利用多态,程序可以对超类进行操作,根据实际情况执行到真正行为,将行为和对象进行解耦。
在程序运行时就是针对超类编程,超类编程就是接口和抽象类。
图为:
所以这样针对新行为,我们重新定义个接口,然后实现这个接口,在调用时初始化接口。
其中主要的代码为:
//关键这是超类,必定是抽象类 public abstract class Duck { protected IFlyBehavior flyBehavior; protected QuackBehavior quackBehavior; public virtual void Quack() { throw new System.NotImplementedException(); } //当然这些行为也可通过接口,但是这游泳鸭子都会,所以超类直接实现 public virtual void Swim() { throw new System.NotImplementedException(); } //抽象函数,子类必须实现,意味子类这个行为不同 public abstract void DisPlay(); public virtual void performFly() { //通过接口执行fly行为,要寻找接口在那初始化 flyBehavior.fly(); } } //duck的子类,其中初始化了接口 public class BlueDuck : Duck { public BlueDuck() { //初始化接口,在用BlueDuck初始化Duck时,接口也被初始化了。 flyBehavior = new FlyWithWings(); } public override void DisPlay() { throw new System.NotImplementedException(); } }
总结
当你将两个类结合起来使用时,如同本例,这就是组合。这种做法的不同是在于行为不是继承而来,单独通过行为类和接口进行实现。
策略模式定义了算法族,分别封装起来,让他们之间可以相互替换,使算法的变化独立于使用算法的客户。
版权声明:本文为博主原创文章,未经博主允许不得转载。