自从有了接口的概念后,OO编程都推荐面向接口编程。根据“如非必要,勿增实体”的原则,通常我们定义(或重构出来)的接口都是有行为的,很少用空接口。那么空接口有什么用呢?
一个接口定义了两方面,类别和特征。比如
public interface Animal{
void eat();
void sleep();
}
定义了类别Animal,它的特征是:可以eat和sleep。如果我们不关心sleep,这个接口就变成
public interface Animal{
void eat();
}
这两个Animal描述的是现实中的同一类别,只是关心的角度不同,抽取出的特征也不同。
更进一步,如果连eat这个特征我们都不关心,这个接口就变成了一个空借口
public interface Animal{
}
定义这样一个借口相当于阐述以下事实“尽管现在不关心动物具体有什么特征,但本接口的存在说明系统中动物和非动物是有区别的,以后也可能会用到这些区别”。
这样,Tree不用实现Animal,但Dog应该实现Animal。空命名接口的存在对类的设计给出了约束,即方便了以后扩展,也让后来者理解代码更加方便。可以认为是“代码即文档”的一种体现。
-------------------------------------------------------------------------------------------------------------------------
在通常的业务系统中,分页查询是非常常用的功能。对这样的查询,在用Toplink(Hibernate应该也一样)实现时一个最佳实践是不用对象,而用SQL实现。
假设User包括id,name,birthday,gander,department,isActive几个属性,在“维护用户”界面上需要分页显示id,name,birthday,gander。那么DAO不要返回一个Page对象给Service,而应该自定义一个PagingUserResult
public class PagingUserResult{
private String id;
private String name;
private Date birthday;
private Gander gander;
//.. Getter and Setter
}
并返回Page<PagingUserResult>给Service。这是因为
1)Toplink组装对象的时间比较长,特别是如果在UnitOfWork中作这件事,每个User会被Clone一份到UnitOfWork中,整体时间消耗要多不少。
2)分页功能牵涉的数据量是比较大的,如果User组装成对象,一旦翻上几页,这些实际不会操作到的对象就会把缓存中的User都挤出缓存,使得缓存命中率非常低,使得用缓存不如不用。
所以,设计框架时要求分页查询都用ReportQuery,不允许出现直接返回Page<User>给Service的情况。当然,这样的规范必须通知Service的实现者。这可以通过文档,code review等方式,不过最好的方法是在框架中尽量杜绝Service这样作的可能性,这时候空接口就派上作用了。
首先定义一个空接口
public interface QueryResult{
}
由于具体的QueryResult(比如PagingUserResult)就是个Bean,所以QueryResult没有共同行为,只是一个标识作用。
然后,定义Page接口
public interface Page<T extends QueryResult> {
T get(int index);
//.... other functions
}
这里,通过泛型表达了“Page只能容纳QueryResult”,由于User是Domain对象,不会实现QueryResult,自然不可能被放到Page中了。
当然,由于Page只是一个接口。为了使用方便,框架还要提供一个PageBuilder,这里是一个大概的样子
public class PageBuilder<T extends QueryResult> {
private List<T> contents=new ArrayList<T>();
public PageBuilder<T> add(T content) {
contents.add(content);
return this;
}
public Page<T> buildPage(){
// You may need a inner class which implements Page<T> here
}
}
总结一下,结合空接口QueryResult和泛型,我们避免了developer以后由于不了解而误用的情况。
类似的,也可以让Domain对象实现一个叫作Entity的空接口,可以规范DAO的使用,避免像DAO中传入非Domain的Class。
分享到:
相关推荐
- **服务做些什么**:指服务提供的具体操作或方法。 - **如何访问服务**:包括数据格式、通信协议等。 - **服务位于何处**:即服务的地址,通常用URL表示。 这些属性共同构成了Web服务的核心信息,帮助开发者了解和...
增强恶意空单拦截,有效应对恶意客户拦截传递过程中的订单信息后提交空单行为 6、升级优化邮件系统内核到最新 7、对空间要求更宽泛,只要空间支持PHP就能使用,支持绝大多数的PHP空间 8、相关提示更加人性化,...
- `NullPointerException`,当试图访问空引用时抛出。 18. **err 和 exception的区别**: - `System.err` 通常用于输出错误信息。 - `Exception` 是所有异常类的基类。 19. **List, Set, Map是否继承自...
HashMap是Hashtable的轻量级实现(非线程安全的实现),他们都完成了Map接口,主要区别在于HashMap允许空(null)键值(key),由于非线程安全,效率上可能高于Hashtable。 HashMap允许将null作为一个entry的key或者...
HashMap是Hashtable的轻量级实现(非线程安全的实现),他们都完成了Map接口,主要区别在于HashMap允许空(null)键值(key),由于非线程安全,效率上可能高于Hashtable。 HashMap允许将null作为一个entry的key或者...
- 运行时异常是程序运行时可能出现的错误,比如空指针异常,无需在方法签名中声明。 - 一般异常(检查异常)则需要在方法中声明抛出,否则编译不通过。 5. **Servlet的生命周期**: - 每个Servlet实例在服务器...
答:一般从CPU的NMI端引入的中断为非屏蔽中断,它不受中断允许标志IF的影响,其类型号为2,系统中只能有一个非屏蔽中断,CPU不论在做什么事,都会响应些中断,它一般用来处理系统的重大故障。 一般从CPU的INTR端...
这样,你就能一次又一次地使用该方案而不必做重复劳动."上述定义是对设计模式的广义定义.将其应用到面向对象软件的领域内,就形成了对设计模式的狭义定义. 可以简单的认为:设计模式就是解决某个特定的面向对象软件问题...
哪种更好些?为什么? - **强类型**:类型在编译时确定,更安全可靠。 - **弱类型**:类型在运行时确定,灵活性高但可能引入错误。 - 强类型通常被认为更优,因为它减少了运行时错误的可能性。 #### 31. 什么是反射...
11、增强支付宝付款接口,在支付宝业务调整,免签接口失效后,本店第一时间升级了订单系统,提供了收款码收款(支付宝收款码获取方法及替换方法见附送的 WORD 文档)及支付宝商户(即时到账、担保交易)双接口,方便...
10、增强支付宝付款接口,在支付宝业务调整,免签接口失效后,本店第一时间升级了订单系统,提供了收款码收款(支付宝收款码获取方法及替换方法见附送的WORD文档)及支付宝商户双接口,方便买家根据自己的需求切换...
除了這些基礎接口外,V4L2 API 中還包含了編碼和效果設備的 stub,雖然這些功能尚未完全確定,但其目的是轉換視頻數據流。此外,還包括了 “teletext” 和 “radiodatasystem” 的接口,這些接口目前在 V4L1 API 中...
`ArrayList`是实现`List`接口的一个具体类,它是一个动态数组,支持快速随机访问,但插入和删除元素相对慢些。`ArrayList`的构造方法有多种,可以为空、基于现有集合或预设大小。 在Java中,`String`类是不可变的,...
关于所要求的对象我们需要知道些什么? - **对象概念**:了解wxPython中的各种对象,如`wx.App`、`wx.Frame`等。 - **对象的作用**:每个对象都有其特定的功能,如`wx.App`用于管理整个应用程序的生命周期。 ####...
我们可能还会遇到另外一个问题,即当用户的口令为空时,即使你做了上述的所有的更改还是不能进行登录,访问还是会被拒绝。(如用administrator账号,密码为空时)这是因为,在系统“安全选项”中有“账户:使用空白...
PTZ代表Pan(左右旋轉)、Tilt(上下傾斜)和Zoom(變焦),這些攝影機能夠進行全方位運動,適用於需要覆蓋更大範圍或需細節放大查看的場景。 ##### 日夜兩用型網路攝影機 這種攝影機能在低光照條件下工作,通常配...
韩国人手机上的J2ME手机游戏哈里波特源代码,运行于LG手机,因些声音方面需要LG特有的API,如果你没有LG的SDK的话,可以建立一个空接口,游戏目前在SJBOY下可以正常运行,但是没有声音。图片资源请在jar包里提龋
在《產銷履歷標籤列印程式》中,開發者可能利用了.NET框架中的System.Drawing命名空間,該命名空間提供了圖形編程接口,可以方便地進行圖形绘制、圖像處理和打印操作。通過創建Graphics對象,開發者能夠在標籤模板上...
不过,我们可以根据文件名“SPEZ18K_110630”做些推断。"SPEZ"可能是编程器型号的前缀,"18K"再次确认了该编程器与18K容量的芯片有关,而"110630"可能是软件版本号或发布日期,表示2011年6月30日。 在IT行业中,...