面向对象思想
“依赖于抽象而非依赖于实现”话句话说“针对于接口编程,而非针对于实现编程”or
“依赖于基类而不是具体实现的子类”:
面向对象概念里的抽象其实说白了,就是能把问题或者事物用一种通用的情形来描述或表达,所以有了基类子类的概念,在解决一些问题的时候,发现某些类和某些类组合在一起更适合解决这些问题,而且让扩展更方便;所以这些解决问题的方法、思路和思想被总结和抽象一下就是所谓的设计模式。
面向抽象编程,关键就四字:“封装变化”,纵观各种设计模式,无一不体现这一思想,如Builder模式,封装对象构建过程,Strategy模式,封装算法具体实现等等。
本质上来说,面向对象和面向过程的核心思想是一样的,区别在于面向过程的重点在功能划分,并耦合于函数原型;而面向对象的重点是功能+数据的划分,并耦合于接口,接口就是对象的原型!!!要注意的接口是划分的产物。如果连对象都没划分清楚,就开始设计接口,最后一定会做不少无用功,弄不好整个软件被糟糕的接口绑架而走上歧途。
对象的划分比功能划分要困难许多,因为功能之间的关系可以表示为堆栈模型,是树状结构(或DAG,递归另算,因为一般不会使用复杂递归),而数据之间的关系则非常复杂,它有两个方面:空间和值(相当于lvalue和rvalue,前者用于引用,后者用于计算),数据的空间关系是一般图结构,值关系则是倒挂的树状结构,这也是为什么在自动化静态分析中,数据分析比过程分析困难许多。而数据的两重特性更加重了对象划分的困难。
这在设计模式里面可没提到,因为那本书是先假设你已经划分好了,然后根据划分的关系给你提供了20多种模式让你选择。如果一上来就先考虑模式,那你就输了。但是在某些显而易见的局部设计中,快速选择一种正确的模式,是条捷径,这也是设计模式这本书的目的。
正是因为对象划分的困难,所以才有重构,因为人不可能总是走在正确的路上。重构实际上是一种把你往正确道路上引导的方法,使得软件在演化的过程中不至于撞南墙也不回头。但是实际的效果还是由人决定的,因为最终是人来选择往哪个方向去重构。实现各种各样的接口是一个很沉重的负担,必要的时候再用。如果每个类都从接口实现起,会很累。有时候强耦合其实也很好,切莫臆造接口,盲目套用设计模式。
在大的项目中,你提供接口给别人用,这时候别人只关心你的接口是如何声明的,在接口声明为抽象类,通常有virtual声明的虚函数。这时候别人依赖的就是你的接口了,不是实现。你的实现可以修改,接口可以不改。如果有多种实现,具体用哪个实现一般由接口的使用者去选择,可以在配置文件中写。