如果我说,要写好代码,必须违背这些原则,我想所有人都会骂:疯子、胡说八道、哗众取宠,找打!
以前我也会骂那个疯子,但现在不会,而且我会肯定地、负责任地说:这是真的!
首先我们要知道这六大原则是什么。
六大设计原则主要是指:
单一职责原则(Single Responsibility Principle);
开闭原则(Open Closed Principle);
里氏替换原则(Liskov Substitution Principle);
迪米特法则(Law of Demeter),又叫“最少知道法则”;
接口隔离原则(Interface Segregation Principle);
依赖倒置原则(Dependence Inversion Principle)。
也就是我们说的SOLID原则。但从来没有人告诉我们这六大原则之间是什么关系,他们之间能同时满足吗?
要知道任何事物都不是孤立地存在的,它总是同周围其他事物相互联系着、相互依赖着、相互制约着、相互作用着。
这些原则之间同样也有联系,也是有主次关系。其中开闭原则是这之中最重要,最根本的一个原则,是系统架构的根本目的,其他五个原则是指导服务于开闭原则。开闭原则是我们的根本目的,一切要从开闭原则出发,它是唯一判断标准。
这五个指导原则的共同目的是一样的,都是为了达成系统对扩展开放,对修改关闭。但在实际中我们要想做到开闭,就不得不去违背这五个原则。因为开闭是根本要求,而五个原则又不是唯一的实现途径,必然导致其他方式跟他们起了冲突。如果为了开闭,而要违背原则,我们也不得不去违背,否则就本末倒置了。
首先是迪米特法则,该法则表明一个对象应该对其他对象有最少的了解。通俗地讲,一个类应该对自己需要耦合或调用的类知道得最少。
那我们要如何做到最少呢?常用的方法就是建立一个中介类封装复杂的操作,但这只是把复杂的东西转移到中介类了,中介类就会违背了这个原则。当然我们可以在中介类里面再封装其他中介类,一层层封装下去,但这造成的一个后果就是:系统中存在大量的中介类,这些类之所以存在完全是为了传递类之间的相互调用关系。就会出现《重构》说的坏味道:过度耦合的消息链(Message Chains)。出现坏味道往往无法满足开闭原则。
为了满足开闭原则,某些情况下我们就必须做一个取舍,中介类要几个?要在哪一个中介类去违背它?于是我们就得到一个看似矛盾的结论为了满足迪米特法则而不得不去违背它!
迪米特法则跟单一职责原则也是冲突的,单一职责说的是一个类应该有且只有一个改变的原因。也就是一个类只负责一个功能,但我们的业务场景往往是需要多个功能配合使用的,这些功能粒度如果拆的很细,我们为了完成业务功能,就必须要对很多的类有了解。可以看出单一职责跟中介类是矛盾的,而中介类的目的又是为了满足迪米特法则,进而得出迪米特法则跟单一职责也是矛盾的。
我们往往要选择违背单一职责!可以负责任,肯定地说:单一职责越得到充分的体现,违背开闭原则的地方就越多。
首先单一职责原则会引起类的剧增,给维护带来非常多的麻烦。其次本来一个类可以实现的行为硬要拆成两个类,然后再使用聚合或组合的方式耦合在一起,人为制造了系统的复杂性。最后一个类究竟拆到什么程度才算单一,往往是把握不住的,里面的水很深,如果为了满足这个原则,强行去考虑,只会适得其反,捡了芝麻丢了西瓜。