20230423 15. 抽象工厂模式 - 数据库
介绍
工厂方法模式是定义一个用于创建对象的接口,让子类决定实例化哪一个类。
抽象工厂模式(Abstract Factory),提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。
- AbstractProductA和AbstractProductB是两个抽象产品,之所以为抽象,是因为它们都有可能有两种不同的实现
- ProductA1、ProductA2和ProductB1、ProductB2就是对两个抽象产品的具体分类的实现
- IFactory是一个抽象工厂接口,它里面应该包含所有的产品创建的抽象方法
- ConcreteFactory1和ConcreteFactory2就是具体的工厂了
通常是在运行时刻再创建一个ConcreteFactory类的实例,这个具体的工厂再创建具有特定实现的产品对象,也就是说,为创建不同的产品对象,客户端应使用不同的具体工厂
抽象工厂模式的好处
- 便是易于交换产品系列,由于具体工厂类在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不同的产品配置
- 它让具体的创建实例过程与客户端分离,客户端是通过它们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户代码中
缺点:增加一个新产品Project,至少要增加三个类,IProject、SqlserverProject、AccessProject,还需要更改IFactory、SqlserverFactory和AccessFactory才可以完全实现
所有在用简单工厂的地方,都可以考虑用反射技术来去除switch或if,解除分支判断带来的耦合。
抽象工厂模式和工厂方法模式的不同点:
- 继承方式不同:工厂方法模式中的工厂类必须继承同一个抽象类或接口,而抽象工厂类可以继承多个抽象类或接口。
- 创建对象的方式不同:工厂方法模式中的工厂类只能创建一种产品,而抽象工厂类可以创建多种不同的产品。
- 设计思路不同:工厂方法模式强调工厂的通用性,以及与产品之间的关系,而抽象工厂类则强调抽象产品的概念。
- 适用场景不同:工厂方法模式适用于创建同类型的产品族,而抽象工厂类适用于创建任意类型的产品族。
代码示例
AbstractProduct 抽象产品
public interface IUser {
void insert();
void get();
}
public interface IDepartment {
void insert();
void get();
}
产品实现
public class AccessDepartment implements IDepartment {
@Override
public void insert() {
System.out.println("access 插入一条 department 信息");
}
@Override
public void get() {
System.out.println("access 获得一条 department 信息");
}
}
public class AccessUser implements IUser {
@Override
public void insert() {
System.out.println("access 插入一条 user 信息");
}
@Override
public void get() {
System.out.println("access 获得一条 user 信息");
}
}
public class SqlServerDepartment implements IDepartment {
@Override
public void insert() {
System.out.println("sql server 插入一条 department 信息");
}
@Override
public void get() {
System.out.println("sql server 获得一条 department 信息");
}
}
public class SqlServerUser implements IUser {
@Override
public void insert() {
System.out.println("sql server 插入一条 user 信息");
}
@Override
public void get() {
System.out.println("sql server 获得一条 user 信息");
}
}
用反射+配置文件实现的工厂
public class DataAccess {
private static String db = null;
public static IUser createUser() {
String db = getDb();
String className = "study.hwj.p15." + db + "User";
return (IUser) getInstance(className);
}
public static IUser createDepartment() {
String db = getDb();
String className = "study.hwj.p15." + db + "Department";
return (IUser) getInstance(className);
}
private static Object getInstance(String className) {
try {
return Class.forName(className).getDeclaredConstructor().newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static String getDb() {
if (db == null) {
Properties properties = new Properties();
try {
properties.load(new FileReader("D:\\Develop\\workspace\\study\\study-design-pattern\\src\\main\\java"
+ "\\study\\hwj\\p15\\db.properties"));
} catch (IOException e) {
e.printStackTrace();
}
db = properties.getProperty("db");
}
return db;
}
}
db.properties
# 这里的值要和类名的前缀相同
db=SqlServer
客户端类
public class Test {
public static void main(String[] args) {
IUser user = DataAccess.createUser();
user.insert();
user.get();
}
}