1、定义
(Abstract Factory)提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
2、使用场景
一个项目,早期使用的数据是Sql Server,但是现在需要切换数据Access,甚至到了后期可能需要换成Oracle,相应的对应的查询插入删除等方法需要做出调整。需要找出最佳解决办法适应各种数据库,且改动较小,易于扩展,耦合性底。
3、代码结构UML图
4、类的实现
(1)、User、Department(实体类)
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;
}
}
public class Department {
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
(2)IUser、IDepart(接口用于客户端访问,解除与具体数据库访问的耦合)
public interface IUser {
void insert(User user);
User getUser(int id);
}
public interface IDepartment {
void insert(Department department);
Department getDepartment(int id);
}
(3)、IFactory(抽象工厂类)
public interface IFactory {
IUser createUser();
IDepartment createDepartment();
}
(4)、SqlServerFactory 、AccessFactory (具体工厂类)
public class SqlServerFactory implements IFactory {
@Override
public IUser createUser() {
return new SqlServerUser();
}
@Override
public IDepartment createDepartment() {
return new SqlServerDepartment();
}
}
public class AccessFactory implements IFactory {
@Override
public IUser createUser() {
return new AccessUser();
}
@Override
public IDepartment createDepartment() {
return new AccessDepartment();
}
}
(5)SqlServerUser、SqlServerDepartment、AccessUser AccessDepartment(用于访问数据库的User、Department)
public class SqlServerUser implements IUser {
@Override
public void insert(User user) {
System.out.println("在Sql Server 中给User表增加一条记录。");
}
@Override
public User getUser(int id) {
System.out.println("在Sql Server 中根据ID得到User表一条记录");
return null;
}
}
public class SqlServerDepartment implements IDepartment {
@Override
public void insert(Department department) {
System.out.println("在Sql Server 中给Department表增加一条记录。");
}
@Override
public Department getDepartment(int id) {
System.out.println("在Sql Server中根据ID得到Department表一条记录。");
return null;
}
}
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;
}
}
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;
}
}
(6)注意:简单工厂模式:需要简化抽象工厂,演变后:
public class DataAccess {
private static String assemblyName = "factory.abstractFactory";//包名
private static String db = "SqlServer";//数据库名称,可以替换成Access
public static IUser createUser() {
//根据包名和类名来创建实例,消除switch case 语句
String className = assemblyName + "." + db + "User";
try {
return (IUser) Class.forName(className).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
public static IDepartment createDepartment() {
//根据类名来创建实例,消除switch case 语句
String className = assemblyName + "." + db + "Department";
try {
return (IDepartment) Class.forName(className).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
}
5、客户端调用
(1)、抽象工厂模式调用
public static void main(String[] args) {
User user = new User();
Department department = new Department();
IUser iu = DataAccess.createUser();
iu.insert(user);
iu.getUser(1);
IDepartment id = DataAccess.createDepartment();
id.insert(department);
id.getDepartment(1);
}
(2)、简单工厂模式调用
public static void main(String[] args) {
User user = new User();
Department department = new Department();
//IFactory factory=new SqlServerFactory();
IFactory factory = new AccessFactory();
IUser iu = factory.createUser();
iu.insert(user);
iu.getUser(1);
IDepartment id = factory.createDepartment();
id.insert(department);
id.getDepartment(1);
}
输出:
6、总结
此模式相对来讲比较抽象一点,而且演化过程也非常有意思,大家可以参看书里面案例和演化过程。
抽象工厂模式:更多的是将工厂进行了抽象,对应的访问对象也进行了再次抽象,灵活性和扩展性是比较高的,比如例子中添加oracle数据库,只需要在创建一个OracleFactory类,然后创建对应的OracleUser、OracleDepartment三个类即可,对原来的SqlServer、Access数据库访问不会造成任何影响,耦合性低,易于扩展,但是缺点也是很明确的,就是类会变得比较多。当类变得比较多的时候可以考虑简单工厂模式,无需OracleFactory 这个类,只需要OracleUser、OracleDepartment这个两个类,改动DateAccess对应的包和类访问路径即可。
参考:《大话设计模式》