找回密码
 立即注册

QQ登录

只需一步,快速开始

WantSong

高级会员

65

主题

78

帖子

1113

积分

高级会员

积分
1113

活字格认证

WantSong
高级会员   /  发表于:2009-12-14 10:31  /   查看:6283  /  回复:0
题记什么是优雅?就是当你用“呕”传达你的目的,这是谈吐优雅;用“呕”实现你的思想,这是设计优雅;用“呕”充斥你的视听,这是十分优雅。
听到这里,L老师在我背上施以一记老拳,气急败坏地跺脚:“吐出来,全部吐出来。”

正文  在讨论中,我们经常会说到XO或者XXO,我搜集整理一下,列在下面:
VO——Value Object  是值对象的缩写。意即很简单的仅仅保存数据的类,在Java中又可称为JavaBean,形如:
//Order Data
public class OrderData {

private Long id;



private Integer iType; //the type of order, enumerate


private String strName; // order name


private java.util.Vector vctOrderDetail; // Order details


private PosData posData; // POS
、柜台


public Long getID(){


return ID;


}


public void setID(Long id){


this.id = id;


}


public Integer getIType() {


return iType;



}


public void setIType(Integer iType){


this.iType = iType;


}


public String getStrName () {


return strName;



}


public void setStrTitle(String strName){


this.strName = strName;


}


public java.util.Vector getVctOrderDetail () {


return vctOrderDetail;



}


public void setVctOrderDetail(Vector vctOrderDetail){


this.vctOrderDetail = vctOrderDetail;


}


public PosData getPosData () {



return posData;


}


public void setPosData(PosData data){


this.posData = data;


}

}
...//Here skip OrderDetail and PosData
  在.Net中也有类似的Setter和Getter的写法。显然这样的写法对于用代码行数统计工作量是很不准确的。

DTO——Data Transition Object  还是Value Object,只是用于特殊的目的。在Java中对EJB的调用,组织好的数据会以Value Object的方式传递,如调用参数、返回值。之所以加上“Transition”是因为对EJB的调用往往是RMI方式。
  随着“J2EE without EJB”的趋势,往往会用DTO来代替VO对值对象的称呼,原因是VO有歧义,它还有View Object的意思。
  另外一种解释是Data Object的简称,还是值对象的意思。

VO——View Object  我们往往用VO表示View Object,而不再指Value Object。在分层结构中,表示层(presentation)用到的数据类。在C/S、Applet、Jsp/Servlet这些结构中,往往还是二进制(值对象)的形式;而在XMLHttp协议的应用中,则可能是一段文本(XML或者JavaScript对象)。下面是使用XMLHttp中的一段文本示例:
<OrderData>

<id>1</id>


<iType>1</iType>


<strName>This is a test order.</strName>


<OrderDetail>


<ID>20012</ID>


<Goods_Name>
鼠标</Goods_Name>

<amount>5</amount>


<price>25.00</price>


<OrderDetail>


<OrderDetail>


<ID>20013</ID>



<Goods_Name>
键盘</Goods_Name>

<amount>10</amount>


<price>15.00</price>


<OrderDetail>

...
</OrderData>
  当浏览器得到这份文本,通过JavaScript解析就可以把相应的数据显示在画面上。当然你也可以认为这份数据是由表示层组织好后向后传递的。但是,我们不能忽略这样一些因素,业务数据并不能涵盖所有的需要显示的数据,比如我们需要将所有的订单类型列出来供客户选择;在WEB编程中,我们往往需要记住一些状态,以提供给浏览器,如token的使用。这样我们需要对前例中的Value Object做些相应的调整,如增加显示用的单元:
public class OrderDataVO {

private Long id;



private Integer iType; //the type of order, enumerate



private String strName; // order name


private java.util.Vector vctOrderDetail; // Order details


private PosData posData; // POS
、柜台


private String strTypeName; // current type name


private String[] iTypeNames; // for type list

private Integer[] iTypeIDs; // for type list
...
}



BO  即Business Object,在分层结构中,业务实现用到的数据。如前例Value Object就可以认为是一个BO。由于BO与PO紧密联系,而且这里有领域模型与失血模型的说法,我们现在看到的是失血模型。关于BO的介绍我将在PO中继续。
  我们可以看到,表现层后面、业务层的前面有一个工作:将BO组织成VO提供给表现层,将VO提取成BO提交给业务层,这是控制层的工作之一。

PO——Persistent Object  在面向对象的编程(OOP)中,我们必须关心对象的持久化(简单点,就是数据的保存)。PO就是用来做持久化的类。前例的Value Object不是一个PO。在这里我们假设数据源是关系型数据库(我们大多也只会用到这样的数据源)。

PO对应的是数据库中一个或一组数据。如上述的Order,在持久化时需要保存一条主单信息,多条明细信息。如果我们的映射工具(O/R Mapping)足够强大,使我们可以忽略数据库中的关系(外键,如表设计时,需要在明细中记录主单ID),这样的PO可以认为是与BO等价的。我们可以执行“OrderPO.save()”就能够实现多条数据的持久化。
  然而如果我们的工具不够强大,不能完整地解决所有映射关系,那我们需要将一个BO拆解成多个PO去持久。也就是以个PO往往与一个表对应。在Order例中,我们需要先保存主单PO,然后取出主单ID,插入到所有的明细PO中,再对明细持久化,并且这一系列操作应该在一个事务中实现。  

