数据库和数据对象的关系,面向对象数据库
在我上学的时候,一聊到设计模式都是很有格调的话题,仿佛设计模式就是解决软件开发的精髓,但是很长一段时间,我从骨子里是排斥设计模式的,因为我觉得自己连面向对象的知识都没有领悟,谈论设计模式还为时尚早,我尤其排斥那本被吹到爆炸的《大话设计模式》,那本设计模式看上去给你用形象的比喻讲明白数据库和数据对象的关系了一个东西,但实际上你真正开始写代码的时候,发现自己什么都写不出来。
这篇博客是想退一步思考,总结一些面向对象的知识,比如思考“对象与对象的关系”到底是怎样的。
和大部分人一样,初学面向对象的时候,都会铺天盖地地听到一些词汇,比如“面向对象的三大特性是继承,封装,多态。”,再比如一切都是对象。但如果你仅仅记住这几句话,真的很难领悟面向对象这件事。我记得自己真正对面向对象有过一次深入体会是在读完《c++编程思想》,这本书的第一章是关于介绍oop的,作者通过一个面向过程的c代码到c++的oop书写方式,引出了面向对象的一些精髓,比如面向对象其实是一种思想,早期在用c的时候,也可以用面向对象的思路去写(struct+函数),但这种代码是单向绑定的,支持面向对象的代码的好处是完成 *** 与数据的双向绑定。而不像struct那样,不知道谁使用了此数据结构。
这些关于封装的知识理论上被称为基于对象,但说句实在的,对于很多人而言,能在系统中用封装的思想将系统建模就已经很不容易了,这可能听上去有点夸张,但仔细想想,对于一个人,一个苹果,一张订单让你去建模,你可能很容易就建了,但如果是类似Controller,Action,Execute这些看上去像是动作的对象呢数据库和数据对象的关系?
再比如一些复杂的系统,如何抽象出领域模型,让系统能够清晰地交互,这些都不是那么容易的。再说继承与多态,其实继承本身和多态不像是处于同一平行线的概念。这个继承,在java中其实分继承接口和继承类,而继承类则主要是为了代码复用,只不过这种复用是静态的,而多态更像是动态的复用。
在c++中没有这么分类,c++提供的oop看上去更像是为数学公式准备的,所有只有继承类这么一说,只不过你定义一个只有虚函数的类,这个类就成接口了。而且c++的继承还包括公有继承,保护继承,私有继承等等继承权限,还有友元和多重继承。这些东西不是没用,而是一般人用不来,所以在java中都选择了精简。
在说回面向对象本身,这种编程思想说来说去都可以总结为以下几点:
(1)所有数据都应该隐藏在它所有的类内部。
(2)类的使用者必须依赖类的公有接口,但类不能依赖它的使用者。
(3)不要把实现细节放到类的公有接口中。
(4)面向对象的 *** 签名,其实算是消息协议,面向对象的本质其实是对象与对象之间发送消息。
完成了上面关于oop的回顾介绍之后,我就要引入这篇博客的主要内容了,对象与对象之间的关系。
使用关系简单的来说,我这样理解面向对象,每个对象封装了自己的状态和协议,而一个对象总想使用另一个对象。总结出一个对象如何使用另一个对象的方式,就基本归纳了面向对象建模的所有场景。
我很喜欢拿汽车和加油站的关系来举这个例子,这个例子是我从《OOD启示录》这本书上读到的。
汽车要如何使用加油站呢?
首先它可以作为参数传递给加油站:
Class Car{voidget_gasoline(GasStation gasStation);}或者它作为Car的一个属性,虽然啊这看上去有点怪,好像这个车只能去指定地点加油。
Class Car{private GasStation gasStation;void get_gasoline(){gasStation...}}不过更怪的是土豪模式,直接new一个加油站出来。
Class Car{void get_gasoline(){GasStation gasStation = new GasStation();}}还有一种退一步的方式,是从另一个地图对象来获得加油站对象,不过这又引出了另一个问题,这个地图对象是从哪来的?
Class Car{void get_gasoline(){GasStation gasStation = map.getGasStation();}}以上的这些都是一个对象想使用另一个对象的方式,我要特别提醒一下那个作为一个属性的方式,同样是定义一个类的属性,比如一个person有一个name属性,那就是它拥有一个属性,算包含关系,而如果是一个person有一个country属性,这个时候就是关联关系了,就像是数据库里面的关联字段一样。不过更官方的叫法,其实将对象与对象的关系分为四种:依赖关系(Dependency),关联关系(Association),聚合关系(Aggregation),组合关系(Compostion)。其中把作为局部变量, *** 参数,或者调用一个类的静态 *** 称为依赖关系。而关联关系,聚合关系,组合关系,都用成员变量的方式表现,但是它们所表达的对象生命周期和耦合度是不一样的。
继承除了使用一个对象,还可以通过继承的方式来获得这份“代码”,不过汽车继承一个加油站看上去太奇怪了。前面提到了,多态是动态的获得,而继承更像是静态的获得,就好像编译器把这份代码给你拷贝过去了一样。设计模式的书常常把继承说的一文不值,说“用组合不用继承”,但如果两个类真有某种父子关系,使用组合而不是继承看上去是很怪的,而且维护性也很差,比如你子类继承了你的父类,那只要给父类添加一个 *** ,那子类是默认就获得了,但是如果你使用了组合,你就不能方便的拥有这些 *** ,要一个个的子类去引用这个新的实现。
多重继承提到继承就不得不提到多重继承,这个东西在java这种语言中被禁用了,很多人说java可以实现多个接口,但是接口和继承类完全不是一个概念,继承类是重用,那接口有能啥重用的地方?充其量是定义协议而已。多重继承这个思想本身没有问题,比如一个木头门继承于门和木头两个父类。这样任何一个父类添加一个新的属性或 *** ,都会默认被木头门继承,这是很自然的建模。而一个木头门有两个属性分别是门和木头,这个就很诡异。多重继承比较被人抨击的主要是那种钻石继承,父类之间签名相同之类的问题,不过有些语言会提供“限制版”的多重继承,来既让你使用多重继承,又不会提升代码的复杂度。比如Mixin(混入类)。
元类最后再说说元类,这个概念来源于元编程,什么是元编程,就是编写生成代码的代码。比如DSL,比如c++中的模板,元类呢就算是用来创建类的类。这个我在python中偶尔会使用一下。一个简单的入门是你可以用type来创建一个类对象(type就是元类)。
Foo = type("Foo", (object,), {"hello": hello})
不过大多数的使用场景是设置类的__metaclass__属性,而在创建这个类的时候,扩展这个类。
今天的分享就到这里了,希望对大家有帮助~
不懂就问,对于准备学习编程的小伙伴,如果你想更好地提升你的编程核心能力(内功)不妨从现在开始!
编程学习书籍分享:
编程学习视频分享:
整理分享(多年学习的源码、项目实战视频、项目笔记,基础入门教程)
欢迎转行和学习编程的伙伴,利用更多的资料学习成长比自己琢磨更快哦!
对于C/C++感兴趣可以关注小编在后台私信我:【编程交流】一起来学习哦!可以领取一些C/C++的项目学习视频资料哦!已经设置好了关键词自动回复,自动领取就好了!