接着上回的说,虽然我们已经找出了阻挡我们通用化Android数据库操作的五个问题,但是现在我们还不能立即开始去解决这些问题。
试想一下,我们有一个News
,那么,相应的就会有NewsDao
和NewsDaoImpl
,同理,如果出现一个Book
,是不是也要写出BookDao
和BookDaoImpl
? 这个问题想想就觉得太疯狂!
这里的BookDao
等等都是假想的,和NewsDao
是一样的东西,就不在复制黏贴一遍了。(偷笑中….)
那么,在解决五个问题之前我们需要做的工作就是,把NewsDao
和BookDao
中公共的部分在提取一次;把NewsDaoImpl
和BookDaoImpl
中的公共部分也再提取一次。
工作需要一步一步做,那么我们首先抽取NewsDao
和BookDao
接口中公共的部分,并放在BaseDao
中。既然是抽取公共的,那么原先位于NewsDao
中,传入特定的参数(如:Integer、News)可能就不在适用了,我们需要寻找更为一般、通用的东西来替代,而泛型就是我们的好帮手(O(∩_∩)O~)。
public interface BaseDao<M> {
/**
* 增加
*/
long insert(M m);
/**
* 删除<
* 传入的参数可能或是Integer或者Long或者String,
* 那么此处就不能够使用具有特殊性的类型,要使用具有一般性的、公共的。<
* 而Serizlizable,则是Integer、Long、String共性的不二选择。
*/
int delete(Serializable id);
/**
* 修改
*/
int update(M m);
/**
* 查询所有
*/
List<M> findAll();
}
是不是很简单?
我们把公用的方法抽取到BaseDao
中,并把参数替换成为泛型和Serializable,这样NewsDao
只需要继承我们的BaseDao
并传入泛型,就大功告成了。代码如下:
public interface NewsDao extends BaseDao<News> {
// 既然提取完公共的了,那么这些具有特殊性的就不需要了
// 另外,实现BaseDao接口
// long insert(News news);
// int delete(int id);
// int update(News news);
// List<News> findAll();
// 当然,除了通用的增删改查,还具有一些特有的方法
// 比如,查询按时间排序的最新的新闻
}
是不是这个样子?NewsDao
里面空空如也,当然,如果我们需要一些更为特殊的方法,还是需要写在这里面的,例如:查询按时间排序的最新的新闻。
既然接口中的公共的方法能够抽取,那么它们的实现类也是不能够例外的。我们抽取实现类(NewsDaoImpl
和BookDaoImpl
)中公共的部分,放在BaseDaoSupport
中。
这里要记住BaseDao
和BaseDaoSupport
之间,只不过是NewsDao
和NewsDaoImpl
的映射,它们之间也是实现类的关系。
public abstract class BaseDaoSupport<M> implements BaseDao<M> {
// * 抽取公共部分应该解决的问题:<br>
// * 问题1:表名的获取<br>
// * 问题2:如何将实体中的数据,按照对应关系导入到数据库中<br>
// * 问题3:明确实体中主键是谁?获取到主键中封装的值<br>
// * 问题4:实体的对象创建<br>
// * 问题5:如何将数据库中表的列的数据,按照对应关系,封装到实体中<br>
private Context context;
private DBHelper helper;
private SQLiteDatabase db;
public BaseDaoSupport(Context context) {
super();
this.context = context;
this.helper = new DBHelper(context);
this.db = helper.getWritableDatabase();
}
@Override
public long insert(M m) {
// 请在此处填写代码
return 0;
}
@Override
public int delete(Serializable id) {
// 请在此处填写代码
return 0;
}
@Override
public int update(M m) {
// 请在此处填写代码
return 0;
}
@Override
public List<M> findAll() {
// 请在此处填写代码
return null;
}
}
我们来看一下BaseDaoSupport
中的东西,我们抽取出了Context
、DBHelper
、SQLiteOpenHelper
还有构造函数,看起来和我们的NewsDaoImpl
中的东西一样。
再看看下面的insert
、delete
、update
、findAll
等方法,模子是一样的,只不过里面具体的参数替换成了泛型。
回过头我们看看被抽取完的NewsDaoImpl
变成什么样子了,首先继承了BaseDaoSupport<News>
并传入了自己所要操作的实体bean,然后又实现了NewsDao
接口。代码如下:
public class NewsDaoImpl extends BaseDaoSupport<News> implements NewsDao {
public NewsDaoImpl(Context context) {
super(context);
}
}
好像除了构造函数就空空如野了,但实际情况并非如此,我们在BaseDaoSupport
中,已经实现了BaseBase
接口,并且重写了insert
、update
、delete
、findAll
等方法,这样我们NewsDaoImple
中就继承了这些公共的方法了。
到了这一步是不是很开心! O(∩_∩)O~ ,代码看着越来越清爽了!
到了这一步,我们的抽取和重构就基本完成了,那么我们接下来的工作重点就位于BaseDaoSupport
,只要我们能够在此类中解决上一篇文章中碰到的五个问题,那么我们就可以做到Android中数据库的通用操作了。
是不是有点小激动了!! 别着急,我们慢慢来,请看下回分解!
最后把重构完成后的包结构展示给大家:
如果你浪费了自己的年龄,那是挺可悲的。因为你的青春只能持续一点儿时间——很短的一点儿时间。 —— 王尔德
原文地址:http://blog.csdn.net/biezhihua/article/details/44003805