java基础_设计模式_设计基础(小鸭子游戏)

news/2024/10/30 17:19:59/

小鸭子游戏,是好多爱好者接触设计模式、认知设计模式概念的一个入门。
每个初学者的理解不同,我加上自己的理解大体是这样的:前提是处理大规模时,假设池塘中有10000头小鸭子,有红头鸭,野鸭子,木头鸭子等等,会叫会游泳,肯定是定义一个父类Duck,拥有这样的基本行为属性;现在要求鸭子中400头,可以飞,该怎么做?
有句话叫:当你处理大规模时,一定要写抽象层次编程

问题:400只小鸭子可以飞,怎么做?

1.最直接想到的就是 父类中定义fly()方法,全部的子鸭子去重写,要飞的就子类自己实现飞这个行为,不要飞的子类可以空实现。目的实现了,存在的问题:①全部子类都要改代码  ②实现的fly方法 具体实现无论是不是空,都要在栈中保留方法的引用 而维护方法的指针需要成本尤其是大量时。  基于这两点肯定不合适。

总结:通过继承实现在父类中声明的行为,主要有以下缺点:

the followings are the disadvantages of using inheritance to provide Duck behavior

①Code is duplicated across subclasses (代码在多个子类中重复)

② Runtime behavior changes are difficult (运行时行为不易改变)

③Changes can unintentionally affect other ducks (改变会牵一发而动全身,造成部分子类型不想要的改变)


2.定义一个FlyAble接口,然后定义400只需要飞的小鸭子实现这个接口,然后实现自己的方法,有没有发现问题的所在,需要每一个子类都去实现这个接口,然后写一样的fly代码;代码如下:

public interface Flyable {void fly();
}
public class RedHeadDuck extends Duck implements Flyable {@Overridevoid display() {System.out.println("红头的");}@Overridepublic void fly() {System.out.println("要飞的");}
}

图示:



这就是“java的接口不具有实现代码,实现接口无法达到代码的复用”,也就意味着“当你需要修改某个行为,你需要往下追踪,并修改每一个定义了此行为的类。” 这两句话,可以细细体会,就是接口不具有代码的实现,无法达到代码的复用。

实现Flyable接口的方式到底有什么坏处?
假设400个鸭子要能飞,那要400个鸭子实现这个接口,每个都重写400次fly方法,然后定义飞的行为,要是不同的鸭子有了高高飞,擦地飞,旋转着飞,是不是,每个鸭子要写不同的飞方法,比如

a   =》高高飞

b   =》擦地飞
c   =》旋转着飞

现在d e f g 也要旋转飞 那肯定要每一个都写旋转飞的方法  这属于“接口不具有实现代码,所以实现接口无法达到代码的复用”。


如果有专门的高高飞行为类,擦地飞行为类,旋转着飞行为类,都去实现flybehavior行为接口,重写fly表达行为,那每次用的时候,就不用写这么多重复的代码了。 而且当你想修改方法的时候只需要改一处就好了。

可以试想,将变化的内容定义形成接口可以实现变化内容和不变内容的剥离。 其接口的实现类可以实现变化内容的重用,即理解为

这些实现类并非Duck.java的子类型,而是专门的一组实现类,称之为 行为类。由行为类而不是Duck.java的子类型实现接口。这样才能保证变化的行为独立于不变的内容。

代码如下:

public interface FlyBehavior {void fly();
}

//具体的行为类 用翅膀飞

public class FlyWithWings implements FlyBehavior {@Overridepublic void fly() {System.out.println("==带翅膀飞");}
}



/*** 父类*/
public abstract class Duck {FlyBehavior flyBehavior;String color;int age;public void performFly() {flyBehavior.fly();}void performSwim() {System.out.println("==所有的鸭子都会游泳呢");}
}

/*** 红头鸭*/public class RedheadDuck extends Duck {public RedheadDuck() {flyBehavior = new FlyWithWings();}
}


测试类:

/*** 测试类*/public class TestDuck {public static void main(String[] args) {System.out.println("=============红头鸭子=========");showRedHeadDuck();}private static void showRedHeadDuck() {Duck duck = new RedheadDuck();duck.performFly();}
}
 这样就实现了鸭子类和fly这一行为的分离,两着没有了关系。

以前的做法是:行为是继承自Duck超类的具体实现而来,或者实现某个接口并由子类自行实现而来。 这两种方法都是依赖于实现。我们被实现绑的死死的,没有办法更改行为(除非写更多的代码)

这种方法和继承的不同之处在于,小鸭子的行为不是继承而来,而是和适当的行为对象结合。这是一个很重要的技巧,其实使用了策略模式中的第三个设计原则,多用组合 少用继承。

当你处理大规模时 一定要写抽象层次编程。

整个过程就是从is-a转成has-a。







http://www.ppmy.cn/news/271290.html

相关文章

Android移动应用开发——实验七——小鸭子报数(广播)

 掌握布局与控件的使用方法  掌握有序广播机制,根据广播接收者的优先级顺序接收广播  掌握广播拦截机制 通过合理布局来搭建界面,界面效果如下图所示。采用有序广播方式,将下方小鸭子优先级分别设置1000、800、600。 1、当点…

用MATLAB求解小鸭过河曲线

题目描述 有只鸭子想游到河对岸的某个位置O,如果它的方向始终朝着目标O。求这只鸭子的游动曲线。问题分析 由于水流速度会对运动产生影响,此时小鸭朝向对岸的方向是一个随时变化的,合速度的方向和大小也是变化的,小鸭的运动轨迹将…

6综合项目 旅游网 【6.我的收藏和收藏排行榜】

我的收藏 分析 先登录→拿到当前登录的用户信息,从数据库中获取uid和对应uid的rid集合→将rid集合信息展示到我的收藏 前台代码 判断用户是否登录,传递uid,通过uid查找其对应的rid集合 当查询的属性涉及到多张表,则必须使用多表连…

实时分析:Flume+Kafka+SparkStreaming商品评分排行榜

写在前面 接上一篇《FlumeKafka数据采集与清洗》。 本文主要介绍用流计算SparkStreaming对数据进行实时处理。 流计算 概念 实时获取来自不同数据源的海量数据,经过实时 分析处理,获得有价值的信息 流计算秉承一个基本理念,即数据的价值…

用python画小鸭,Python 处理输入法字库(五笔极点字库转小鸭字库)

Python 处理输入法字库(五笔极点字库转小鸭字库) Python 处理输入法字库(五笔极点字库转小鸭字库) 一直都是用的小鸭五笔,091新字库是极点格式的,刚开始懒得动,直接用极点五笔了,用了一段时间碰到很多问题.其中最坑的是. 在tkinter Gui 里极点输入不能退格,一退格就乱码( ) ,我…

微信运动排行榜服务器忙,那些在微信运动排行榜上霸榜的朋友都在哪儿运动的?...

入冬以来,这天是一天比一天冷,周报君已经开启了冬眠模式,能不出门尽量不出门吹冷风,能不动尽量猫在被窝里不动。 但朋友圈里总有那么几位,他们从不畏严寒酷暑,在每一个你赖床的早晨和吃夜宵的夜晚&#xff…

万能网卡驱动

http://drivers.160.com/universal/network.html#universal_tab

万能驱动 32位,64位最新版 电脑万能驱动

万能驱动最新版本:这万能驱动可以安装现在绝大部分的本本,装机必备的东西。直接看看吧。 下载地址:http://pan.baidu.com/share/home?uk1345536464