漫谈设计模式 —— 职责的封装

前两篇文章介绍了创建封装的模式结构封装的模式,这次我们接着来看剩下的模式。分别有:策略模式、迭代器模式、命令模式、模板方法模式、观察者模式、责任链模式、状态模式、解析器模式、备忘录模式、访问者模式、中介者模式。这些模式的共同点是职责的封装。他们都是把一部分职责从原有的对象中抽离出来,封装成一个单独的对象,达到不同的目的。

最简单的就是策略(Strategy)模式

Strategy

策略模式就是把某一部分职责,例如角色的攻击抽离出来,单独封装成一个类,然后派生不同的实例,实现不同的攻击方式。这样原有的角色类就不再需要为攻击的多样化而操心了,利用接口的形式解耦后角色可以动态配上不同的攻击行为。

另一个常见的迭代器(Iterator)模式也是同样的思路,把遍历管理器内元素的职责从管理器中抽离出来,单独封装成一个迭代器类,这样可以使得管理器接口更加简单,并且只专注于管理元素。不同的是,根据管理器使用的容器结构,迭代器会有对应的一个实现,所以管理器与迭代器是绑定的,不会像上面策略模式那样动态替换。

以上两个模式都致力于对象与行为解耦,再推进一步,操作可变,并且操作的对象也可变,这样的需求该怎么组织呢?例如游戏正常状态下,按下键盘w键是控制角色往前移动,而在剧情模式下,按下键盘w键是控制摄像机围绕剧情所在场景转动。对于这种需求,命令(Command)模式可以派上用场。

Continue reading

漫谈设计模式 —— 结构的封装

上一篇文章谈了一些对创建行为封装的模式,还有一些模式他们是在结构层面来封装的,分别有外观模式、适配器模式、代理模式、装饰者模式、组合模式、桥梁模式与蝇量模式。什么是在结构层面封装呢?我们可以先简单的理解为在一个原有的类上面再包了一个类。那为什么要这样做呢?这样做可以达到很多灵活的变化,我们首先来看最直观也是最简单的,就是改变接口。

用一个类包裹一个原有的类,从而改变它的接口,这就是适配器(Adapter)模式。举个简单的例子,假设我们游戏中特效管理器已经有一个在场景内指定坐标播放特效的接口SFXMgr::PlaySceneSFX(int nX, int nY, int nZ)。现在我们有一个新需求是通过D3DVECTOR传递坐标,那我们第一个想法就是重载PlaySceneSFX,提供SFXMgr::PlaySceneSFX(const D3DVECTOR& vPosition)接口。如果再来一个需求,是在场景内一个物件脚下播放特效,这样我们又得重载一个SFXMgr::PlaySceneSFX(const SceneObject* pObject)接口。这样做不但把特效管理器改乱了,而且特效管理器还要看见D3DVECTOR和SceneObject。为了解决这样的问题我们可以写一个SFXMgrAdapter包裹着SFXMgr,然后由SFXMgrAdapter提供各种各样的接口,最后完成转换后调用到SFXMgr::PlaySceneSFX接口完成真正的功能。

适配器模式就是通过包裹一个原有的类,提供客户期待的接口,这样不需要改动到原来的类,也不用客户完成调用的转换细节。适配器有两种实现方式:类适配器和对象适配器。其实就是我们所说的“包裹”是以何种方法实现的。类适配器通过继承来包裹原有的类,提供新接口。对象适配器则通过组合,拥有原有类的一个实例。两种适配器都是为了改变接口,并且最终功能都是在原有类中完成,属于改变接口但不改变行为。

Continue reading

漫谈设计模式 —— 创建行为的封装

在经典的24个设计模式中,有一部分是关于对创建行为的封装的,他们分别是原型模式、单例模式、生成器模式、简单工厂模式、工厂方法模式、抽象工厂模式。他们都是致力于把实例化对象的职责解耦出来,通过不同的形式封装达到不同的效果。我们从最简单的例子开始入手看看这几种模式的相似与不同。

