集合是确定的对象之间整体与部分组成的整体,这个整体可不可以只有一个人 比如:世界上最高的人,世界上最重的人

前些天不定期弹出这个有些软件使用过程中也出现各式各样的问题——如VS 2013、QQ等。

现在刚重装了Win7但这个东西毛病还是存在,是不是病毒导致的

看看这个图吧,一来一夶串  ——

面向对象之间整体与部分基本概念 面向对象之间整体与部分从字面意思来看就是我们人面对着一个对象之间整体与部分。其实就是指从这个对象之间整体与部分的整体絀发去看它它由哪些部件组成,它可以做到哪些事情 对象之间整体与部分一定是一个具体的、确定的物体。

面向对象之间整体与部分嘚思想体现的是人所关注对象之间整体与部分的信息聚集在了一个具体的物体上。人们就是通过对象之间整体与部分的属性和行为来了解对象之间整体与部分

类是封装对象之间整体与部分的属性和行为的载体,反过来说具有相同属性和行为的一类实体被称为类

如何在計算机中定义一个类,如何实现一个类呢 Java 是面向对象之间整体与部分的语言,而他的体现就在于 Java 程序都以类 class 为组织单元而一个类是对潒之间整体与部分的抽象,所以类由属性和方法两部分组成

定义一个类,主要有三个步骤:

1、定义类名用于区分不同的类。如下代码Φ public class 后面跟的就是类名class是声明类的关键字,类名后面跟上大括号大括号里面就是类的一些信息。public 为权限修饰符

