拍摄UFO——单职责原则
1.新手机
大鸟小菜晚上晚饭过后,再外面散步。
大鸟:“小菜,刚换的手机感觉如何?”
小菜:“哈,当然是怎个爽字了得,可以听音乐、玩游戏、拍照、摄像,功能全着呢!”
大鸟:“你们这些小年轻,只会赶时髦,手机要那么多功能干吗?能打电话就可以了。”
小菜:”这你就不懂了吧,比如你出门旅游,数码相机一定要的吧,拍照是最起码的旅游需求;
有摄像机会更好,动的影像不是更有保留价值吗;
一路上无聊的时候,打打游戏总是需要的,游戏机要准备;
坐在大巴士上,看着窗外美景,听听音乐应该也属子正常需求吧,MP3一定要带着了;
有时或许还需要什么GPS来定定位,上网看看新闻,发发邮件,查查股票行情,这些求如何办,总不能带着笔记本电脑在路上跑吧。
这些东西且不说本身就很重,很麻烦,就说这些东西的充电器,就是五花八门,估计单就带这些东西,你就得累个半死了。”
大鸟:“你说得也没错,现在电子产品能玩的东西太多……”
小菜:”啊,大鸟!快看!“
2.拍摄
小菜惊呼,左手拉住大鸟的手,右手指向了天空。
大鸟跟着抬头一看,“那应该是架飞机吧!”
“不可能,”小菜坚决地说,“飞机哪有没翅膀的,那个东西飞得很奇怪,你看,你看,它停在空中,普通飞机怎么会在空中停下来。”
“是不太像飞机,飞碟?!——傻菜,快点用你手机录像呀!”
“是是是,啊,这手机怎么……等等,”小菜手忙脚乱。
“看你慌得,”大鸟说,“快些,马上可能就没了。”
“好了好了,”小菜终于打开了手机的摄像功能,对准了天空,“主要是对新功能不熟悉,你看,这家伙飞得多快。”
“嗯,它应该是飞碟,不然不可能这种样子的,以前也没有听说过这玩意,”大鸟肯定道,“还好你这手机可以摄像——啊,它飞跑了,你拍下来了没有?”
“好了,我都拍下来了,有点不太清楚,回去放电脑上看看吧。”小菜很开心,他的新手机发挥大作用了,“头一次看到 UFO,就拍到了,这下可是大新闻了。”
“是呀,我也头一次看到,我们太幸运了。”
3.没用的东西
回到家中。小菜将手机文件传入电脑。
”这什么呀,黑乎乎的,什么也看不清。”大鸟大为失望。
“那不是有一个小白点吗?”小菜想极力申辩。
“那白点就和液晶显示器里的坏点一样,这如何看得出是UFO呢,说给别人谁信呀。”
“害!是的。”小菜也承认了这个事实,“这手机拍出来的东西没办法看呀,根本算不上是UFO的证据。”
小菜拿起手机,一脸苦相,对着它说道:“狗屁,要你这么多功能有鸟用,关键时刻就萎掉,我砸……”小菜举起手机欲往地上砸去。
4.单一职责原则
“砸呀,你砸呀!”大鸟笑嘻嘻地看着小菜,“哼哼,我就知道你舍不得,不过你的手机的确是太没用,这么好的机遇,都没有录成,如果是摄像机,效果一定不会差,因为当时我们眼睛看得很清楚呀。这下说给谁,谁也不信呀!大多数时候,
一件产品简单一些,职责单一一些,或许是更好的选择。这就和设计模式中的一大原则——单一职责的道理是一样的。”
“哦,听字面意思,单一职责原则,意思就是说,功能要单一?”
“哈,可以简单地这么理解,它的准确解释是,就一个类而言,应该仅有一个引起它变化的原因(ASD)。
我们在做编程的时候,很自然地就会给一个类加各种各样的功能,比如我们写一个窗体应用程序,一般都会生成一个 Form1
这样的类,于是我们就把各种各样的代码,像某种商业运算的算法呀,像数据库访问的 SQL 语句呀什么的都写到这样的类当中,这就意味着,无论任何需求要来,你都需要更改这个窗体类,这其实是很糟糕的,维护麻烦,复用不可能,也缺乏灵活性。”
“是的,我写代码一般刚开始就是把所有的方法直接写在窗体类的代码当中的。”
5.方块游戏的设计
“我们再来举些例子,比如就拿手机里的俄罗斯方块游戏为例。要是让你开发这个小游戏,你如何考虑?”大鸟问道。
“我想想,首先它方块下落动画的原理是画四个小方块,擦掉,然后再在下一行画四个方块。不断地绘出和擦掉就形成了动画,所以应该要有画和擦方块的代码。然后左右键实现左移和右移,下键实现加速,上键实现旋转,这其实都应该是函数,当然左右移动需要考虑碰撞的问题,下移需要考虑堆积和消层的问题。”
“OK,你也说了不少了。如果就用 WinForm
的方式开发,你打算怎么开发呢?”
“那当然是先建立一个窗体 Form
,然后加一个用于游戏框的控件,比如 Panel
或者 PictureBox
,一个按钮 Button
来控制'开始',最后再放一个 Timer
控件用于分时动画的编程。写代码当然就是编写 Timer_Tick
事件来绘出和擦除方块,并做出堆积和消层的判断。再编写控件的键盘事件,按了左箭头则左移,右箭头则右移等等。对了,还需要用到些GDI技术的方法来画方块和擦方块。”
“你能不能就这些代码划分一下类呢?”
“分类? 这里好像关键在于各种事件代码如何写吧,这里有什么类可言呢?”
“看来你的面向过程开发已经根深蒂固了。你把所有的代码都写在了 Form1.cs 这个类里,你觉得这合理吗?”
“可能不合理,但我实在没想出怎么分离它。”
“打个比方,如果现在要你写的是手机版的俄罗斯方块程序,即 PocketPC
或者 Windows CE
上运行的程序,它们可以安装 .NET
框架的精简版,运行 C#
语言编写的应用程序,但PC上的普通 WinForm
界面的程序不能使用。那你现在这个代码有什么可以复用的吗?”
“你都已经说了,不能使用,我当然就没法使用了。Copy过去,再针对代码做些改进吧。“
“但这当中,有些东西是始终没变的。”
“你是说,下落、旋转、碰撞判断、移动、堆积这些游戏逻辑吧?”
“说得没错,这些都是和游戏有关的逻辑,和界面如何表示没有什么关系,为什么要写在一个类里面呢?
如果一个类承担的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会削弱或者抑制这个类完成其他职责的能力。这种耦合会导致脆弱的设计,当变化发生时,设计会遭受到意想不到的破坏(ASD)。
事实上,你完全可以找出哪些是界面,哪些是游戏逻辑,然后进行分离。”
“但我还是不明白,如何分离开。”
“你仔细想想看,方块的可移动的游戏区域,可以设计为一个二维整型数组用来表示坐标,宽10,高20,比如' int[,]arraySquare=new int[10,20];
’,那么整个方块的移动其实就是数组的下标变化,比如原方块在 araySquare[3,5]
上,则下移时变成 arraySquare [3,6]
,如果下移同时还按了左键,则是 arraySquare[2,6]
。每个数组的值就是是否存在方块的标志,存在为1,不存在时缺省为0。这下你该明白,所谓的碰撞判断,其实就是什么?”
“我知道了,
是否能左移,就是判断 arraySquare[x,y]
中的x-1
是否小于 0,否则就撞墙了。或者arraySquare [x-1,y]
是否等于1,否则就说明左侧有堆积的方块。所谓堆积,不过是判断 arraySquare [x,y+1]
是否等于1的过程,如果是,则将自己arraySquare[x,y]
的值改1。那么消层,其实就是 arraySquare [x,y]
中循环x由0到9,判断arraySquare[x,y]
是否都等于1,是则此行数据清零,并将其上方的数组值遍历下移一位。”
“那你就应该明白了,所谓游戏逻辑,不过就是数组的每一项值变化的问题,下落、旋转、碰撞判断、移动、堆积这些都是在做数组具体项的值的变化。
而界面表示逻辑,不过是根据数组的数据进行绘出和擦除,或者根据键盘命令调用数组的相应方法进行改变。
因此,至少应该考虑将此程序分为两个类,一个是游戏逻辑的类,一个是 WinFom 窗体的类。当有一天要改变界面,或者换界面时,不过是窗体类的变化,和游戏逻辑无关,以此达到复用的目的。”
“这个听起来容易,真正要做起来还是有难度的哦!”
“当然,软件设计真正要做的许多内容,就是发现职责并把那些职责相互分离(ASD)。其实要去判断是否应该分离出类来,也不难,那就是
“的确是这样,界面的变化是和游戏本身没有关系的,界面是容易变化的,而游戏逻辑是不太容易变化的,将它们分离开有利于界面的改动。”
6.手机职责过多吗?
“这下你知道你的手机为什么不能拍摄好 UFO的原因了吧?”大鸟笑道。
“如果手机只用来接听电话,DV用来拍摄,职责的分离是可以把事情做得更好。不过这其实不是一回事哦,现在的智能手机承担的职责多,并不等于就不可以做好,只不过现在的科技还不能让手机在摄像时超过 DV 而已。”小菜分析说。
“整合当然是一种很好的思想。比如 Google 最初的理想就是将一切的需求都整合到一个文本框里提交,用干净的页面来吸引用户,导致互联网的一场变革。
但现在分类信息、垂直搜索又开始流行,这却是单一职责的思想体现。
现在智能手机整合了很多功能的原因是因为 DV、DC、MP3 等产品的体积也太大了。手机携带很方便,所以才有了这样的过渡产品,如果,每一样数码产品都缩小100倍,就像放在包里的一张卡片、一支笔那么简单,而功能和质量都不发生变化,你还会觉得它们很麻烦吗?”大鸟总结道,“总的来说,手机的发展有它的特点,
推荐站内搜索:最好用的开发软件、免费开源系统、渗透测试工具云盘下载、最新渗透测试资料、最新黑客工具下载……
还没有评论,来说两句吧...