Java多种对象学习

本文介绍了Java中的基础对象模型,包括POJO(简单的Java对象)、PO(持久化对象)、DAO(数据访问对象)、DTO(数据传输对象)、BO(业务对象)和VO(值对象)。它们各自的特点、用途和在软件架构中的角色得到了详细解释。

POJO(plain old/ordinary java object)

普通的JavaBean,仅包含自身的属性及对应的getter、setter方法,没有继承任何类,没有实现任何接口,没有被其它框架请入的对象。
POJO特点是简单及灵活,使得其能够任意扩展,易于迁移与复用。

public class Customer{
	private int id;
	private String name;
	//对应getter、setter方法
	public String getName(){return name;}
	....
}

PO(presistence object)

对象字段持有的数据需要被持久化到数据表中,参与到持久化操作的对象就被称为持久化对象。
《开发手册》中也将PO称为DO(data object),因为其自身属性通常与数据库表结构一一对应,能够将数据表中的一条记录作为一个对象处理,并转化为其它对象(如果需要的话)。
同POJO类似(多序列化版本信息),其内部包含:

  • getter、setter方法;
  • 与数据表结构对应的属性;
  • (一般)不包含业务逻辑及数据库访问,因为数据库本身不包含这些内容;
  • 在分布式存储或前端输出及远程调用时需要实现序列化,其余情况下一般不需要。
public class User implements Serializable {
    //序列化版本,通过IDEA自动生成
    private static final long serialiVersionUID = 1Lprivate Long id;
    private String username;
    private String password;    
    //省略getter和setter方法
}

DAO(data access object)

包含:

  • 对数据的访问;
  • 对持久层的操作

通常结合PO来访问数据库,主要用于封装对数据的访问,并不转化为其他对象。
只在基于”事务脚本“的业务设计时包含业务逻辑,其余情况下只包含持久化封装。

public interface Dao{
    int insert(User user);
    User selectById(long id);
}

DTO(data transfer object)

《开发手册》规定为Service或Manager向外传输的对象,为了减少方法调用次数而在进程间传输数据的对象。
在输入方面,请求时应用在接口接收传入对象,转化为实体进行持久化,此过程中传入对象就是DTO;
在输出方面,响应时PO转换为DTO进行返回。

多个不同小DTO:PO的内容并不需要全部返回,则选取特定部分每次创建小的DTO,创建次数多,传输数据清晰;
单个大DTO:尽可能一次封装多个(可能的)PO组成DTO,减少调用次数,但难以掌握传输数据。

//继承实体类,从查询到的PO中添加属性返回给前端
public class UserDTO extends User {
    //序列化版本
    private static final long serialiVersionUID = 2L//用户标识
    private String username;
    public String getUsername(){return username;}
    public void setUsername(String username){this.username= username;}
    //添加额外属性
    private HashMap<String, Object> extProperties;        
    public HashMap<String, Object> getExtProperties() {
        return extProperties;
    }
    public void setExtProperties(HashMap<String, Object> extProperties) {
        this.extProperties = extProperties;
    }
}

Entity

实体存在于一个生命周期中,拥有自身状态。例如抽象订单一个唯一识别号作为实体,订单从创建到最后交货结束完成一整个生命周期,其状态可以变化。
实体会被给予一个唯一标识以互相区分,相对的值对象VO不需要互相区分。

与VO区别:

Entity对象的唯一标识相等,则判定两个对象相等,即使其他属性不同,同时可以修改实体状态;
VO没有标识,只当所有属性相等,才判断两个对象相等。同时不能修改,只能创建新的VO。

与PO区别:

PO与数据表结构对应,通常也会赋予PO一个主键ID(同数据库),称为委派标识。例如身份证号作为实体标识唯一区分其它身份证,但在数据库中也可能会分配自增主键ID,便于存储。当VO需要持久化时也会被分配委派标识,方便查询和与外键关联;
实体标识与业务相关,委派标识与技术相关只作用于存储便利。

public class Entity{
    private int id;
    int getId(){return id;}
}

VO(value object)