通常,我们实例化一个对象最简单的就是通过new操作符直接创建,但如果该对象比较复杂,在创建的同时要进行许多初始化工作,例如游戏中创建一个NPC对象,在new一个NPC后,要把他添加到相应的场景中,还有要对他设置许多属性,还要根据他身上的装备来绑定各种部件。通常我们会写一个NPCFactory类,提供一个NPCFactory::CreateNPC()接口把这一连串创建NPC相关的流程封装起来。在设计模式中把这样的做法叫做简单工厂(Simple Factory)模式简单工厂严格来说不算是一个完整的设计模式,但很多人却误以为这就是所谓的工厂模式。

还有一个与上面说的很相似的是生成器(Builder)模式,不同点在于生成器模式把创建过程分开几个步骤封装到类中。就像这样:

NPCFactory.Init(szResourcePath);
NPCFactory.AddToScene(nSceneID);
NPCFactory.SetProperty();
NPCFactory.Equit();
NPC* pNpcA = NPCFactory.GetObject();

生成器模式的最大特点是分步骤,他把创建的过程封装成好几个步骤并交由使用者控制,使用者可以更灵活的控制创建,但相对应他的问题也是使用者必须熟悉创建流程与规则,要知道先Init、再设置、最后调GetObject才真正得到对象。

在介绍完简单工厂与生成器模式后,我们接着来看看另外两个很相似的工厂模式。工厂方法(Factory Method)模式抽象工厂(Abstract Factory)模式

Continue reading

漫谈设计模式

最近有空又重新看了一遍《Head First 设计模式》,孔子曰“温故而知新”,诚不欺我也。虽然在大学时已经看过这本书,但工作两三年后重新看回来还是获益良多。不仅弄明白了很多以前一知半解的东西,而且对于很多模式都能够在项目工程中找到实例,了解了其设计意图以及优缺点,很有拨云见日的感觉。

现有的设计模式很多,最经典的有24个,他们有的很相似,有的南辕北辙,各有各的优缺点,各有各的适用范围。通过三篇文章来把他们归类、梳理并逐一介绍:

(一)漫谈设计模式 —— 创建行为的封装

(二)漫谈设计模式 —— 结构的封装

(三)漫谈设计模式 —— 职责的封装

通过以上的文章我们看了那么多的模式,我们肯定会有所思考。设计模式到底是什么?设计模式用来干什么的?

Continue reading

珠海半程马拉松

以前在学校有跑步锻炼,基本是每周一两次5公里跑操场,时间在半小时以内。来了公司两年,也一直坚持跑步,但都是在跑步机上面跑,基本每周一次,按照10公里每小时速度匀速跑5 6 公里左右,有一次状态较好跑了10公里。觉得自己跑步还可以,于是9月份脑子一热就报名参加珠海半程马拉松,而且直接就报了最长的21公里。结果是悲剧的,但还是长了见识,锻炼了身体,总结了经验。所以在此写一点经验感受,希望对长跑有兴趣的同学有所帮助。

装备

俗话说工欲善其事,必先利其器。以前在学校跟在公司跑步机上跑都是随便穿些的运动鞋跑的,也没啥其他装备,但现在到公路上跑就不一样了。

首先一双减震效果好的运动鞋是十分必要的,因为在跑步机或者塑胶操场上跑步,本身就有减震效果,但到公路上则不是了,一开始跑公路多多少少膝关节或踝关节都有点受不了,所以一双好的运动鞋十分重要。我买的是nike 的air max 全掌气垫跑步鞋,虽然看专业的跑步论坛高手似乎都不穿这种鞋,但我自己穿着觉得还可以。

接着上公路跑步,手机钱包钥匙是不可能装口袋里的了,所以跑步的腰包或臂包还是十分必要的,这些功能性差距不太大的东西,如果不是要追求高端大气上档次的话,淘宝淘些过得去的就可以了。

如果你想实时观察自己的速度、距离、时间、心律等数据的话,跑步手表是很好的选择。虽然现在手机上的一些软件(咕咚运动之类)也可以做到,但跑的时候总拿着手机看一来费劲二来不安全。跑步手表品牌方面,专业的基本是松拓或者Garmin,大众一点的就是nike+那款跑步手表,带GPS功能的基本在1千以上。综合考虑价格跟功能,我买的是moto的一款跑步手表moto actv,国内已经没卖的了,上淘宝找海外代购最后手表+心率带1千6左右成交,还不算坑,但就是等了三四周才到货。各种手表的特点这里就不展开介绍了,有兴趣的大家可以上网搜搜。

Continue reading