抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。
抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式。抽象工厂模式可以向客户端提
供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象。
与工厂方法模式的区别:
抽象工厂模式:
1.多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。
2.一个抽象工厂类,可以派生出多个具体的工厂类。
3.每个具体工厂类可以创建多个具体产品类的实例。
工厂方法模式:
1.一个抽象产品类,可以派生出多个具体产品类。
2.一个抽象工厂类,可以派生出多个具体工厂类。
3.每个具体工厂类只能创建一个具体产品类的实例。
抽象工厂就像工厂,而工厂方法则像是工厂的一种产品生产线
抽象工厂模式实例:
/**
* 用户类
*/
public class User {
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/**
* 用户接口
*/
public interface IUser {
public void insertUser(User user);
public User getUser(String id);
}
/**
* 用于访问Access的User。
*/
public class UserAccess implements IUser {
public User getUser(String id) {
System.out.println("在Access中根据ID得到User表一条记录。");
return null;
}
public void insertUser(User user) {
System.out.println("在Access中给User表添加一条记录。");
}
}
/**
* 用于访问SqlServer的User。
*/
public class UserSqlServer implements IUser {
public User getUser(String id) {
System.out.println("在SqlServer中根据ID得到User表一条记录。");
return null;
}
public void insertUser(User user) {
System.out.println("在SqlServer中给User表添加一条记录。");
}
}
/**
* 部门类
*/
public class Department {
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/**
* 部门接口
*/
public interface IDepartment {
public void insertDepartment(Department department);
public Department getDepartment(String id);
}
/**
* 用于访问Access的Department。
*/
public class DepartmentAccess implements IDepartment {
public Department getDepartment(String id) {
System.out.println("在Access中根据ID得到Department表一条记录。");
return null;
}
public void insertDepartment(Department department) {
System.out.println("在Access中给Department表添加一条记录。");
}
}
/**
* 用于访问SqlServer的Department。
*/
public class DepartmentSqlServer implements IDepartment {
public Department getDepartment(String id) {
System.out.println("在SqlServer中根据ID得到Department表一条记录。");
return null;
}
public void insertDepartment(Department department) {
System.out.println("在SqlServer中给Department表添加一条记录。");
}
}
/**
* 定义一个创建访问User表和部门表对象的抽象的工厂接口
*/
public interface IFactory {
// 创建用户
public IUser createUser();
// 创建部门
public IDepartment createDepartment();
}
/**
* 实现IFactory接口,实例化AccessUser和AccessDepartment。
*/
public class FactoryAccess implements IFactory{
public IDepartment createDepartment() {
return new DepartmentAccess();
}
public IUser createUser() {
return new UserAccess();
}
}
/**
* 实现IFactory接口,实例化SqlServerUser和SqlServerDepartment。
*/
public class FactorySqlServer implements IFactory{
public IDepartment createDepartment() {
return new DepartmentSqlServer();
}
public IUser createUser() {
return new UserSqlServer();
}
}
public class Main {
public static void main(String[] args) {
// 用户
User user = new User();
// 部门
Department department = new Department();
// 访问SqlServer数据库(访问Access只要改为new FactoryAccess()).
IFactory factory = new FactorySqlServer();
// 操作用户表
IUser iu = factory.createUser();
iu.insertUser(user);
iu.getUser("1");
// 操作部门表
IDepartment id = factory.createDepartment();
id.insertDepartment(department);
id.getDepartment("1");
}
}
用简单工厂改进抽象工厂:抛弃了IFactory,FactorySqlServer,FactoryAccess三个工厂类.
不足之处:如果需要增加Oracle数据库,应需要在每个方法的switch中添加case处理。
/**
* 数据库枚举类
*/
public enum DataBaseEnum {
SqlServer,Access;
}
public class DataAccess {
// 数据库名称(可替换成Access)
private static final DataBaseEnum dataBase = DataBaseEnum.SqlServer;
// 根据不同的数据库操作用户表
public static IUser createUser(){
IUser iUser = null;
// 由于DB的事先设置,此处可根据选择实例化出相应的对象
switch(dataBase){
case SqlServer:
iUser = new UserSqlServer();
break;
case Access:
iUser = new UserAccess();
break;
}
return iUser;
}
// 根据不同的数据库操作部门表
public static IDepartment createDepartment(){
IDepartment iDepartment = null;
// 由于DB的事先设置,此处可根据选择实例化出相应的对象
switch(dataBase){
case SqlServer:
iDepartment = new DepartmentSqlServer();
break;
case Access:
iDepartment = new DepartmentAccess();
break;
}
return iDepartment;
}
}
简单工厂类的改进:采用反射机制解决简单工厂中switch分支添加case处理的修改变动。
也可采用配置文件和反射技术进行改进。
public class DataAccessReflect {
// 此处可改为AccessUser(访问Access数据库)或OracleUser(访问oracle数据库)
private static final String userClassName = "com.design." +
"factory.abstractFactory.UserSqlServer";
private static final String departClassName = "com.design." +
"factory.abstractFactory.DepartmentSqlServer";
// 根据不同的数据库操作用户表
public static IUser createUser(){
IUser iUser = null;
try {
// 利用反射实例化指定的对象
iUser = (IUser)Class.forName(userClassName).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return iUser;
}
// 根据不同的数据库操作部门表
public static IDepartment createDepartment(){
IDepartment iDepartment = null;
try {
// 利用反射实例化指定的对象
iDepartment = (IDepartment)Class
.forName(departClassName).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return iDepartment;
}
}
public class Main {
public static void main(String[] args) {
// 用户
User user = new User();
// 部门
Department department = new Department();
// 操作用户表(直接得到实际的数据库访问实例,而不存在任何依赖)
IUser iu = DataAccess.createUser();
iu.insertUser(user);
iu.getUser("1");
// 操作部门表(直接得到实际的数据库访问实例,而不存在任何依赖)
IDepartment id = DataAccess.createDepartment();
id.insertDepartment(department);
id.getDepartment("1");
//**************改进后的反射机制调用*********************
IUser iuReflect = DataAccessReflect.createUser();
iuReflect.insertUser(user);
iuReflect.getUser("1");
// 操作部门表(直接得到实际的数据库访问实例,而不存在任何依赖)
IDepartment idReflect = DataAccessReflect.createDepartment();
idReflect.insertDepartment(department);
idReflect.getDepartment("1");
}
}