值对象通常只作用于业务层数据传递,仅包含自身数据。

  1. VO通常时小而简的对象,如日期、地址等,值相同则判断两个对象相等;
  2. VO需易于创建,参数传递通常是值传递而非引用传递;
  3. VO不应被持久化,创建后只能被引用,无引用时被垃圾回收。

与Entity区别:

没有唯一标识,无生命周期,内部值不变;

与PO区别:

PO只在数据层作为存储,VO在商业逻辑层和表示层,作为概念整体。

//比如Address这样无唯一标识的就是值对象
public class Address{
    private String country;
    private String province;
    private String city;
    public Address(String country, String province, String city) {
        this.country= country;
        this.province= province;
        this.city= city;
    }
    //省略equals方法
}
//调用值对象,若要修改值对象,值对象不用维护,直接创建一个全新的Address对象
//原对象直接被抛弃,而不是在原对象上进行修改
public Address changeAddress(String newCity, String newProvince, String newCity) {
    return new Address(newCity, newProvince, newCity);
}

VO(view object)

此处VO通常是Web向模板渲染引擎传输的对象,《开发手册》建议把输出的显示曾对象命名为VO,也有人将这个对象命名为DTO。
同时由于许多页面需要额外数据,则会把响应的DTO封装为VO------显示层对象再显示出来。

//Controller层
public HttpResult list(@RequestBody XXParam param){
    HttpResult vo=HttpResultUtils.convert(XXDTO);
    return vo;
}

BO(business object)

BO就是把业务逻辑封装为一个业务对象,只包含业务对象自身的业务逻辑,不包含对外协调的逻辑,这个业务对象可以包含一个或多个其他对象。
“充血模型”指将对象的数据及行为(其本身的业务逻辑)封装在一起,service类仅用作协调称为应用服务层。这样,当业务不断演化时,只用关注BO,减轻应用层面的变化。因此BO也成为DO(domain object)的另一种说法。

public class User implements Serializable{
	private String name;
	private String password;
	//对象自身的业务逻辑
	public void changePassword(String newPassword){
		this.setPassword(newPassword);
	}
	//省略getter、setter方法
}

QO(query object)

数据查询对象,各层用于接受上层的查询请求。当超过两个参数的查询封装,则禁止使用Map类传输

public class MyQO {
  private String param1;
  private String param2;
  ...
}
@PostMapping("/post")
public String post(@RequestBody MyQO qo) {
  ......
}
MyBO bo = service.createBO(qo);//创建业务对象
bo.dosomething();
//将业务对象存储在不同的表中
MyPO po1 = service.createPO1(bo);
dao1.save(po1);
MyPO po2 = service.createPO2(bo);
dao2.save(po2);
MyPO po3 = service.createPO3(bo);
dao3.save(po3);

AO(application object)

一般用于控制层和服务层间,作为Param和VO或Param和DTO的组合,将前端查询的属性和保存的属性几乎一致的对象封装为AO。如读取用户属性传给前端,用户在前端编辑了用户属性后传回后端。

//Controller层
public HttpResult update(@RequestBody XXAO ao1){
	XXAO ao2 = XXService.update(ao1);
	HttpResult vo = HttpResultUtils.convert(ao2);
	return vo;
}

总结

  1. POJO:简单Java对象,它没有任何限制和特定的约定,是一个普通的Java对象。
  2. DTO:数据传输对象,它是一个数据传输结构,通常用于不同进程间的数据传输,在不同层之间传递数据的对象。
  3. DAO:数据访问对象,是一个数据访问模式,在应用程序中它通常扮演着对数据库的访问。
  4. PO:持久化对象,通常指ORM(对象关系映射)中映射的数据库表对应的实体类。
  5. BO:业务对象,是应用程序中业务逻辑的实现。
  6. VO:值对象,它是一个用于存储数据的对象,通常是与UI/界面模型相关的对象。
  7. QO:查询对象,它主要用于定义查询条件和规则,用于接收前端传递的查询条件参数。
  8. ENTITY:实体对象,是一个与业务相关的对象,通常是与应用程序领域模型相关的对象。
  9. 习惯目录结构:

PO----bean、entiyt、model目录;
DAO----DAO、mapper、repository目录;
BO----service、manager、business、domain、model目录;
DTO----command、representation、DTO目录。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值