一、最基本的数据访问程序
用“新增用户”和“得到用户”为例;假设只有ID和Name两个字段。
class User{
private int id;
public int ID;
public int getId() {
return id;
}
public void setId(int id) {
this.id=id;
}
private String name;
public String Name;
public String getName() {
return name;
}
public void setName(String name) {
this.name=name;
}
}
/*SqlserverUser类——用于操作User表,假设只有“新增用户”和“得到用户”方法,其余方法以及具体的SQL语句省略*/
class SqlserverUser{
public void Insert(User user) {
System.out.println("在Sqlserver中给User表增加一条记录");
}
public User GetUser(int id)
{
System.out.println("在Sqlserver中根据ID得到User表一条记录");
return null;
}
}
/*客户端代码*/
public class Main{
public static void main(String[] args) {
User user=new User();
SqlserverUser su=new SqlserverUser();
su.Insert(user);
su.GetUser(1);
}
}
这里之所以不能换数据库,原因就在于SqlserverUser su=new SqlserverUser()使得su这个对象被框死在SQL Server上了。如果这里是多态的那么在执行‘su.Inesrt(user);’和‘su.GetUser(1);'时就不用考虑是用在SQL Server上还是用在Access。
用“工厂方法模式来封装new SqlserverUser()”所造成的变化。
工厂方法模式就是定义一个用于创建对象的接口让子类决定实例化哪一个类。
二、用工厂方法模式的数据访问程序
package operation;
class User{
private int id;
public int ID;
public int getId() {
return id;
}
public void setId(int id) {
this.id=id;
}
private String name;
public String Name;
public String getName() {
return name;
}
public void setName(String name) {
this.name=name;
}
}
/*class SqlserverUser{
public void Insert(User user) {
System.out.println("在Sqlserver中给User表增加一条记录");
}
public User GetUser(int id)
{
System.out.println("在Sqlserver中根据ID得到User表一条记录");
return null;
}
}
public class Main{
public static void main(String[] args) {
User user=new User();
SqlserverUser su=new SqlserverUser();
su.Insert(user);
su.GetUser(1);
}
}
*/
/*IUser接口,用于客户端访问,解除与具体数据库访问的耦合*/
interface IUser{
void Insert(User user);
User GetUser(int id);
}
/*SqlserverUser类,用于访问SQl Server的User*/
class SqlserverUser implements IUser{
public void Insert(User user) {
System.out.println("在Sqlserver中给User表增加一条记录");
}
public User GetUser(int id)
{
System.out.println("在Sqlserver中根据ID得到User表一条记录");
return null;
}}
/*AccessUser类,用于访问Access的User*/
class AccessUser implements IUser{
public void Insert(User user) {
System.out.println("在Sqlserver中给User表增加一条记录");
}
public User GetUser(int id)
{
System.out.println("在Sqlserver中根据ID得到User表一条记录");
return null;
}
}
/*IFactory接口,定义一个创建访问User表对象的抽象的工厂接口*/
interface IFactory{
IUser CreateUser();
}
/*SqlServerFactory类,实现IFactory接口,实例化SqlserverUser*/
class SqlServerFactory implements IFactory{
public IUser CreateUser() {
return new SqlserverUser();
}
}
/*AccessFactory类,实现IFactory接口,实例化AccessUser*/
class AccessFactory implements IFactory{
public IUser CreateUser() {
return new AccessUser();
}
}
public class Main{
public static void main(String[] args) {
User user=new User();
SqlserverUser iu=new SqlserverUser();
iu.Insert(user);
iu.GetUser(1);
}
}
三、用抽象工厂模式访问数据
package operation;
class User{
private int id;
public int ID;
public int getId() {
return id;
}
public void setId(int id) {
this.id=id;
}
private String name;
public String Name;
public String getName() {
return name;
}
public void setName(String name) {
this.name=name;
}
}
class Department{
private int id;
private String deptName;
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName=deptName;
}
}
interface IUser{
void Insert(User user);
User GetUser(int id);
}
/*SqlserverUser类,用于访问SQl Server的User*/
class SqlserverUser implements IUser{
public void Insert(User user) {
System.out.println("在Sqlserver中给User表增加一条记录");
}
public User GetUser(int id)
{
System.out.println("在Sqlserver中根据ID得到User表一条记录");
return null;
}}
/*AccessUser类,用于访问Access的User*/
class AccessUser implements IUser{
public void Insert(User user) {
System.out.println("在Sqlserver中给User表增加一条记录");
}
public User GetUser(int id)
{
System.out.println("在Sqlserver中根据ID得到User表一条记录");
return null;
}
}
/*IDepartment接口,用于客户端访问,解除与具体数据库访问的耦合*/
interface IDepartment{
void Insert(Department department);
Department GetDepartment(int id);
}
/*SqlserverDepartment类,用于访问SQl Server的Department*/
class SqlserverDepartment implements IDepartment{
public void Insert(Department department) {
System.out.println("在Sqlserver中给User表增加一条记录");
}
public Department GetDepartment(int id)
{
System.out.println("在Sqlserver中根据ID得到User表一条记录");
return null;
}
}
/*AccessDepartment类,用于访问Access的Department*/
class AccessDepartment implements IDepartment{
public void Insert(Department department) {
System.out.println("在Sqlserver中给User表增加一条记录");
}
public Department GetDepartment(int id)
{
System.out.println("在Sqlserver中根据ID得到User表一条记录");
return null;
}
}
/*IFactory接口,定义一个创建访问User表对象的抽象的工厂接口*/
interface IFactory{
IUser CreateUser();
IDepartment CreateDepartment();
}
/*SqlServerFactory类,实现IFactory接口,实例化SqlserverUser*/
class SqlServerFactory implements IFactory{
public IUser CreateUser() {
return new SqlserverUser();
}
public IDepartment CreateDepartment() {
return new SqlserverDepartment();
}
}
/*AccessFactory类,实现IFactory接口,实例化AccessUser*/
class AccessFactory implements IFactory{
public IUser CreateUser() {
return new AccessUser();
}
public IDepartment CreateDepartment() {
return new AccessDepartment();
}
}
public class Main{
public static void main(String[] args) {
User user=new User();
Department dept=new Department();
//IFactory factory= new SqlServerFactory();
IFactory factory= new AccessFactory();
IUser iu=factory.CreateUser();
iu.Insert(user);
iu.GetUser(1);
IDepartment id=factory.CreateDepartment();
id.Insert(dept);
id.GetDepartment(1);
}
}
四、用简单工厂来改进抽象工厂
去除IFactory,SqlsrverFactory和AccessFactory三个工厂,用DataAcess类代替,用一个简单工厂模式来实现。
package operation;
class User{
private int id;
public int ID;
public int getId() {
return id;
}
public void setId(int id) {
this.id=id;
}
private String name;
public String Name;
public String getName() {
return name;
}
public void setName(String name) {
this.name=name;
}
}
class Department{
private int id;
private String deptName;
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName=deptName;
}
}
interface IUser{
void Insert(User user);
User GetUser(int id);
}
/*SqlserverUser类,用于访问SQl Server的User*/
class SqlserverUser implements IUser{
public void Insert(User user) {
System.out.println("在Sqlserver中给User表增加一条记录");
}
public User GetUser(int id)
{
System.out.println("在Sqlserver中根据ID得到User表一条记录");
return null;
}}
/*AccessUser类,用于访问Access的User*/
class AccessUser implements IUser{
public void Insert(User user) {
System.out.println("在Sqlserver中给User表增加一条记录");
}
public User GetUser(int id)
{
System.out.println("在Sqlserver中根据ID得到User表一条记录");
return null;
}
}
/*IDepartment接口,用于客户端访问,解除与具体数据库访问的耦合*/
interface IDepartment{
void Insert(Department department);
Department GetDepartment(int id);
}
/*SqlserverDepartment类,用于访问SQl Server的Department*/
class SqlserverDepartment implements IDepartment{
public void Insert(Department department) {
System.out.println("在Sqlserver中给User表增加一条记录");
}
public Department GetDepartment(int id)
{
System.out.println("在Sqlserver中根据ID得到User表一条记录");
return null;
}
}
/*AccessDepartment类,用于访问Access的Department*/
class AccessDepartment implements IDepartment{
public void Insert(Department department) {
System.out.println("在Sqlserver中给User表增加一条记录");
}
public Department GetDepartment(int id)
{
System.out.println("在Sqlserver中根据ID得到User表一条记录");
return null;
}
}
class DataAccess{
private static String db="Sqlserver";
//private static String db="Access";
/*数据库名称,可替换*/
static IUser CreateUser() {
IUser result=null;
/*db事先设置,可根据选择实例化相应对象*/
switch(db)
{case"Sqlserver":
result=new SqlserverUser();
break;
case"Access":
result=new AccessUser();
break;
}
return result;}
public static IDepartment CreateDepartment() {
IDepartment result=null;
switch(db)
{case"Sqlserver":
result=new SqlserverDepartment();
break;
case"Access":
result=new AccessDepartment();
break;
}
return result;}}
public class Main{
public static void main(String[] args) {
User user=new User();
Department dept=new Department();
//IFactory factory= new SqlServerFactory();
/*直接得到实际的数据库访问实例,而不存在任何依赖*/
IUser iu=DataAccess.CreateUser();
iu.Insert(user);
iu.GetUser(1);
IDepartment id=DataAccess.CreateDepartment();
id.Insert(dept);
id.GetDepartment(1);
}
}
五、用反射+抽象工厂的数据访问程序
用反射可以利用字符串来实例化对象,而变量是可更换的。因此,变量的值是SQL server还是Access,完全由事先那个db变量决定,所以就去除了switch判断的麻烦。
DataAcess类,用反射技术代替IFactory,SqlsrverFactory和AccessFactory。
改写DataAcess类
class DataAccess {
private static final String AssemblyName = "抽象工厂模式";
private static final String db = "Sqlserver";
//private static final String db = "Access";
public static IUser CreateUser() throws ClassNotFoundException, InstantiationException, IllegalAccessException
{
String className = AssemblyName+"."+db+"User";
@SuppressWarnings("unchecked")
Class<IUser> forName = (Class<IUser>) Class.forName(className);
return forName.newInstance();
}
public static IDepartment CreateDepartment() throws ClassNotFoundException, InstantiationException, IllegalAccessException
{
String className = AssemblyName+"."+db+"Department";
@SuppressWarnings("unchecked")
Class<IDepartment> forName = (Class<IDepartment>) Class.forName(className);
return forName.newInstance();
}
}