欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

关于命名你真的懂吗?–JavaBean\Domain\Entity\POJO的区别

程序员文章站 2022-06-15 12:06:58
...

关于命名你真的懂吗?–JavaBean\Domain\Entity\POJO的区别

JavaBean(Java 豆子)

JavaBeans API specification中这样写到:

The goal of the JavaBeans APIs is to define a software component model for Java, so that third party ISVs can create and ship Java components that can be composed together into applications by end users.

由来

Java语言欠缺属性、事件、多重继承功能。所以,如果要在Java程序中实现一些面向对象编程的常见需求,只能手写大量胶水代码。Java Bean正是编写这套胶水代码的惯用模式或约定。这些约定包括getXxx、setXxx、isXxx、addXxxListener、XxxEvent等。遵守上述约定的类可以用于若干工具或库。

举个例子,假如有人要用Java实现一个单向链表类,可能会这样写:

// 编译成 java-int-list_1.0.jar
public final class JavaIntList {
  static class Node {
    public Node next;
    public int value;
  }
  public Node head;
  public int size;
}

上述实现为了能够快速获取链表的大小,把链表大小缓存在size变量中。用法如下:

JavaIntList myList = new JavaIntList();
System.out.println(myList.size);

JavaIntList的作者很满意,于是开源了java-int-list库的1.0版。文件名是java-int-list_1.0.jar。发布后,吸引了许多用户来使用java-int-list_1.0.jar。
有一天,作者决定要节省内存,不要缓存size变量了,把代码改成这样:

// 编译成 java-int-list_2.0.jar
public final class JavaIntList {
  static final class Node {
    public Node next;
    public int value;
  }
  public Node head;
  public int getSize() {
    Node n = head;
    int i = 0;
    while (n != null) {
      n = n.next;
      i++;
    }
    return i;
  }
}

然后发布了2.0版:java-int-list_2.0.jar。发布后,原有java-int-list_1.0.jar的用户纷纷升级版本到2.0。这些用户一升级,就发现自己的程序全部坏掉了,说是找不到什么size变量。于是这些用户就把作者暴打一顿,再也不敢用java-int-list库了。

这个故事告诉我们,如果不想被暴打致死,你就必须保持向后兼容性。太阳公司在设计Java语言时,也懂得这个道理。所以Java标准库中,绝对不会出现public int size这样的代码,而一定会一开始就写成:

private int size;
public int getSize() { return size; }

让用户一开始就使用getSize,以便有朝一日修改getSize实现时,不破坏向后兼容性。这种public int getSize() { return size; }的惯用手法,就是Java Bean。

什么是JavaBean?

JavaBean规范:

  1. JavaBean 类必须是一个公共类, 即将其访问属性设置为 public, 如: public class Student{…}

  2. JavaBean 类必须有一个空的构造函数: 类中必须有一个无参的public构造方法

  3. 一个JavaBean类不应有公共实例变量, 类变量都为private, 如: private int age;

  4. 属性应该由一组读写方法(getXxx 和 setXxx)来访问,一般是IDE(Eclipse、IntelliJ IDEA)为属性生成getter/setter 方法

    公共类\属性私有\无参构造函数\有get、set方法

JavaBean属性一般以小写字母开头, 使用驼峰命名格式. 相应的 getter/setter 方法是 get/set 接首字母大写的属性名. 例如: 属性名为age, 其对应的getter/setter 方法是 getAge/setAge.

一些特殊情况:

  1. 如果操作的字段为boolean类型, 此时不应该叫个getter方法, 而是is方法, 例如把getName变成isName.
  2. 如果属性名的第二个字母大写, 那么该属性名直接用作 getter/setter 方法中 get/set 的后部分, 就是说大小写不变. 例如属性名为sName,方法是getsName/setsName.
  3. 如果前两个字母是大写(专有名词和缩略词等), 这种情况属性名直接接在 getter/setter 方法中 get/set 的后部分. 例如属性名为URL, 方法是getURL/setURL.
  4. 如果首字母大写,也是属性名直接接在 getter/setter 方法中 get/set 的后部分. 例如属性名为Name, 方法是getName/setName, 这种情况会出问题, 会因为找不到属性而出错: 因为默认的属性名是name.

基于JavaBean规范,很多框架利用反射实现数据与java对象的转换

