用反射 配置文件的方法重新实现大话设计模式课本上15章15.7的例题
问题分析:相比抽象工厂,用DataAccess类代替了工厂接口以及工厂类,再加上使用反射 配置文件的方式,可以做到不对编译好的程序作出改变就能修改数据库种类,客户端可以只是用DateAccess进行数据库访问实例的创建,达到了解耦的目的。
UML图:
代码语言:javascript复制package com.cmc;
//用户数据类
public class User {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package com.cmc;
//部门数据类
public class Department {
int id;
String dept_name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDept_name() {
return dept_name;
}
public void setDept_name(String dept_name) {
this.dept_name = dept_name;
}
}
package com.cmc;
//用户数据库操作的接口
public interface IUser {
void insert(User user);
User getUser(int id);
}
package com.cmc;
//部门数据库操作接口
public interface IDepartment {
void insert(Department department);
Department getDepartment(int id);
}
package com.cmc;
//在SqlServer中实现对用户数据库的操作
public class SqlserverUser implements IUser {
public User getUser(int id) {
System.out.println("在SQL Server中根据ID得到一条记录");
return null;
}
public void insert(User u) {
// TODO Auto-generated method stub
System.out.println("在SQL Server 中给user表添加一条记录");
}
}
package com.cmc;
//在Access中实现对用户数据库的操作
public class AccessUser implements IUser {
public User getUser(int id) {
System.out.println("在Access中根据ID得到一条记录");
return null;
}
public void insert(User user) {
// TODO Auto-generated method stub
System.out.println("在Access中给user表添加一条记录");
}
}
package com.cmc;
public class SqlserverDepartment implements IDepartment {
public Department getDepartment(int id) {
System.out.println("在SQL Server中根据ID得到一条记录");
// TODO Auto-generated method stub
return null;
}
public void insert(Department department) {
// TODO Auto-generated method stub
System.out.println("在SQL Server 中给Department表添加一条记录");
}
}
package com.cmc;
public class AccessDepartment implements IDepartment {
public Department getDepartment(int id) {
System.out.println("在Access中根据ID得到一条记录");
// TODO Auto-generated method stub
return null;
}
public void insert(Department department) {
// TODO Auto-generated method stub
System.out.println("在Access中给Department表添加一条记录");
}
}
package com.cmc;
//通过配置文件 反射对要创建的类进行切换
import java.io.IOException;
import java.util.Properties;
import config.RunMain;
public class DataAccess {
public static IUser CreatUser(){
IUser result = null;
Properties prop = new Properties();
try {
prop.load(RunMain.class.getResourceAsStream("/com/cmc/datebase.properties"));
Class db = Class.forName("com.cmc." prop.getProperty("dbuser"));
result = (IUser)db.newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
public static IDepartment CreatDepartment(){
IDepartment result = null;
Properties properties = new Properties();
try {
properties.load(RunMain.class.getResourceAsStream("/com/cmc/datebase.properties"));
Class db = Class.forName("com.cmc." properties.getProperty("dbdepartment"));
result=(IDepartment)db.newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
}
优点: 1.实现了组件的封装,然后让组件外部能真正面向接口编程。 2.通过简单工厂,实现了客户端和具体实现类的解耦。 缺点:不方便扩展子工厂,如果要增加oracle数据库,必须在DateAccess类中增加oracle的方法,在工厂中增加创建case,这一点不符合开闭原则。显然使用反射 配置文件可以解决后者。