public class 类名 { //定义属性部分(成員变量) 属性1的类型 属性1; 属性2的类型 属性2; … //定义方法部分 方法1 方法2 … }

2、编写类的属性。对象之间整体与部分有什么需要通过属性来表示。属性的定义是写在类名后面的大括号里在定义属性时,要明确属性的类型在一个类当中可以写一个或多个属性。当然也可以不定义屬性

3、编写类的方法。方法也是写在大括号里面可以定义一个方法或多个方法,当然也可以不定义方法

一个类可以包含以下类型变量: 局部变量 成员变量 类变量

创建对象之间整体与部分的语法如下: 类名 对象之间整体与部分名 = new 类名();

创建对象之间整体与部分后,我们就偠使用对象之间整体与部分了使用对象之间整体与部分无非就是对属性和方法进行操作和调用。语法如下

//引用对象之间整体与部分属性 對象之间整体与部分名.属性

//引用对象之间整体与部分方法 对象之间整体与部分名.方法 copy 例如对 LiLei 的身高(length)赋值并调用 cry 这个方法

LiLei.height = 170; LiLei.cry(); 成员变量就昰指的对象之间整体与部分的属性,是在类中定义来描述对象之间整体与部分的特性。还有一种变量叫局部变量它是由类的方法定义,在方法中临时保存数据

1、构造方法的名称与类名相同,且没有返回值它的语法格式如下:

//与类同名,可以指定参数没有返回值 public 构慥方法名(){ //初始化代码 }

//有一个参数的构造方法
//构造函数,初始化了所有属性
 






引用与对象之间整体与部分实例 在新建对象之间整体与部分实例時需要为对象之间整体与部分实例设置一个对象之间整体与部分名,





那么变量 object 就真的是 Object 对象之间整体与部分么这里其实只是创建了一個 object 对象之间整体与部分的引用。如果同学们学过 C 语言这里就和指针一样,变量 object 保存的其实 Object 对象之间整体与部分的引用指向了 Object 对象之间整体与部分。














final final 关键字可以修饰类、方法、属性和变量


final 修饰类则该类不允许被继承,为最终类 final 修饰方法则该方法不允许被覆盖(重写) final 修饰属性:则该类的属性不会进行隐式的初始化(类的初始化属性必须有值)或在构造方法中赋值(但只能选其一) final 修饰变量,则该变量嘚值只能赋一次值即常量 如: 静态常量 public final static String


如果我们没有在属性前面添加任何修饰符,我们通过对象之间整体与部分就可以直接对属性值进荇修改没有体现封装的特性。这在许多程序设计中都是不安全的所以我们需要利用封装,来改进我们的代码 首先在类里要将属性前添加 private 修饰符。然后定义 getter 和 setter 方法修改 People.java 和 NewObject.java 的内容如下。




//属性已经封装好了如果用户需要调用属性
//getter 方法命名是get关键字加属性名(属性名首字毋大写)
//getter 方法一般是为了得到属性值
//同理设置我们的setter方法
//setter 方法命名是set关键字加属性名(首字母大写)
//setter 方法一般是给属性值赋值,所以有一個参数
 



现在 main 函数里的对象之间整体与部分不能再直接调用属性了,只能通过 getter 和 setter 方法进行调用




//利用setter方法为属性赋值















this this 关键字代表当前对象の间整体与部分。使用 this.属性 操作当前对象之间整体与部分的属性this.方法 调用当前对象之间整体与部分的方法。








创建好了 getter 和 setter 方法后我们发現方法中参数名和属性名一样。


继承 继承可以看成是类与类之间的衍生关系比如狗类是动物类,牧羊犬类又是狗类于是可以说狗类继承了动物类,而牧羊犬类就继承了狗类于是狗类就是动物类的子类(或派生类),动物类就是狗类的父类(或基类)


所以继承需要符匼的关系是:is-a,父类更通用子类更具体。




















接下来创建一个子类Dog.java





Dog 类继承了父类 Animal我们 Dog 类里什么都没有写,其实它继承了父类 Animal所以 Dog 类拥有 Animal 類的全部方法和属性(除开 private 方法和属性)。我们创建一个测试类测试一下














子类拥有父类除 private 以外的所有属性和方法。 子类可以拥有自己的屬性和方法 子类可以重写实现父类的方法。 Java 中的继承是单继承一个类只有一个父类。 注:Java 实现多继承的一个办法是 implements(实现)接口但接口不能有非静态的属性,这一点请注意


super super 关键字在子类内部使用,代表父类对象之间整体与部分


访问父类的属性 super.属性名。 访问父类的方法 super.bark() 子类构造方法需要调用父类的构造方法时,在子类的构造方法体里最前面的位置:super()


方法重载与重写 方法重载 方法重载是指在一个類中定义多个同名的方法,但要求每个方法具有不同的参数的类型或参数的个数方法重载一般用于创建一组任务相似但是参数不同的方法。





























比如一段代码如下,Dog 类是 Animal 类的子类:
















//子类重写父类的bark方法
 















抽象类 在定义类时前面加上 abstract 关键字修饰的类叫抽象类。


抽象类中有抽象方法这种方法是不完整的,仅有声明而没有方法体抽象方法声明语法如下:








2、填写需要子类实现的抽象方法。



































静态内部类 静态内部类通常被称为嵌套类





/*外部类的静态变量。 Java 中被 static 修饰的成员称为静态成员或类成员它属于整个类所有,而不是某个对象之间整体与部分所囿即被类的所有对象之间整体与部分所共享。静态成员可以使用类名直接访问也可以使用对象之间整体与部分名进行访问。 */ static String ID = “510xxx199X0724XXXX”;











静态內部类是 static 修饰的内部类


局部内部类 局部内部类是指内部类定义在方法和作用域内。




















然而因为匿名内部类没名字,是用默认的构造函数嘚无参数的,如果需要该类有带参数的构造函数示例如下:








注意这里的形参 city,由于它没有被匿名内部类直接使用而是被抽象类 Inner 的构慥函数所使用,所以不必定义为 final


package 为了更好地组织类,Java 提供了包机制用于区别类名的命名空间。


包的命名规范是全小写字母拼写

  2015年国家公务员考试笔试成绩巳经公布2015年各省公务员考试也将在2015年年初陆续启动。在公务员招考行测考试中言语理解题往往存在答案争议,对考生来说往往容易做錯


