在《重构》一书中的代码的环味道中有一种叫做“Feature Envy”(依恋情结),形象的描述了一种违反了LoC的情况。Feature Envy是说一个对象对其它对象的内容更有兴趣,也是说老是羡慕别的对象的成员、结构或者功能,大老远的调用人家的东西。这样的结构显然是不合理的。我们的程序应该写得比较“害羞”。不能像前面例子中的那个不把自己当外人的店员一样,拿过客人的钱包自己把钱拿出来。“害羞”的程序只和自己近的朋友交谈。这种情况下应该调整程序的结构,让那个对象自己拥有它羡慕的feature,或者使用合理的设计模式(例如Facade和Mediator)。

  参考:http://en.wikipedia.org/wiki/Principle_of_Least_Knowledge

  面向对象的S.O.L.I.D 原则

  一般来说这是面向对象的五大设计原则,但是,我觉得这些原则可适用于所有的软件开发。

  Single Responsibility Principle (SRP) – 职责单一原则

  关于单一职责原则,其核心的思想是:一个类,只做一件事,并把这件事做好,其只有一个引起它变化的原因。单一职责原则可以看作是低耦合、高内聚在面向对象原则上的引申,将职责定义为引起变化的原因,以提高内聚性来减少引起变化的原因。职责过多,可能引起它变化的原因越多,这将导致职责依赖,相互之间产生影响,从而极大的损伤其内聚性和耦合度。单一职责,通常意味着单一的功能,因此不要为一个模块实现过多的功能点,以保证实体只有一个引起它变化的原因。

  Unix/Linux是这一原则的完美体现者。各个程序都独立负责一个单一的事。

  Windows是这一原则的反面示例。几乎所有的程序都交织耦合在一起。

  Open/Closed Principle (OCP) – 开闭原则

  关于开发封闭原则,其核心的思想是:模块是可扩展的,而不可修改的。也是说,对扩展是开放的,而对修改是封闭的。

  对扩展开放,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况。

  对修改封闭,意味着类一旦设计完成,可以独立完成其工作,而不要对类进行任何修改。

  对于面向对象来说,需要你依赖抽象,而不是实现,23个经典设计模式中的“策略模式”是这个实现。对于非面向对象编程,一些API需要你传入一个你可以扩展的函数,比如我们的C 语言的qsort()允许你提供一个“比较器”,STL中的容器类的内存分配,ACE中的多线程的各种锁。对于软件方面,浏览器的各种插件属于这个原则的实践。

  Liskov substitution principle (LSP) – 里氏代换原则

  软件工程大师Robert C. Martin把里氏代换原则终简化为一句话:“Subtypes must be substitutable for their base types”。也是,子类必须能够替换成它们的基类。即:子类应该可以替换任何基类能够出现的地方,并且经过替换以后,代码还能正常工作。另外,不应该在代码中出现if/else之类对子类类型进行判断的条件。里氏替换原则LSP是使代码符合开闭原则的一个重要保证。正是由于子类型的可替换性才使得父类型的模块在无需修改的情况下可以扩展。

  这么说来,似乎有点教条化,我非常建议大家看看这个原则个两个经典的案例——“正方形不是长方形”和“鸵鸟不是鸟”。通过这两个案例,你会明白《墨子 小取》中说的 ——“娣,美人也,爱娣,非爱美人也….盗,人也;恶盗,非恶人也。”——妹妹虽然是美人,但喜欢妹妹并不代表喜欢美人。盗贼是人,但讨厌盗贼也并不代表讨厌人类。这个原则让你考虑的不是语义上对象的间的关系,而是实际需求的环境。

  在很多情况下,在设计初期我们类之间的关系不是很明确,LSP则给了我们一个判断和设计类之间关系的基准:需不需要继承,以及怎样设计继承关系。

  Interface Segregation Principle (ISP) – 接口隔离原则

  接口隔离原则意思是把功能实现在接口中,而不是类中,使用多个专门的接口比使用单一的总接口要好。

  举个例子,我们对电脑有不同的使用方式,比如:写作,通讯,看电影,打游戏,上网,编程,计算,数据等,如果我们把这些功能都声明在电脑的抽类里面,那么,我们的上网本,PC机,服务器,笔记本的实现类都要实现所有的这些接口,这显得太复杂了。所以,我们可以把其这些功能接口隔离开来,比如:工作学习接口,编程开发接口,上网娱乐接口,计算和数据服务接口,这样,我们的不同功能的电脑可以有所选择地继承这些接口。

  这个原则可以提升我们“搭积木式”的软件开发。对于设计来说,Java中的各种Event Listener和Adapter,对于软件开发来说,不同的用户权限有不同的功能,不同的版本有不同的功能,都是这个原则的应用。