扫码在手机阅读
手机阅读《大话设计模式》
大话设计模式

第179章

publicvoiddisplay{

//外观是绿头

publicclassRedheadDuckextendsDuck{

Java代码

PublicabstractclassDuck{

voidquack;//呱呱叫

//otherextends

大B:“现在多了个主意,要让鸭子能飞,那么你可能想到只要在Duck类中加上fly方法,然后让所有的鸭子都来继承这个方法。”

Java代码

PublicabstractclassDuck{

Voidquack;//呱呱叫

Voidswin;//游泳

abstractvoiddisplay;//鸭子外观不同,所以是抽象的

fly;//刚加的会飞的方法,所有的子类都会继承

//other

publicabstractclassDuck{

voidquack;//呱呱叫

voidswin;//游泳

abstractvoiddisplay;//鸭子外观不同,所以是抽象的

fly;//刚加的会飞的方法,所有的子类都会继承

//other

大B:“但是,可怕的问题就出来了:‘塑料橡皮鸭子’也会飞了,忽略了一件事,并非所有的鸭子都会飞。能想到继承,把橡皮鸭子类中的fly方法覆盖掉,什么也不做。可是,如果以后要加入木头鸭子,不会飞也不会叫,你又想到了,把fly从超类中取出来,做一个Flyable接口,同样的方式,设计一个会叫的接口Quackable。”

小A:“但是你没发现这么一来重复的代码会很多吗?”

大B:“现在我们知道使用继承并不能很好的解决问题,因为鸭子的行为在子类里不断的改变,让所有的子类都有这些行为是不恰当的。”

第一个设计原则:

找出应用中可能需要变化之处,把它独立出来,不要和那些不需要变化的代码混在一起。现在知道Duck类里的fly和quack会随着鸭子的不同而改变,我们把它从Duck类里取出来,写2个接口:

代码:

publicinterfaceFlyBehavior{

publicvoidfly;//飞行行为必须实现的接口

publicinterfaceQuackBehavior{

publicvoidquack;//叫行为必须实现的接口

}publicinterfaceFlyBehavior{publicvoidfly;//飞行行为必须实现的接口

publicinterfaceQuackBehavior{

publicvoidquack;//叫行为必须实现的接口

这样的设计可以让这2个动作行为与鸭子类无关,可以被其他的对象复用,也可以新增加一些行为。

第二个设计原则:

针对接口编程,而不是针对实现编程。

现在来整合下鸭子的行为:

代码:

1、Duck抽象类

publicabstractclassDuck{

//为行为接口类型声明2个引用变量,所有的鸭子子类都继承它们

FlyBehaviorflyBehavior;

QuackBehaviorquackBehavior;

publicDuck{

//设定鸭子的行为,而不是在鸭子的构造器内实例化

publicvoidsetFlyBehavior(FlyBehaviorfb){

flyBehavior=fb;

publicvoidsetQuackBehavior(QuackBehaviorqb){

quackBehavior=qb;

abstractvoiddisplay;//抽象外观方法

publicvoidperformFly{

;//委托给会飞的行为类

publicvoidperformQuack{

;//委托给会叫的行为类

publicvoidswim{

(“Allducksfloat,evendecoys!”);

2、FlyBehavior接口与2个行为实现类

publicinterfaceFlyBehavior{

publicvoidfly;

publicclassFlyNoWayimplementsFlyBehavior{

publicvoidfly{

(“Icantfly”);

publicclassFlyWithWingsimplementsFlyBehavior{

publicvoidfly{

(“Imflying!”);

3、QuackBehavior接口与2个行为实现类

PublicinterfaceQuackBehavior{

publicvoidquack;

publicclassQuackimplementsQuackBehavior{

publicvoidquack{

(“Quack”);

publicclassMuteQuackimplementsQuackBehavior{

publicvoidquack{

(“《Silence》”);

4、来看看如何设定FlyBehavior和QuackBehavior的实例变量(继承)

publicclassMallardDuckextendsDuck{

publicMallardDuck{

//绿头鸭子使用Quack类处理呱呱叫,所以当performQuack被调用时,叫的责任被委托给Quack对象,

//而我们得到了真正的呱呱叫

quackBehavior=newQuack;

//使用FlyWithWings作为其FlyBehavior类型

flyBehavior=newFlyWithWings;

publicvoiddisplay{

(“ImarealMallardduck”);

5、制造一个新的鸭子类型

publicclassModelDuckextendsDuck{

publicModelDuck{

flyBehavior=newFlyNoWay;//一开始我们的鸭子是不会飞的

quackBehavior=newQuack;

publicvoiddisplay{

(“Imamodelduck”);

6、建立一个新的FlyBehavior类型,火箭动力的飞行行为

publicclassFlyRocketPoweredimplementsFlyBehavior{

publicvoidfly{

(“Imflyingwitharocket”);

7、测试类

publicclassMiniDuckSimulator{

publicstaticvoidmain(Stringargs){

Duckmallard=newMallardDuck;

//这会调用MallardDuck继承来的performQuack方法,进而委托给该对象的QuackBehavion对象处理

//也就是说调用继承来的quackBehavion引用对象的quack方法

Duckmodel=newModelDuck;

//第一次调用performFly会被委托给flyBahavion对象,

//也就是FlyNoWay实例,该对象是在模型鸭子构造器中设置的

//这会调用继承来的setter方法,把FlyRocketPowered火箭动力飞行行为设定到模型鸭子中,牛吧……

(newFlyRocketPowered);

//如果成功了,就意味着模型鸭子可以动态的改变它的飞行行为

voidswin;//游泳

abstractvoiddisplay;//鸭子外观不同,所以是抽象的

//other

publicclassMallardDuckextendsDuck{

publicabstractclassDuck{

大B:“游戏中会出现各种鸭子,一边游戏戏水,一边呱呱叫,我们设计了一个鸭子超类(Duck),并让各种鸭子继承此类。”

//other

PublicclassMallardDuckextendsDuck{

Publicvoiddisplay{

voidquack;//呱呱叫

voidswin;//游泳

abstractvoiddisplay;//鸭子外观不同,所以是抽象的

//外观是绿头

PublicclassRedheadDuckextendsDuck{

publicvoiddisplay{

//外观是红头

//外观是红头

//otherextends

Publicvoiddisplay{

  • 加入收藏
  • 目录
  • A+
  • A-