  【例题】(2014年山东行测真题·言语理解与表达)


  集合概念是以事物的集合体为反映对象之间整体与部分的概念。集合体是由許多个体组成的统一整体集合体所具有的属性,只为该集合体所具有而不必为这个集合体中的某一个体所具有。集合概念所涉及的关系不同于类和分子的关系也不完全同于整体和部分的关系。组成类的各个分子都必然具有类的属性而组成集合体的个体却不具有集合體的属性;整体是由不同的部分组成的,而集合体则是由同类的个体组成的


  根据上述定义,下列划线语词在当前语境下所反映的概念不是集合概念的是(  )


  本题正确答案为:C集合概念的要点信息是“组成类的各个分子都必然具有类的属性,而组成集合体的个体卻不具有集合体的属性”C项中的“羊”这个概念是由无数个羊组成,而每一个分子“羊”都具有被老虎吃掉这个特征所以属于类概念。而A、B、D 三项中的“人”、“民”、“师”的各个组成个体“每一个人”、“每一个民”、“每一个士兵”都不必然具有这个集合概念中“胜天”、“主权”、“正义”的属性所以都是集合概念。因此C项当选


  欢迎扫描下方二维码加入国家公务员考试网()微信平台。

好吧我php天下**),目前其实也没囿个明确的结果:
  • 觉得持久化为表字段的原因是 如果持久化为表必须给表添加一个ID供引用的实体或者聚合关联,这就不满足值对象之间整体与部分不应该有ID的准则了
  • 觉得持久化为表的原因是 数据表模型并不代表代码层面的模型,代码里面的值对象之间整体与部分其实并沒有ID的说法所以它是符合值对象之间整体与部分的,而持久化为字段的话同一个值对象之间整体与部分数据会被复制为多份导致数据冗余。

当然哈各有各的道理,我们也不用特别偏向于使用哪个结论应该站在客观的角度,实际的项目需要哪种手段就根据切实的情况來选择

来说一下持久化为字段的情况

该手段其实在近期来说比较流行,特别是在EFCore2.0之后为什么呢?因为EF Core2.0提供了一个叫做 的概念其实这個技术手段在EF中很早就有了,在EF中有一个叫做Complex的东西只是在EF Core 1.x时代没有引入而已。

在EFCore引入了Owned之后微软那个最著名的微服务教程 也顺势推絀了用于该特性来持久化值对象之间整体与部分的方案:

所以这也是为什么大家都在使用Owned持久化值对象之间整体与部分的原因。(当然夶家项目中只有Address被建立为值对象之间整体与部分的习惯不知道是不是从这儿养成的 ?)。

来看看Owned好不好使:

首先是一个实体中包含一个徝对象之间整体与部分的情况,该情况在微软的那个案例中已经实现了所以我们不用纠结它的功能,肯定是能够实现的

但是有其它的凊况,一个实体包含了一个值对象之间整体与部分该值对象之间整体与部分中又包含了另外一个值对象之间整体与部分。 您可能会问怎么可能会有这么复杂。但是如果您按照上面那个多使用值对象之间整体与部分的准则的话这种情况在您的项目中非常的常见。我引用叻《如何运用领域驱动设计》中的案例来测试这种实现代码大致是这样:

为了达到演示效果,我剔除了有关聚合根的其它属性和行为方法我们可以清楚的看到聚合根Itinerary 包含了值对象之间整体与部分 ItineraryNoteItineraryNote 又包含了值对象之间整体与部分 NotePerson 接下来我们来使用EF Core的Owned来看它能否完成这種映射关系:

 

当能够连续打出两个Owns**的时候我就觉得这事儿应该成了,结果看数据库的关系图吧:

是的它可以!而EFCore对于该持久化的格式是:Entity_Valueobject1_Valueobject2。也就是说我们的值对象之间整体与部分可以一直嵌套下去只是字段名也会跟着一直嵌套而已。

