首页 > 代码库 > 设计模式3---抽象工厂模式
设计模式3---抽象工厂模式
public interface IFactory { IUser CreateUser(); IDepartment CreateDepartment();}
在工厂模式中,每个工厂类会为特定的操作类型产生操作对象类。
但是如果有产品系列的话,工厂模式就不太适用。
考虑一个数据库的问题。
1.数据库可能有替换
2.每个数据库可以修改多个表,比如user,department。
抽象工厂类就是对于工厂类产生的对象,我其实不需要得到具体的类,只要抽象类(接口)就可以了。
main方法:
public class AbstractFactoryMain extends BasicExample { @Override public void startDemo() { // TODO Auto-generated method stub User user = new User(); Department department = new Department(); IFactory factory = new AccessFactory(); IUser iu = factory.CreateUser(); iu.insertUser(user); iu.getUser(1); IDepartment id = factory.CreateDepartment(); id.insertDepartment(department); id.getDepartment(1); }}
IFactory 是工厂方法接口
IUser 和IDepartment 是对于User和Department的操作接口,具体是access还是SQLserver其实客户端不关心。
其他类具体实现:
public interface IFactory { IUser CreateUser(); IDepartment CreateDepartment();}
//封装对User表的操作public interface IUser { void insertUser(User user); User getUser(int id);}
//封装对Department表的操作public interface IDepartment { void insertDepartment(Department department); Department getDepartment(int id);}
SQLserver工厂类:
public class SqlServerFactory implements IFactory { @Override public IUser CreateUser() { // TODO Auto-generated method stub return new SqlserverUser(); } @Override public IDepartment CreateDepartment() { // TODO Auto-generated method stub return new SqlserverDepartment(); }}
Access工厂类:
public class AccessFactory implements IFactory { @Override public IUser CreateUser() { // TODO Auto-generated method stub return new AccessUser(); } @Override public IDepartment CreateDepartment() { // TODO Auto-generated method stub return new AccessDepartment(); }}
具体操作类:
public class SqlserverUser implements IUser { @Override public void insertUser(User user) { System.out.println("在SQLserver 中给user表添加一条记录"); } @Override public User getUser(int id) { System.out.println("在SQLserver 中根据ID得到user表一条记录"); return null; }}
public class SqlserverDepartment implements IDepartment { @Override public void insertDepartment(Department department) { System.out.println("在SQLserver 中给Department表添加一条记录"); } @Override public Department getDepartment(int id) { System.out.println("在SQLserver 中根据ID得到Department表一条记录"); return null; }}
public class AccessDepartment implements IDepartment { @Override public void insertDepartment(Department department) { // TODO Auto-generated method stub System.out.println("在Access 中给Department表添加一条记录"); } @Override public Department getDepartment(int id) { System.out.println("在Access 中根据ID得到Department表一条记录"); return null; }}
public class AccessUser implements IUser { @Override public void insertUser(User user) { System.out.println("在Access 中给user表添加一条记录"); } @Override public User getUser(int id) { System.out.println("在Access 中根据ID得到user表一条记录"); return null; }}
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 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; }}
如果需要添加Oracle 数据库,那只要添加 工厂生成类OracleFactory,以及操作OracleUser 和OracleDepartment类。
这样就不会改动原有代码,可以快速替换数据库。
抽象工厂模型:
优点: 1.可以方便的交换产品系列,只需在初始化的地方出现一次,就可以应用一个具体工厂。
2.具体实现隔离客户端,客户端通过抽象接口来操作具体实例。
简单工厂模型优化抽象工厂模型。
把AccessFactory 和SqlserverFactory可以合并成DataAccess方法来处理。
问题:如果上述“ IFactory factory = new AccessFactory();” 有还多处地方,甚至好几百处,这样就需要做大量的修改。
把AccessFactory用DataAccess来代替,客户端彻底杜绝出现数据库字段。
public class DataAccess {// private static final String db = "Sqlserver"; private static final String db = "Access"; public static IUser CreateUser() { IUser result = null; switch(db) { case "Sqlserver": result = new SqlserverUser(); break; case "Access": result = new AccessUser(); break; } return result; } public static IDepartment CreateDepartment() { IDepartment result = null; switch(db) { case "Sqlserver": result = new SqlserverDepartment(); break; case "Access": result = new AccessDepartment(); break; } return result; }}
main方法修改为:
public class AbstractFactoryMain extends BasicExample { @Override public void startDemo() { // TODO Auto-generated method stub User user = new User(); Department department = new Department();// IFactory factory = new AccessFactory(); IUser iu = DataAccess.CreateUser(); iu.insertUser(user); iu.getUser(1); IDepartment id = DataAccess.CreateDepartment(); id.insertDepartment(department); id.getDepartment(1); }}
从main方法看,根本看不到任何SQL和Access的字段,也就是客户端与业务逻辑隔离了!
但是,如果新增一个Oracle数据库,需要修改DataAccess的switch--case,如何彻底不用switch语句呢?
利用反射,把类对象反射出来,这样只需要添加工厂类定义就可以了。
package com.jayfulmath.designpattern.abstractfactory;import java.lang.reflect.*;public class DataAccessReflection { private static final String AssemblyName = "com.jayfulmath.designpattern.abstractfactory"; private static final String db = "Access"; public static IUser CreateUser() { String className =AssemblyName+"."+db+"User"; IUser result = null; try { Class<?> c = Class.forName(className); Constructor<?> ct = c.getConstructor(); result = (IUser) (ct.newInstance()); } catch (NoSuchMethodException |ClassNotFoundException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } return result; } public static IDepartment CreateDepartment() { String className = AssemblyName+"."+db+"Department"; IDepartment result = null; try { Class<?> c = Class.forName(className); Constructor<?> ct = c.getConstructor(); result = (IDepartment) (ct.newInstance()); } catch (NoSuchMethodException |ClassNotFoundException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } return result; }}
自此,完美的解决了switch---case的问题。如果使用配置文件的话,可以彻底不用修改代码,而达到更换数据库的问题。
设计模式3---抽象工厂模式
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。