第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{
其他人正在读 :【重生就别当舔狗了】【重生之奶爸的悠闲生活】【因人而异的系统】【从小欢喜开启诸天之旅】【综漫:这友好交流系统也太友好了】【道爷要飞升】【重生之娱乐女神医】【将夜:吾为当世仙】【龙王传说世界的天才玩家M】【乱战异世之召唤群雄】【封神还没开始,你篡位了纣王?】【燕歌行 第二部】【制卡师:我的卡牌无限连锁】【玄幻:我是大反派】【海贼之绝巅霸气】【昭奚旧草】【人生副本游戏】【成人】【直播鉴宝,我竟成了国宝级专家?】【从尸解仙开始】【星象制卡师:从昴日星官开始】【柯南里的不柯学侦探】【人在港综,你管这叫卧底?】【天黑请下凡】【重生99做汽车巨头】【枕刀】【这个诡异三国游戏太凶残了】【直播被剧透历史的千古一帝,今天也很尴尬】【神秘降临,我的污染愈发变态】【神佛竟是我自己】