1 概述
抽象工厂模式(Abstract Factory),提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
-
AbstractProductA
和AbstractProductB
是两个抽象产品,而ProductA1
、ProductA2
和ProductB1
、ProductB2
就是对两个抽象产品的具体分类的实现。 -
AbstractFactory
是一个抽象工厂接口,它里面应该包含所有的产品创建的抽象方法。而ConcreteFactory1
和ConcreteFactory2
就是具体的工厂。 -
通常是在运行时刻再创建一个
ConcreteFactory
类的实例,这个具体的工厂再创建具有特定实现的产品对象,也就是说,为创建不同的产品对象,客户端应使用不同的具体工厂。
2 示例
User类,表示User表。
public class User {
}
IUser接口,用于客户端访问,解除与具体数据库访问的耦合。
public interface IUser {
void insert(User user);
User getUser(int id);
}
SqlserverUser类,用于访问SQL Server的User。
public class SqlServerUser implements IUser {
@Override
public void insert(User user) {
System.out.println("在SqlServer中给User表增加一条记录");
}
@Override
public User getUser(int id) {
System.out.println("在SqlServer中根据id得到User表一条记录");
return null;
}
}
AccessUser类,用于访问Access的User。
public class AccessUser implements IUser {
@Override
public void insert(User user) {
System.out.println("在Access中给User表增加一条记录");
}
@Override
public User getUser(int id) {
System.out.println("在Access中根据id得到User表一条记录");
return null;
}
}
Department类,表示Department表。
public class Department {
}
IDepartment接口,用于客户端访问,解除与具体数据库访问的耦合。
public interface IDepartment {
void insert(Department department);
Department getDepartment(int id);
}
SqlserverDepartment类,用于访问SQL Server的Department。
public class SqlServerDepartment implements IDepartment {
@Override
public void insert(Department department) {
System.out.println("在SqlServer中给Department表增加一条记录");
}
@Override
public Department getDepartment(int id) {
System.out.println("在SqlServer中根据id得到Department表一条记录");
return null;
}
}
AccessDepartment类,用于访问Access的Department。
public class AccessDepartment implements IDepartment {
@Override
public void insert(Department department) {
System.out.println("在Access中给Department表增加一条记录");
}
@Override
public Department getDepartment(int id) {
System.out.println("在Access中根据id得到Department表一条记录");
return null;
}
}
IFactory接口,定义一个创建访问User表和Department表对象的抽象的工厂接口。
public interface IFactory {
IUser createUser();
IDepartment createDepartment();
}
SqlServerFactory类,实现IFactory接口,实例化SqlserverUser和 SqlserverDepartment。
public class SqlServerFactory implements IFactory {
@Override
public IUser createUser() {
return new SqlServerUser();
}
@Override
public IDepartment createDepartment() {
return new SqlServerDepartment();
}
}
AccessFactory类,实现IFactory接口,实例化AccessUser和AccessDepartment。
public class AccessFactory implements IFactory {
@Override
public IUser createUser() {
return new AccessUser();
}
@Override
public IDepartment createDepartment() {
return new AccessDepartment();
}
}
客户端代码。
public class Client {
public static void main(String[] args) {
User user = new User();
Department department = new Department();
// 只需确定实例化哪一个数据库访问对象给 factory
IFactory factory = new SqlServerFactory();
// 则此时已与具体的数据库访问解除了依赖
IUser iu = factory.createUser();
iu.insert(user);
iu.getUser(1);
factory = new AccessFactory();
IDepartment id = factory.createDepartment();
id.insert(department);
id.getDepartment(1);
}
}
输出入下。
在SqlServer中给User表增加一条记录
在SqlServer中根据id得到User表一条记录
在Access中给Department表增加一条记录
在Access中根据id得到Department表一条记录
Process finished with exit code 0
3 优缺点
优点:
-
易于交换产品系列,由于具体工厂类在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不同的产品配置。
-
让具体的创建实例过程与客户端分离,客户端是通过它们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户代码中。
缺点
- 增加一个抽象产品时,要增加多个具体产品实现,而且抽象工厂和各具体工厂都要更改。
例如,要增加项目表Project,那就至少要增加三个类,IProject、SqIserverProject、AccessProject,还需要更改IFactory、SqlserverFactory和 AccessFactory 才可以完全实现。
- 每次定义工厂时,都要指定具体的实例化工厂。
例如:lFactory factory =new SqlserverFactoryO;
4 改进
用简单工厂改进,DataAccessc用反射技术,取代IFactory、SqlserverFactory和AccessFactory。
这里感觉保留IFactory,用DataAccess实现IFactory接口也挺好的。
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Properties;
public class DataAccess {
private String db;
public DataAccess() {
try {
// 读取配置文件
InputStream inputStream = DataAccess.class.getClassLoader().getResourceAsStream("dbConfig.properties");
// 设置编码
InputStreamReader isr = new InputStreamReader(inputStream, "UTF-8");
Properties properties = new Properties();
properties.load(isr);
db = properties.getProperty("db");
} catch (IOException e) {
e.printStackTrace();
}
}
public IUser creatUser() {
IUser iu = null;
try {
// 利用反射创建对象
Class cl = Class.forName(db + "User");
iu = (IUser) cl.newInstance();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
return iu;
}
public IDepartment creatDepartment() {
IDepartment id = null;
try {
Class cl = Class.forName(db + "Department");
id = (IDepartment) cl.newInstance();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
return id;
}
}
配置文件dbConfig.properties
。
db = 抽象工厂模式.SqlServer
输出入下。
在SqlServer中根据id得到User表一条记录
在SqlServer中给User表增加一条记录
在SqlServer中根据id得到Department表一条记录
在SqlServer中给Department表增加一条记录
Process finished with exit code 0
参考书籍:
《大话设计模式》