面向对象开发课程开发:penghao2008-04-01课程目的描述面向对象编程的一般性的手法,原则和技巧工欲善其事,必先利其器。课程大纲引言面向对象的表达方法面向对象的五个原则面向对象的几个设计模式我们面对的是什么?这种情况下的应对之道规模大且服务不断的情况下对应的非功能性需求就会要求比较多.变化多且持续变化的情况下要求程序具有良好的结构。本文档所关注的核心。程序,服务具有良好结构有两个层面的考虑大粒度的结构设计。关注的层面比较宏观。这一块的知识参考《面向模式的体系结构》卷一。本文档不关注。细粒度结构设计-本文档关注的核心什么代码写得好?什么叫坏的代码?有标准吗?2-5坏代码举例僵化:很难对系统进行改动,因为每个改动都会迫使许多对系统其他部分的改动。脆弱:对系统的改动会导致系统综合改动的地方在概念上无关的许多地方出现问题。牢固:很难解开系统的纠结,使之成为一些可重用的组件。粘滞:做正确的事情比做错误的事情要困难。不必要的复杂:设计中包含不具有任何直接好处的基础结构。不必要的重复:晦涩:很难阅读,理解。(引用于《敏捷软件开发:原则,模式与实践》强烈推荐该书。)好代码的近似标准介绍OO(或者说语言)的核心思想OO的五大技术原则(标准)从OO看合理的分层架构OO(或者说语言)的核心思想—表达领域概念语言的语法都是比较简单的。不过同样的语法写出来的代码却有好坏高低之分。重要的区别就在于表达领域概念的水平重要的原则就是:“程序(代码)应该反映人的思想,而不是相反。”Martinfowler.(《分析模式》)如何来表达一个mmog-静态视图?针对某个领域对象粗分操作,行为,职责。通过对领域概念应用OO原则,分析模式,设计模式等等手段对对象职责进行抽象,细分职责。形成最终静态对象图。通过对用例画时序图,确认对象职责是否可行,恰当。ObjectWorldObjectUnitCreaturePetTotemPlayer基本的容器类抽象类int型float型GUID管理有位置的东西.管理坐标3D距离水平距离有HP的东西.有hp就会有level,armor,被攻击,被施法,有路径,甚至可能有技能。这个层次开始变得复杂。所以想以聚合的形式实现。这一层的实现和mangos不同。但总体来看是表达同样的概念。MaNGoSStructurecorpse有智能的东西实际mmogAI表达的例子+Enter()+Update()+Exit()+OnMetPlayer()+OnBeHit()+OnMoveEnd()state巡逻战斗逃跑拾取+ShouldAttack()+ShouldEscape()+ShouldPickUp()IPolicy+AttackStart()+AttackEnd()+Update()IActionImpGlobalState实现与状态无关的行为变化需求。描述一个怪物的个性。+Update()IMovementGenerator实现目标点的产生表达概念的几种类型释意接口。表达实体对象表达约束表达流程(服务)表达规格隐含机制表达“在初学面向对象时对它们并不熟悉。每学会一个这样的表达的类型,我的设计水平就又进了一步”“MydesignsbecamesharperwitheachoneoftheseIleaned.”EricEvans《领域驱动设计》强烈推荐该书释意接口的例子intCPlayer::StandUp(intiSessionID){intiOpenNum=0;iOpenNum=m_Sessions.GetLastIdx();//下面两个判断判断违法情况。if(iSessionID0){}elseif(iSessionIDiOpenNum){}}推荐写法如下:RoomSession提取成一个对象(类),提供CheckRoomIDValid接口。intCPlayer::StandUp(intiSessionID){iRet=m_Session.CheckValid(iSessionID);If(iRet){}}这种是完全达到了隐藏实现,消除了代码重复,又充分表意的目的。特别在此强调释意接口。好的类应该是每个函数都比较短,五,六十行。然后有二,三十个方法。这个类形成一个接近封闭的类型。具有充分的自我表达能力。实体表达的例子charsNowDate[20]={0};charsLastDate[20]={0};GetDate(time(NULL),sNowDate);GetDate(iReserve[LastGive],sLastDate);if(strcmp(sNowDate,sLastDate)0){}else{}同一个功能的另外一种写法也是实际代码。intCGiveDaily::OnGive(CAttach*pPA,intiHE){DatedToday(time(NULL));DatedLastDay(pPA-GetGiveHELastTime());if(dLastDay==dToday){}else{}}可以看出抽取出了日期类,用日期类来表达人的思想,而不是只记得使用哪个API来实现功能。日期这个概念在这个需求里面是比较重要的一个概念。面向对象就表达出了这个概念。约束表达的例子有时候某些约束表达的是领域逻辑。通常隐式的表达,将他们显示表达出来能够极大地改进设计。比如QQGame里面进入房间限制。实际产品对进房需求的演化第一个版本:限制一下玩家最低,最高积分。第二个版本超级玩家和网管要优先进房第三个版本如果是出租房间需要是承租方才能进房第四个版本如果是比赛房间需要是比赛方才能进房第五个版本需要拥有某种道具第六个版本如果是欢乐场房间需要检查欢乐豆上下限制。+Check(intiRoomID,intiPlayerID)()+Next()IEnterRoomRuleCCheckPointRuleCCheckIdentityRuleCCheckRentRole产品的需求演化说明进房约束是个热点问题。抽象出约束接口,把约束的增加,约束的实现,变更对进房主流程屏蔽起来。流程(服务)表达的例子CPlayerCTableCRoom角色坐下IsFeasibleIsFeasibleSitdownIsFeasibleSitdown基本行为流程概念的表达,对于产品同事不断提及到的流程概念表达。主角1SitdownCPlayerCTableCRoomIsFeasibleIsFeasibleSitdownSitdwonSitdown行为概念流程表达的好处主角1CRoom坐下普通坐下,检查玩家各自的设置,比如网速等混战房间,预分配座位.随机选择一个座位让用户坐下混战房间,统一撮合机制加入等待撮合的队列比赛房间指定座位,到指定座位坐下把规格用对象来表达验证。选择(查询)按需创建隐含概念表达实例在QQGame里面对房间模式的描述结构如下。不同的房间模式,具有不一样的基本行为。我们通过不同的工厂实现来屏蔽掉这一层变化。不同的房间聚合不同的生成工厂。房间模式是挖掘出来的概念,抽象工厂表达出了这个概念。CRoom11+CreateSitDownAction()+CreateStandup()+CreateEnterRoom()+CreateLeaveRoom()+CreateStartGame()+CreateOnGameEnd()+CreateOnGameStart()+CreateSetGameScoreAcion()IActionFatoryCCommonRoomFatoryCCompetionRoomFactoryCDogFightRoomFactoryOO的五项技术原则是什么?(讨论,提问)OO的五项技术原则单一职责—事情不要太复杂。开闭原则—让易变的容易变化,不变的稳定。依赖倒置—让易变的依赖于稳定,而不是相反。接口隔离可替代OCP(Open-ClosedPrinciple):开放-关闭原则对扩展要说YES,对修改说NO。LSP(LiskovSubstitutionPrinciple):LSP原则父母要对孩子负责。SRP(SingleResponsibilityPrinciple):单一职责原则感情要单一,不要脚踏两支船。DIP(DependencyInversionPrinciple):关系返转原则不要一天打10个电话给我,有结果我会通知你。ISP(InterfaceSegregationPrinciple):接口隔离原则让李部长只负责开发吧,市场就让辛部长做吧学习面向对象中最主要的一点就是,理解面向对象原则。如果你还没有真正理解这些原则,那你做出的设计可能不是最好的设计,那你学习设计模式也不能真正理解它的真谛。五项技术原则实例-单一职责实际代码例子classCDBCtrl{public:CDBCtrl();~CDBCtrl();intInitialize(constchar*szCfgFile);intPrepareToRun();intRun();void*operatornew(size_tnSize);voidoperatordelete(void*pMem);staticintCountSize();staticCSharedMem*pCurrentShm;private:intReadCfg(constchar*szCfgFile);intLoadProxyCfgFromFile(char*szProxyFile,int&iProxyNumber);intLoadGivenRuleFromFile(char*szRuleFile,int&iRuleCount);intLoadForbidRuleFromFile(char*szRuleFile,int&iRuleCount);intReadPublicCfg(constchar*szCfgFile);intLoadCreditConfig(constchar*szCfgFile);intCheckRunFlags();intConnectToProxys();intCheckAndDispatchInputMsg();intRoutineCheck();intDispatchOneCode(shortnCodeLength,BYTE*pbyCode);intPostInternalMsgToHandle(intiHandleID,CMsg*pMsg);intNofityDBHandles(CMsg*stMsg);TDBCfgm_stDBCfg;CTCPConnm_astProxyConn[MAXPROXYNUMBER];CDBHandle*m_apHandles[MAXHANDLENUMBER];classCMainCtrl{public:CMainCtrl();virtual~CMainCtrl();virtualintInitialize();virtualintRun();intReloadCfg();intCheckRunFlag();protected:private:};职责表达了负责的变化,有多个维度的职责,就有多个维度的变化五项技术原则实例-开闭原则QQGame最经典的例子,MainFrame可以不动代码,游戏服务可以源源不断输出新的游戏。觉得这个是最核心的规则。(下图引用自zengyu《QQGame服务器架构技术》)TableGameGetInfoSendDataSetInfo。。。OnEnterOnExitOnReadyITableIGameMainServerProcessMainFrameSharedObject。。。五项技术原则实例-依赖倒置问题界面控件,比如Button,