PO有三种状态:
1.Transient,未被持久化的,此时的PO就是一个Value Object,由VM管理其生命周期;
2.Persistent,已被持久化的,且在框架工具管理的Session内。此时映射数据库数据,由数据库管理生命周期。也就是说,此时的PO对应的是数据库中的记录,它的创建、更改和删除对应的是数据库中记录的Insert、Update和Delete;而内存中其他的数据对象,它们的生命周期是由虚拟机来维护的,对应的是New、Set和Destroy。
3.Detached,曾被持久化的,但现在和Session已经分离,以Value Object的身份在运行。
  在O/R Mapping工具成熟之前,由于每个项目都会遇到类似问题,我们是如何处理的?
  继承抽象类的方式:
public abstract class TO{

private int _getNewId(Connection cnct) {. . .}


private int insert(Connection cnct){. . .}


private int update{Connection cnct}{. . .}


public void deleteByID(Integer id, Connection conn){. . .}


public void getByID(Integer id, Connection conn){. . .}


public int getID(){. . .}


public int save(Connection conn){. . .}


public abstract String getIdentity();

public abstract String getTBName();

}
  这个TO提供了大部分的对表操作的公共方法,如果具体对某个表进行操作,我们只需要继承这个抽象类即可:
public TBOrder extends TO{

public Long id;



public Integer iType; //the type of order, enumerate


public String strName; // order name


public java.util.Vector vctOrderDetail; // Order details


public PosData posData; // POS
、柜台

public
String getIdentity(){

return “id”;


}


public String getTBName(){


return “TB_Order”;


}


...

}
  如果构造的TBOrder属性与实际表TB_Order字段一致,TO利用反射就可以构造操作表的SQL。如果要维护主从表这种一对多关系,我们可以要求开发者在实现TBOrder时进行硬代码,先存主TBOrder,再存TBDetail。我们也可以用配置文件记录这些类与表的映射。
  还有一种方式也有一定的代表性,用动态Map,这样开发时不必写过多的类。
public final class PO{

private Map mapData;


private String strClassName;


private int iState = 0; //PO
状态,0:初始化未入库时;1:从库中取出,可修改;2:删除标志

private int iSubscript = -1; //PO_Class[]
中的下标,默认为-1

private int iDataChage = 0; //check for update



private boolean bLobFlag = false;


. . .

}
  上例是一个PO类通过配置文件,映射了所有的数据库表。这种方式在开发时会带来一些不便,请比较一下“PO.getID()”与“(Long)PO.getProperty(“ID”)”在开发时的异同(我不是指敲的字不一样多哦)。
  因此由于需要记录状态位,PO最不可能的便是值对象,但我们使用Hibernate或者JDO这些工具时,并没有额外要求我们继承某个特殊的接口或者留下状态位。它们是如何做的?  这里稍微引用点IOC &amp; AOP的知识,我们知道AOP的织入(Wave)时间有编译时、载入时和运行时三种。

JDO使用了编译时:我们写完Value Object类后,需要用JDO提供的小工具对编译后的二进制跑一下,生成了真正的PO。这个被称为buildtime class enhancement。

JDO2和Hibernate则利用CGLIB2,在载入时/运行时对我们写的Value Object类进行增强,使其具有状态位。如果你在运行时把Hibernate中的PO导出并反编译,会发现此PO非彼PO。不过由于要在第一次加载Class到VM的时候要做动态产生bytecode和内存占用较多(由于要缓存产生的bytecode),这是他们的缺点。



TO——Table Object  实际是PO的一种,只是框架没有提供更强的关系映射,只能用类来映射某张表,如上例中用到的TO。

DAO——Data Access Object  请注意,这是一种模式,而不是某个类。应用这个模式最大的目的是抽象数据源,提供对数据的透明访问:
1.管理Transaction
2.封装DataSource,JDBC
3.便于进行统计/log操作
4.便于进行权限控制



SDO——Service Data Object  这是IBM的SOA架构中几个要素中的一个,是以上提到的DTO、VO、BO等的泛称。拥有动态模型(类似于Map)和静态模型(类似于ValueObject)两种。


  如果接触Java,可能还会听到以下两个O:
PICO  是杰出的IOC &amp; AOP 容器之一,全面是PICOContainer。

POJO
Plain-Old Java Object,即Value Object。是在O/R Mapping中被推广的一种做法:不依赖继承;可以轻松的换掉持久框架而不影响程序。
后记LB听到这里,诡异地笑了笑,“听过DSO么?”
“不知道,愿闻其详。”
“我们‘摸大象’的都知道DSO是‘Data Store Object’,在诊察终了后的用来存储缓存数据的。小样,你新来的吧?!”
L老师点点头,语重心长得说,“我们出来吐的,迟早是要吃回去的。不过也没关系,年轻人,吐啊吐啊的就习惯了。”


跋  文中故事纯系虚构,文中概念纯属抄袭。

0 个回复

您需要登录后才可以回帖 登录 | 立即注册
返回顶部