设计模式很符合中庸之道,适量的话可以大幅提高可维护性,过量的话不但加大工作量,而且会影响可读性。
单一职责原则(Single Responsibility Principle)
定义:不要存在多于一个导致类变更的原因。通俗的说,即一个模块(类、函数等)只负责一项职责。有人在美食城当了三十年厨师,却不会做钣,原因是他只负责切葱花。单一职责完括两层意思,一:一个模块只完成一个功能,二,一个功能只由一个模板完成。稍有经验的程序员,就算不知道单一职责原则,他也会无意识地遵守单一职责原则,因为这样省事。但在实际开发中, “暂时”不遵守单一职责确很常见,且合理。下面以我开发《智勇三国》的经历来举2个例子来说明。在《智勇三国》中学技能是通过使用技能书实现的,其功能封装在CJiNengShu类中。后来增加装备书,100本140级装备书可以将130级装备升级为140装备,加持和系数保留。按单一职责原则,应该增加新类。但增加新类的问题是:
技能书、装备书之类的都存放在背包中,背包和人物信息是部分和整体关系。出于性能考虑,限制了人物信息的长度不超过2K。随着维护地不断深入,人物信息的备用数据已经基本用完。如果要给人物增加新的背包,要重写内核 ,这个代价太重了,所以暂时将装备书的功能封装在CJiNengShu类中。 《智勇三国》的一般等价物是铜钱,long型,众所周知,long型的上限是21亿多。最初一个玩家只赚钱不花钱,理论上三年可以赚到21亿。所以这个上限很大。游戏不断更新,玩家打钱的能力也不断提升。再加上有玩家开许多小号打钱交易给大号。于是21亿的上限,显得很小了。最理想的方法是:将long换成__int64,虽然只改了一行代码,但影响所有和交易有关的模块。最后的解决方案:增加摇钱,__int64类型,摇钱和铜钱可以1比1自由兑换。大额交易用摇钱,小额交易用铜钱。
里氏替换原则(Liskov Substitution Principle)
如果对每一个类型为 T1的对象 o1,都有类型为 T2 的对象o2,使得以 T1定义的所有程序 P 在所有的对象 o1 都代换成 o2 时,程序 P 的行为没有发生变化,那么类型 T2 是类型 T1 的子类型。
此原则如果严格执行的话,至少对MFC而言,是因噎废食。此原则会消灭“覆盖”和“隐藏”。其实MS也不遵守则原则,下两段代码的效果显然不一样,代码一写的是文件,代码二写的内存。
代码一:
CFile f; f.Open("d:\\1.txt",CFile::modeCreate|CFile::modeWrite); f.Write("aa",2); f.Close();
代码二:
CMemFile f; f.Open("d:\\1.txt",CFile::modeCreate|CFile::modeWrite); f.Write("aa",2); f.Close();
MS这样做的是好处通用性强,操作文件和内存是完全一样的。
依赖倒置原则(Dependence Inversion Principle)
定义:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。
由于游戏操作界面必须简单,所以智勇三国的部分界面使用了自绘,自绘由自定义类CVWnd和他的派生类负责。
迪米特法则(Law Of Demeter)
定义:一个对象应该对其他对象保持最少的了解。
简单地说:只与直接的朋友通信。首先来解释一下什么是直接的朋友:每个对象都会与其他对象有耦合关系,只要两个对象之间有耦合关系,我们就说这两个对象之间是朋友关系。耦合的方式很多,依赖、关联、组合、聚合等。其中,我们称出现成员变量、方法参数、方法返回值中的类为直接的朋友,而出现在局部变量中的类则不是直接的朋友。也就是说,陌生的类最好不要作为局部变量的形式出现在类的内部。
《智勇三国》在这方面做得比较差,下面试举一例。
商店管理类之所以和柜台类发生关系是因为商店管理类通过商店类,访问了柜台类。CYongHuss类之所以和柜台类发生关系是因为CYongHuss类直接操作了柜台类,要取消这两个关系,正确的做法是:CYongHuss调用商店管理类的函数,商店管理类调用商店类的函数,商店类的成员函数再操作拒台类。
接口隔离原则(Interface Segregation Principle)
定义:客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。不然有大量不需要,但必须实现的接口。
开闭原则(Open Close Principle)
定义:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。
问题由来:在软件的生命周期内,因为变化、升级和维护等原因需要对软件原有代码进行修改时,可能会给旧代码中引入错误,也可能会使我们不得不对整个功能进行重构,并且需要原有代码经过重新测试。我的理解是平时尽量遵守开闭原则,大更新的时候再统一进行整合。