本文共 6124 字,大约阅读时间需要 20 分钟。
抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。
抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式。抽象工厂模式可以向客户端提 供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象。 与工厂方法模式的区别: 抽象工厂模式: 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"); }}
转载地址:http://nyxmb.baihongyu.com/