接上一篇博客:http://blog.csdn.net/chaogu94/article/details/52397749
Demo1:多层数据访问层切换事例,在多种数据库之间切换时而不影响其他代码的改变,根据面向对象的思想,使用MVC的设计模式,一点一点的进行优化。
文件属于那个包中可自行比对,不在多说
第一版本:
结构目录:
Depart.java://
package com.mq.class1.reflectdemo.entity;
public class Depart {
private int deptNo;
private String name;
public int getDeptNo() {
return deptNo;
}
public void setDeptNo(int deptNo) {
this.deptNo = deptNo;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Depart() {
super();
// TODO Auto-generated constructor stub
}
public Depart(int deptNo, String name) {
super();
this.deptNo = deptNo;
this.name = name;
}
@Override
public String toString() {
return "Depart [deptNo=" + deptNo + ", name=" + name + "]";
}
}
IDepart.java:
package com.mq.class1.reflectdemo.dao;
import java.util.List;
import com.mq.class1.reflectdemo.entity.Depart;
public interface IDepart {
/**
* 通过部门ID查找部门
*
* @param id
* @return
*/
public Depart getDepartById(int id);
/**
* 查找所有的部门
*
* @return
*/
public List<Depart> getAllDepart();
}
DepartService.java:
package com.mq.class1.reflectdemo.mysqldaoImpl;
import java.util.List;
import com.mq.class1.reflectdemo.dao.IDepart;
import com.mq.class1.reflectdemo.entity.Depart;
public class DepartService implements IDepart{
@Override
public Depart getDepartById(int id) {
System.out.println("mysql------------->根据编号"+id+",可以查找出相应的部门");
return null;
}
@Override
public List<Depart> getAllDepart() {
// TODO Auto-generated method stub
System.out.println("mysql------------->查找出所有的部门");
return null;
}
}
DepartManager.java //重点
package com.mq.class1.reflectdemo.biz;
import java.util.List;
import com.mq.class1.reflectdemo.dao.IDepart;
import com.mq.class1.reflectdemo.entity.Depart;
import com.mq.class1.reflectdemo.mysqldaoImpl.DepartService;
public class DepartManager {
private IDepart dao = null;
/**
* 在构造函数中创建dao层对象IDepart
*/
public DepartManager() {
// TODO Auto-generated constructor stub
dao = new DepartService();
}
public Depart getDepartById(int id) {
dao.getDepartById(id);
return null;
}
public List<Depart> getAllDepart() {
// TODO Auto-generated method stub
dao.getAllDepart();
return null;
}
}
第二版本
如果要更改连接的数据库为sql server,要符合面向对象的open-close的原则,则最好不要动原来的代码,应该增加一个包,存放使用sql server数据库的代码
结构目录:
DepartService.java
package com.mq.class1.reflectdemo.sqlserverdaoImpl;
import java.util.List;
import com.mq.class1.reflectdemo.dao.IDepart;
import com.mq.class1.reflectdemo.entity.Depart;
public class DepartService implements IDepart{
@Override
public Depart getDepartById(int id) {
System.out.println("sql server------------->根据编号"+id+",可以查找出相应的部门");
return null;
}
@Override
public List<Depart> getAllDepart() {
// TODO Auto-generated method stub
System.out.println("sql server------------->查找出所有的部门");
return null;
}
}
更改DepartManager类:
package com.mq.class1.reflectdemo.biz;
import java.util.List;
import com.mq.class1.reflectdemo.dao.IDepart;
import com.mq.class1.reflectdemo.entity.Depart;
import com.mq.class1.reflectdemo.mysqldaoImpl.DepartService;
public class DepartManager {
private IDepart dao = null;
/**
* 在构造方法中传递进来一个接口Idepart,可以自由的进行dao层的转换
*
* @param dao
*/
public DepartManager(IDepart dao) {
this.dao = dao;
}
public Depart getDepartById(int id) {
dao.getDepartById(id);
return null;
}
public List<Depart> getAllDepart() {
// TODO Auto-generated method stub
dao.getAllDepart();
return null;
}
}
Test类做相应的改变:
package com.mq.class1.reflectdemo.view;
import com.mq.class1.reflectdemo.biz.DepartManager;
import com.mq.class1.reflectdemo.dao.IDepart;
import com.mq.class1.reflectdemo.mysqldaoImpl.DepartService;
public class Test {
public static void main(String[] args) {
IDepart mysqlDao = new DepartService();
DepartManager departManager = new DepartManager(mysqlDao);
// 调用biz层中DepartManager类的getDepartById方法和getAllDepart方法
departManager.getDepartById(1);
departManager.getAllDepart();
IDepart sqlserverDao = new com.mq.class1.reflectdemo.sqlserverdaoImpl.DepartService();
departManager = new DepartManager(sqlserverDao);
// 调用biz层中DepartManager类的getDepartById方法和getAllDepart方法
departManager.getDepartById(1);
departManager.getAllDepart();
}
}
输出结果:
mysql------------->根据编号1,可以查找出相应的部门
mysql------------->查找出所有的部门
sql server------------->根据编号1,可以查找出相应的部门
sql server------------->查找出所有的部门
第三版本:
为了让界面层看起来更加的简单,对代码进行了如下的操作
1.使用工厂模式,创建dao层
2.达到在界面层输入好使用的数据库类型,就可以使用这种类型的数据库
结构目录:
AppType.java
package com.mq.class1.reflectdemo.basetype;
public enum AppType {
sqlserver, mysql, oracle
}
Factory:
package com.mq.class1.reflectdemo.factory;
import com.mq.class1.reflectdemo.basetype.AppType;
import com.mq.class1.reflectdemo.dao.IDepart;
import com.mq.class1.reflectdemo.sqlserverdaoImpl.DepartService;
public class Factory {
private static Factory factory = null;
private static IDepart dao = null;
public static Factory getInstance() {
if (factory == null) {
factory = new Factory();
}
return factory;
}
/**根据不同的类型创建相应的dao层
* @param type
* @return
*/
public IDepart createDepart(AppType type) {
switch (type) {
case sqlserver:
dao = new DepartService();
break;
case mysql:
dao = new com.mq.class1.reflectdemo.mysqldaoImpl.DepartService();
break;
default:
break;
}
return dao;
}
}
更改DepartManager.java:
package com.mq.class1.reflectdemo.biz;
import java.util.List;
import com.mq.class1.reflectdemo.basetype.AppType;
import com.mq.class1.reflectdemo.dao.IDepart;
import com.mq.class1.reflectdemo.entity.Depart;
import com.mq.class1.reflectdemo.factory.Factory;
import com.mq.class1.reflectdemo.mysqldaoImpl.DepartService;
public class DepartManager {
private IDepart dao = null;
private Factory factory = null;
/**
* 在构造方法中传递进来一个枚举类型的参数,可以根据参数创建相应的dao层
*
* @param dao
*/
public DepartManager(AppType type) {
factory = new Factory();
this.dao = factory.createDepart(type);
}
public Depart getDepartById(int id) {
dao.getDepartById(id);
return null;
}
public List<Depart> getAllDepart() {
// TODO Auto-generated method stub
dao.getAllDepart();
return null;
}
}
修改Test.java,界面更加简单:
package com.mq.class1.reflectdemo.view;
import com.mq.class1.reflectdemo.basetype.AppType;
import com.mq.class1.reflectdemo.biz.DepartManager;
public class Test {
public static void main(String[] args) {
//改变AppType.sqlserver或者AppType.mysql可以切换两个数据库
DepartManager departManager = new DepartManager(AppType.sqlserver);
departManager.getDepartById(1);
departManager.getAllDepart();
}
}
第四版本:
第三版本虽然已经充分体现了高内聚低耦合的特点,但是如果要新增一个数据库,就会在DepartManager文件里添加相应的代码,要重新进行编译,如果量比较大的话则速度很慢。所以进行了一下的更改,使用配置文件的方式。新增加xml文件。如下
config.xml:
<?xml version="1.0" encoding="UTF-8"?>
<basics>
<basic>
<name>mysql</name>
<package>com.mq.class1.reflectdemo.mysqldaoImpl</package>
</basic>
<basic>
<name>sqlserver</name>
<package>com.mq.class1.reflectdemo.sqlserverdaoImpl</package>
</basic>
</basics>
要达到这样的效果,只需要更改Factory.java文件,如下:
package com.mq.class1.reflectdemo.factory;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.InvalidPropertiesFormatException;
import java.util.List;
import java.util.Properties;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import com.mq.class1.reflectdemo.basetype.AppType;
import com.mq.class1.reflectdemo.dao.IDepart;
import com.mq.class1.reflectdemo.sqlserverdaoImpl.DepartService;
public class Factory {
private static Factory factory = null;
private static IDepart dao = null;
public static Factory getInstance() {
if (factory == null) {
factory = new Factory();
}
return factory;
}
/**
* 根据不同的类型创建相应的dao层
*
* @param type
* @return
*/
public IDepart createDepart() {
String myPackage = getTypeFromXML();
String className = myPackage + ".DepartService";
IDepart dao = null;
try {
Class<?> class1 = Class.forName(className);
dao = (IDepart) class1.newInstance();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return dao;
}
/**
* 使用dom4j或者其他的解析工具,将package里的 文本解析出来,不懂得可以查看我的一篇关于demo4j的博客,很简单的一个
*
* @return
*/
public String getTypeFromXML() {
SAXReader reader = new SAXReader();
Document document = null;
try {
document = reader
.read(new File(
"E:\\Workspaces\\MyEclipse 10\\Test\\src\\com\\mq\\class1\\config.xml"));
} catch (DocumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Element root = document.getRootElement();
String mypackage = "";
// 查找name为mysql的包路径,用到XPath知识
List<Element> elements = root.selectNodes("basic[name='sqlserver']");//在此更改要使用的数据库名字,xml文件会自动的找到路径,不存在重新编译的问题
for (Element element : elements) {
mypackage = element.elementText("package");
}
return mypackage;
}
}