Domain(域)

领域类是什么鬼?领域不是field吗?

Oxford Dict中的解释是,domain源自于法语domeine,原意是estate, belonging to a lord,后来引进英语主要指an area of territory。domain在计算机方向有两个解释:

  • 来自于数学术语,the set of possible values of the independent variable or variables of a function.

  • 因特网,a distinct subset of the Internet with addresses sharing a common suffix.

因特网这个比较好理解,网站也叫site,所以网域是借助了an area of territory的含义。而编程中的domain主要来自数学上的含义,在数据库设计中,是指一个独立的数据类型能够包含的全部取值范围。我们知道OOP中都是值传递,Java Bean就是对值的封装,它的所有取值范围就被抽象成类,和数据库中的表对应,表的一条记录又对应一个对象,那一张表所有可能的记录就是它的domain,也就是说,不同的类就是不同的domain(所有取值的集合),因此Java Bean,Entity,POJO,domain model说的其实是一个东西,而且从这个意义上也很容易将对象理解成map。

顺便提一下哲学上的解释也很有意思。中文里"范围"被翻译为scope,range或limits,而domain被翻译为"范畴",与category同义,是指哲学中对所有存在最广义的分类,是分类的最高层次的统称,是人的思维对客观事物的普遍本质的概括。所以你看,domain正好契合了OOP中一切皆是对象的思想。

Entity

实体关系模型(或ER 模型)描述了特定知识领域中相互关联的兴趣事物。基本的 ER 模型由实体类型(对感兴趣的东西进行分类)组成,并指定实体之间可能存在的关系(这些实体类型的实例)。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rOgqmwQX-1616656839069)(JAVA%E5%91%BD%E5%90%8D.assets/450px-ER_Diagram_MMORPG.png)]

使用陈的符号为MMORPG绘制的实体属性关系图。

软件工程中,ER 模型通常代表企业执行业务流程时需要记住的东西。因此,ER模型成为一个抽象的数据模型,定义一个数据或信息结构,可以在数据库中实现,通常是一个关系数据库

实体关系建模是由Peter Chen为数据库和设计而开发的,发表在1976年的一篇论文中[,1]与以前存在的想法的变体。 [2]一些 ER 模型显示由泛化-专业化关系连接的超级和亚型实体[,3]和 ER 模型也可用于特定领域本体论的规范。

POJO

POJO(Plain Ordinary Java Object)简单的Java对象,实际就是普通JavaBeans,是为了避免和EJB混淆所创造的简称。

使用POJO名称是为了避免和EJB混淆起来, 而且简称比较直接. 其中有一些属性及其getter setter方法的类,没有业务逻辑,有时可以作为VO(value -object)或dto(Data Transform Object)来使用.当然,如果你有一个简单的运算属性也是可以的,但不允许有业务方法,也不能携带有connection之类的方法。

VO

value object:值对象

通常用于业务层之间的数据传递,由new创建,由GC回收。

PO

persistant object:持久层对象

对应数据库中表的字段。

VO和PO,都是属性加上属性的get和set方法;表面看没什么不同,但代表的含义是完全不同的。

DTO

data transfer object:数据传输对象。

表里面有十几个字段:id,name,gender(M/F),age,conmpanyId(如001)…

页面需要展示四个字段:name,gender(男/女),age,conmpanyName(如今日头条股份有限公司)。

DTO由此产生,一是能提高数据传输的速度(减少了传输字段),二能隐藏后端表结构。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J1fZyiqP-1616656839072)(JAVA%E5%91%BD%E5%90%8D.assets/6ef500025174c9ec01e4.png)]

BO

business object:业务对象

BO把业务逻辑封装为一个对象。

我理解是PO的组合,比如投保人是一个PO,被保险人是一个PO,险种信息是一个PO等等,他们组合起来是第一张保单的BO。

POJO

plain ordinary java object:简单无规则java对象

纯的传统意义的java对象,最基本的Java Bean只有属性加上属性的get和set方法。

可以转化为PO、DTO、VO;比如POJO在传输过程中就是DTO。

java对象

纯的传统意义的java对象,最基本的Java Bean只有属性加上属性的get和set方法。

可以转化为PO、DTO、VO;比如POJO在传输过程中就是DTO。

相关标签: java