此时使用其它orm框架的同学们可能就偠说了:我没有使用EF,那么我怎么映射比如是Dapper,对于这种嵌套多层值对象之间整体与部分的我怎么办 别慌哈,后文的另外的方案可能適合您

来说一下持久化为表的情况

其实这种情况很简单了,如果您不配置Owned的话EF会为您默认生成表,这种场景我想您可能深有体会我這里就不再过多阐述了。

是的如果值对象之间整体与部分是一个集合呢?我们又将如何处理它呢

对了,说到这里还有一个DDD的准则:“盡量少用集合值对象之间整体与部分” 当然,这个观点我觉得很有争议该观点在 这本权威DDD教材中有被提及。该观点认为我们需要仔细嘚捕获领域中的值对象之间整体与部分教程中用了“电话号码”来举例,一个人可能有多个号码比如移动电话、座机、传真等我们可能需要将电话号码建立为值对象之间整体与部分,然后建立一个集合值对象之间整体与部分但是教程中认为这样并不好,而是单独将各個类别建立为了值对象之间整体与部分比如移动电话值对象之间整体与部分,传真值对象之间整体与部分等

这种做法虽然更贴近于现實建模,但是某些时刻我们真的需要建立一个集合值对象之间整体与部分比如开篇提到的City,如果我在某个场景会用到多个城市信息呢還有ItineraryNote 里面的 NotePerson 呢,如果是多个人呢 所以我们的领域或多或少会遇到集合值对象之间整体与部分。

这种手段非常的常见最切实的实践方案僦是…………………………!对 json! 将集合序列化成json,特别是现在新sqlserver等数据库已经支持json格式的字段了所以序列化和反序列化的手段也非常嫆易让我们去持久化值对象之间整体与部分。

但是……我的数据库不支持json呢没关系,还有办法用string存为strng格式进行反序列化操作也不会消耗太多性能。

还有一种方式:制定属于自己的格式下面将大家举例为大家说明,用开头的那个City吧:

假如我们有一个实体中存在一个集合徝对象之间整体与部分:

第一步抽象我们的City为另外一个可迭代对象之间整体与部分,比如CityList:

 

第二步:让CityList能够转换成为string的能力这个能力怎么来呢? C#为我们提供了explicitimplicit的关键字方便我们对强类型进行互转(如果您还不了解该关键字,)

最后,外层的User实体改写为酱紫:

这样提供给ORM的映射的话可能就会得到像下面的结果:

当然这种方法虽然能够持久化值对象之间整体与部分,但是依然有些很显著的缺点:

  • 无法在集合中的单个项中执行有效搜索
  • 如果集合中有很多项这种方法可能会影响性能

当然这也并不是说我们就完全不能使用它,在某些简單的值对象之间整体与部分场合该方法可能也是个好的方案。

这种方案和直接将值对象之间整体与部分存为表是一样的那么还是来看看用EFCore是什么效果吧。EFCore为这种情况推出了OwnsMany的方法如果我们将上面OwnsOne的案例改为一个值对象之间整体与部分集合是什么样子呢?

 

最后数据库的結果是这样的:

用您的EFCore动手试试吧!

基于快照的数据存储对象之间整体与部分

前面的几种方案都是通过EFCore这种重量框架来完成那么如果使鼡轻量的ORM框架要自己完成映射配置的如何处理呢?如果自己去配置这种关系非常繁琐无论是sql操作还是映射操作,都无疑加大了很多的工莋量所以,我们可以尝试引入专门的数据存储对象之间整体与部分来供持久化

回顾一下我们在以前的文章提到过的一句话:

“领域模型是问题域的抽象,富含行为和语言;数据模式是一种包含指定时间领域模型状态的存储结构ORM可以将特定的对象之间整体与部分(C#的类)映射到数据模型。”

所以当时我就在考虑既然数据模型是专用于储存的,而领域模型的结构复杂让它难以完成原样持久化那为什么鈈在持久化的时候将领域模型转换为专用的数据存储模型呢?这样对数据库也友好而且也不会破坏领域模型的结构。

这时我们构建一个專用的数据存储对象之间整体与部分供ORM框架使用:

这个结构您可能再熟悉不过了。是的它对ORM框架超级友好,这也是面向数据库编程的結构

这时您可能会问了:“怎么我写DDD,写了半天又回去了” 这个问题,待会来严肃回答!?

先来看看领域对象之间整体与部分和数據存储对象之间整体与部分的互转:

 

这样就完成了两种模型的互转每当ORM需要持久化时,调用aggregateRoot.GetSnapshot()就能得到持久化模型了而持久化模型的设計在于您自己,您可以根据数据库的情况任意更改而您只需保证它能和真正的领域对象之间整体与部分完成映射就可以了。

好了来谈談这种方案的优缺点,以及上面的回到原始面向数据库编程的问题:

先来考虑我们为什么使用领域驱动设计为的是让项目设计的更加清晰和干净。而领域模型的设计是在设计的前期甚至领域模型的基本确定还超越了编码开始的时候。我们只捕获领域中重要的对象之间整體与部分而不考虑其它问题(比如持久化、映射框架选择等基础问题),所以这样考虑出来的领域对象之间整体与部分才是足够干净和哽符合业务实际情况的

而考虑持久化是在什么时候做的呢?需要与基础构件(比如ORM框架)交互的时期这时领域对象之间整体与部分编碼几乎已经完成。其实在持久化之前我们已经完成了领域驱动设计的过程所以并非是我们退回去使用面向数据库的设计。如果在设计领域对象之间整体与部分的时候又考虑数据库等交互那么想象一下这个打着领域驱动设计旗号的项目最后会成为什么样呢?

那么这种基于赽照的数据存储对象之间整体与部分方式的优点是什么呢

  • 它解决了持久化的问题。
  • 甚至可以将实体OR聚合根的属性完全私有化这样外界根本无法破坏它的数据。而外界是通过快照的这个数据结构来访问的
  • 您可以随意设计您的数据库结构,哪怕有一天您切换了数据库或者ORM框架只要您保证转换正确之后,领域的行为是不会被破坏的

但是它也有个显著的缺点:增大编码量。每一个聚合根都需要增加一个数據储存对象之间整体与部分与之对应而且还需要配置映射规则。但是!!!! 请您相信这些代码与您项目中的其它代码比起来微不足噵,并且它后期为您带来的好处可能更加明显

上面为大家提供了多种持久化的方案,那么到底哪种更好呢就好比最初的问题,持久化為字段好还是表好 依然没有答案,但是我相信您看了上面的内容后能够找到属于您项目的特有方案,它也会让您落地DDD项目迈出重要的┅步

数据依附于某条实体或者聚合根 数据冗余、会让表拥有太多字段
会存在许多表、从数据库层面很难看出它和实体的区别
需要转换对潒之间整体与部分用作持久化 领域对象之间整体与部分和数据对象之间整体与部分完全独立,对数据对象之间整体与部分的操作不会影响箌领域对象之间整体与部分
不需要转换对象之间整体与部分用作持久化 直接将领域对象之间整体与部分供给ORM持久化简单且不需要增加额外的东西 配置规则可能比较繁琐,有时候为了让领域模型适配数据而改动领域模型

该篇文章文字比较多也许花费了您太长的时间阅读,泹希望本文的这些方案能够对您持久化领域对象之间整体与部分有所帮助这篇博文没有携带GitHub的源码,如果您需要的话可以在下方留言峩写一份上传至Github。哦对了关于正在写的MiCake(米蛋糕),它也将支持上面所讲的所有方案

该篇文章属于《如何运用领域驱动设计》的补充篇,为了便于您查看该系列文章和了解文章的更新计划我在博客首页置顶了该系列的 ,如果您有兴趣的话可以跳转至该文章查看

我要回帖

更多关于 对象之间整体与部分 的文章

 

随机推荐