通过 DAOFactory 的泛型写法来演示Java泛型的特殊用法
小型项目中常常都没有用三方持久化框架,而大都是用公司或自行依据DAO模式封装的一些组件来完成数据库持久化动作,并且,通常为了更具可扩展性,常常使用抽象工厂模式来解耦合。
一、先看代码
1、简单工厂代码
import java.io.Serializable;
import com.china.codingmouse.cmsdk4j.config.CmSdk4jConfigurationReader;
import com.china.codingmouse.cmsdk4j.dao.generaldao.GeneralDAO;
import com.china.codingmouse.cmsdk4j.dao.generaldao.IGeneralDAO;
import com.china.codingmouse.cmsdk4j.dao.genericsdao.GenericsDAO;
import com.china.codingmouse.cmsdk4j.dao.genericsdao.IGenericsDAO;
import com.china.codingmouse.cmsdk4j.exception.GeneralException;
/**
* 数据访问工厂。<br><br>
*
* 用于封装常规以及泛型数据访问动作实现的构建。
* @param <T> 泛型类型参数。
* @author CodingMouse
* @version 1.0
* @see AbstractDAOFactory
* @since JDK1.5
*/
public class DAOFactory<T extends Serializable> extends AbstractDAOFactory<T> {
/**
* 构建常规数据访问动作实例。
* @return 常规数据访问动作接口实例。
*/
@Override
public IGeneralDAO buildGeneralDAO() {
try {
// 从配置档中读取常规数据访问动作实现类完全限定名
String className = CmSdk4jConfigurationReader.getInstance().getBaseSetting(false).getGeneralDAOFullName();
// 如果没有配置则返回默认实现类实例
if (className == null
|| className.length() == 0)
return new GeneralDAO();
// 否则,将配置的实现类加载到虚拟机环境并通过默认构造器构建实例
Object instance = Class.forName(className).newInstance();
// 返回实现类实例
return IGeneralDAO.class.cast(instance);
} catch (Throwable e) {
// 调试信息
String debugMsg = "Configuration items <generaldao> the contents of the invalid, " +
"can not be converted to the specified class interface " + IGeneralDAO.class.getName() + " instance.";
// 抛出自定义异常
throw new GeneralException(debugMsg, e);
}
}
/**
* 构建泛型数据访问动作实例。
* @return 泛型数据访问动作接口实例。
*/
@Override
@SuppressWarnings("unchecked")
public IGenericsDAO<T> buildGenericsDAO() {
try {
// 从配置档中读取常规数据访问动作实现类完全限定名
String className = CmSdk4jConfigurationReader.getInstance().getBaseSetting(false).getGenericsDAOFullName();
// 如果没有配置则返回默认实现类实例
if (className == null
|| className.length() == 0)
return new GenericsDAO<T>();
// 否则,将配置的实现类加载到虚拟机环境并通过默认构造器构建实例
Object instance = Class.forName(className).newInstance();
// 返回实现类实例
return IGenericsDAO.class.cast(instance);
} catch (Throwable e) {
// 调试信息
String debugMsg = "Configuration items <genericsdao> the contents of the invalid, " +
"can not be converted to the specified class interface " + IGenericsDAO.class.getName() + " instance.";
// 抛出自定义异常
throw new GeneralException(debugMsg, e);
}
}
}
2、抽象工厂代码
import java.io.Serializable;
import com.china.codingmouse.cmsdk4j.dao.generaldao.IGeneralDAO;
import com.china.codingmouse.cmsdk4j.dao.genericsdao.IGenericsDAO;
/**
* 抽象数据访问工厂。<br><br>
*
* 用于封装数据访问工厂实现的构建。
* @param <T> 泛型类型参数。
* @author CodingMouse
* @version 1.0
* @see DAOFactory
* @since JDK1.5
*/
public abstract class AbstractDAOFactory<T extends Serializable> {
/**
* 获取抽象数据访问工厂实例。
* @param <T> 泛型类型参数。
* @return 抽象数据访问工厂实例。
*/
public static<T extends Serializable> AbstractDAOFactory<T> newInstance() {
return new DAOFactory<T>();
}
/**
* 构建常规数据访问动作实例。
* @return 常规数据访问动作接口实例。
*/
public abstract IGeneralDAO buildGeneralDAO();
/**
* 构建泛型数据访问动作实例。
* @return 泛型数据访问动作接口实例。
*/
public abstract IGenericsDAO<T> buildGenericsDAO();
}
3、客户端代码
import com.china.codingmouse.cmsdk4j.dao.factory.AbstractDAOFactory;
import com.china.codingmouse.cmsdk4j.dao.factory.DAOFactory;
import com.china.codingmouse.cmsdk4j.dao.generaldao.IGeneralDAO;
import com.china.codingmouse.cmsdk4j.dao.genericsdao.IGenericsDAO;
import com.china.codingmouse.cmsdk4j.example.pojo.AccountPOJO;
/**
* 演示泛型/非泛型DAO工厂的创建。
*
* @author CodingMouse
* @version 1.0
* @see DAOFactory
* @see AbstractDAOFactory
* @since JDK1.5
*/
public class TestFactory {
public static void main(String[] args) {
// 演示泛型DAO工厂的创建方法
AbstractDAOFactory<AccountPOJO> factory = AbstractDAOFactory.newInstance();
IGenericsDAO<AccountPOJO> dao = factory.buildGenericsDAO();
AccountPOJO account = dao.get(AccountPOJO.class, 2);
System.out.println(account);
// 演示普通DAO工厂的创建方法
IGeneralDAO dao2 = AbstractDAOFactory.newInstance().buildGeneralDAO();
AccountPOJO account2 = (AccountPOJO) dao2.get(AccountPOJO.class, 1);
System.out.println(account2);
dao2.closePool();
}
}
二、然后说明
1、简单工厂代码中使用反射机制构建外部指定的实现类来创建接口 IGeneralDAO 和 IGenericsDAO 的实例。这样以来,我们可以将工厂制造的产品类型放到外部来配置以降低耦合度。其中,有两个抽象方法实现,方法签名为 public IGeneralDAO buildGeneralDAO() 的这个方法没有使用泛型机制,而方法签名为 public IGenericsDAO<T> buildGenericsDAO() 的这个方法则使用了泛型机制。
2、抽象工厂代码中名为 newInstance 的静态方法使用了泛型机制。请注意泛型的写法。
3、客户端代码中则演示了用相同的抽象工厂,如何构建泛型和非泛型的方法。需要注意的是:
与下面这种写法是不一样的(这段代码无法通过编译,原因在于这时AbstractDAOFactory.newInstance().buildGenericsDAO()返回的是IGenericsDAO<Serializable> 类型,而非IGenericsDAO<AccountPOJO> ):
怎么样?感觉类似的写法,效果却大不相同。慢慢体会吧!
By CodingMouse
2010年1月11日