抽象工厂模式

简单工厂模式

工厂方法模式

抽象工厂模式

提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类

在这里插入图片描述

原始模型

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UUKxLgYs-1647078237644)(D:\Markdown图片\image-20220312094209022.png)]

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);
	}
}

用简单工厂来改进抽象工厂

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JQ8RJy4t-1647078237645)(D:\Markdown图片\image-20220312104418528.png)]

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文件即可

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王景清

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值