简单工厂模式
工厂方法模式
抽象工厂模式
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类
原始模型
public interface IUser {
void insert(User user);
User getUser(int id);
}
在MySQL的user表操作
public class MySQLUser implements IUser {
@Override
public void insert(User user) {
System.out.println("在MySQL中给User表插入了一条数据:" + user.toString());
}
@Override
public User getUser(int id) {
System.out.println("在MySQL中从User表获取到一条数据");
return null;
}
}
在Oracle的user表操作
public class OracleUser implements IUser {
@Override
public void insert(User user) {
System.out.println("在Oracle中给User表插入了一条数据:" + user.toString());
}
@Override
public User getUser(int id) {
System.out.println("在Oracle中从User表获取到一条数据");
return null;
}
}
抽象工厂
public interface IFactory {
IUser createUser();
IDepartment createDepartment();
}
具体的MySQL工厂
public class MySQLFactory implements IFactory {
@Override
public IUser createUser() {
return new MySQLUser();
}
@Override
public IDepartment createDepartment() {
return new MySQLDepartment();
}
}
具体的Oracle工厂
public class OracleFactory implements IFactory {
@Override
public IUser createUser() {
return new OracleUser();
}
@Override
public IDepartment createDepartment() {
return new OracleDepartment();
}
}
客户端
public class Client {
public static void main(String[] args) {
User user = new User(1, "小明");
Department department = new Department(1, "人才公寓");
// 在这里切换数据库 如MySQL则创建MySQLFactory
IFactory mySQLFactory = new MySQLFactory();
IUser iu1 = mySQLFactory.createUser();
iu1.insert(user);
iu1.getUser(1);
IDepartment id1 = mySQLFactory.createDepartment();
id1.insert(department);
id1.getDepartment(1);
// 使用Oracle数据库
IFactory oracleFactory = new OracleFactory();
IUser iu2 = oracleFactory.createUser();
iu2.insert(user);
iu2.getUser(1);
IDepartment id2 = oracleFactory.createDepartment();
id2.insert(department);
id2.getDepartment(1);
}
}
用简单工厂来改进抽象工厂
public class DataAccess {
// 这里可以切换数据库 不用在客户单中切换 解耦
//private static final String db = "MySQL";
private static final String db = "Oracle";
public static IUser createUser() {
IUser result = null;
switch(db) {
case "MySQL":
result = new MySQLUser();
case "Oracle":
result = new OracleUser();
}
return result;
}
public static IDepartment createDepartment() {
IDepartment result = null;
switch(db) {
case "MySQL":
result = new MySQLDepartment();
case "Oracle":
result = new OracleDepartment();
}
return result;
}
}
public class Client2 {
public static void main(String[] args) {
User user = new User(1, "小明");
Department department = new Department(1, "人才公寓");
// 用户不需要选择数据库,直接得到实际的数据库访问实例,不存在任何依赖
IUser iu = DataAccess.createUser();
iu.insert(user);
iu.getUser(1);
IDepartment id = DataAccess.createDepartment();
id.insert(department);
id.getDepartment(1);
}
}
优点:客户端看不到切换数据库的操作
确定:有case判断 如果要增加数据库类型 还需要在case加条件 修改了代码 违背了开闭原则
使用反射机制来改进
public class DataAccess_Reflection {
// 包名
private static final String packageName = "abstractFactoryModel";
// 使用哪个数据库 把数据库信息写死在程序类中
private static final String db = "Oracle";
public static IUser createUser() throws Exception {
// 拼接成完整的类路径
String className = packageName + "." + db + "User";
// 通过反射来动态的创建出实例 去除case
return (IUser) Class.forName(className).getDeclaredConstructor().newInstance();
}
public static IDepartment createDepartment() throws Exception{
String className = packageName + "." + db + "Department";
return (IDepartment) Class.forName(className).getDeclaredConstructor().newInstance();
}
}
public class Client3 {
public static void main(String[] args) throws Exception {
User user = new User(1, "小明");
Department department = new Department(1, "人才公寓");
// 用户不需要选择数据库,直接得到实际的数据库访问实例,不存在任何依赖
IUser iu = DataAccess_Reflection.createUser();
iu.insert(user);
iu.getUser(1);
IDepartment id = DataAccess_Reflection.createDepartment();
id.insert(department);
id.getDepartment(1);
}
}
优点:去除之前的case 接触分支判断带来的耦合 不需要修改代码
确定:如果要更改数据库类型 db 字段还是需要修改
读取外部XML文件来解耦
datasoure.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appSettings>
<datasource key="DB" value="MySQL">MySQL</datasource>
</appSettings>
</configuration>
public class DataAccess_Reflection_XML{
// 包名
private static final String packageName = "abstractFactoryModel";
public static IUser createUser() throws Exception {
// 拼接成完整的类路径
String className = packageName + "." + getDB() + "User";
// 通过反射来动态的创建出实例 去除case
return (IUser) Class.forName(className).getDeclaredConstructor().newInstance();
}
public static IDepartment createDepartment() throws Exception{
String className = packageName + "." + getDB() + "Department";
return (IDepartment) Class.forName(className).getDeclaredConstructor().newInstance();
}
private static String getDB() throws Exception {
String filePath = "src/abstractFactoryModel/datasoure.xml";
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.parse(filePath);
Element root = document.getDocumentElement();
Node appSettings = root.getFirstChild();
Node datasource = appSettings.getFirstChild();
String db = datasource.getTextContent();
return db;
}
}
public class Client4 {
public static void main(String[] args) throws Exception {
User user = new User(1, "小明");
Department department = new Department(1, "人才公寓");
// 用户不需要选择数据库,直接得到实际的数据库访问实例,不存在任何依赖
IUser iu = DataAccess_Reflection_XML.createUser();
iu.insert(user);
iu.getUser(1);
IDepartment id = DataAccess_Reflection_XML.createDepartment();
id.insert(department);
id.getDepartment(1);
}
}
优点:如果要切换数据库类型 只需要修改外部XML文件即可