一、何为抽象工厂模式?
- 定义:提供一个创建一系列相关或者相互依赖对象的接口,而无需指定它们具体的类.
相信大伙们,看了上面的概念肯定是这样!!!
这尼玛是啥?(其实小编也是看了好多遍整个概念加上具体的例子才理解掉的)
- 案例:
我们举个例子来说明:现在有一个场景,就是需要访问两个数据库(Sqlserver和Access),当需要从其中一个数据库更换成另外一个的时候,如何更好 解除客户端和数据库访问的耦合,假设数据库中有一张User表.
我们首先想到的就是使用工厂方法模式设计这段访问的代码,先看工厂方法模式下的UML类图:
工厂方法模式下的具体的代码实现:
interface IUser{
void insert();
void update();
}
class SqlserverUser implements IUser{
@Override
public void insert() {
System.out.println("想Sqlserver数据库User表插入一条数据");
}
@Override
public void update() {
System.out.println("想Sqlserver数据库User表更新一条数据");
}
}
class AccessUser implements IUser{
@Override
public void insert() {
System.out.println("想Access数据库User表插入一条数据");
}
@Override
public void update() {
System.out.println("想Access数据库User表更新一条数据");
}
}
interface IFactory{
IUser createUser();
}
class SqlserverFactory implements IFactory{
@Override
public IUser createUser() {
return new SqlserverUser();
}
}
class AccessFactory implements IFactory{
@Override
public IUser createUser() {
return new AccessUser();
}
}
public class AbstractFactoryMain {
public static void main(String[] args) {
// IFactory iFactory = new SqlserverFactory(); //当需要修改数据库时只需要修改成相对应的factory即可以
IFactory iFactory = new AccessFactory();
IUser user = iFactory.createUser();
user.insert();
user.update();
}
}
工厂方法模式下运行的截图:
但是,如果此时我们再增加一张部门表呢?
此时的UML类图为:
具体的代码的实现:
interface IUser{
void insert();
void update();
}
interface IDepartment{
void insert();
void update();
}
class SqlserverUser implements IUser{
@Override
public void insert() {
System.out.println("想Sqlserver数据库User表插入一条数据");
}
@Override
public void update() {
System.out.println("想Sqlserver数据库User表更新一条数据");
}
}
class AccessUser implements IUser{
@Override
public void insert() {
System.out.println("想Access数据库User表插入一条数据");
}
@Override
public void update() {
System.out.println("想Access数据库User表更新一条数据");
}
}
class SqlserverDepartment implements IDepartment{
@Override
public void insert() {
System.out.println("想Sqlserver数据库Department表插入一条数据");
}
@Override
public void update() {
System.out.println("想Sqlserver数据库Department表更新一条数据");
}
}
class AccessDepartment implements IDepartment{
@Override
public void insert() {
System.out.println("想Access数据库Department表插入一条数据");
}
@Override
public void update() {
System.out.println("想Access数据库Department表更新一条数据");
}
}
interface IFactory{
IUser createUser();
IDepartment createDepartment();
}
class SqlserverFactory implements IFactory{
@Override
public IUser createUser() {
return new SqlserverUser();
}
@Override
public IDepartment createDepartment() {
return new SqlserverDepartment();
}
}
class AccessFactory implements IFactory{
@Override
public IUser createUser() {
return new AccessUser();
}
@Override
public IDepartment createDepartment() {
return new AccessDepartment();
}
}
public class AbstractFactoryMain {
public static void main(String[] args) {
IFactory iFactory = new SqlserverFactory();
IDepartment department = iFactory.createDepartment();
IUser user = iFactory.createUser();
}
}
是不是感觉跟工厂方法模式很相同呀!!此时我们再次回到定义中,提供一个创建一系列相关或者相互用来对象的接口指的就是上图的IFactory接口,而无需指定到他们具体的类,即SqlserverUser、AccessUser、SqlserverDepartmentAccessDepartment。
此时,疑惑有来了,这个不就是工厂方法模式吗??其实是这样的,只有一个User类和User操作类的时候,是只需要工厂方法模式的,但现在显然数据库中很多的表,而SQL Server 与Access又是两大不同的分类,所以解决这种涉及到多个产品系列的问题,有一个专门的工厂模式叫做 抽象工厂模式。
二、抽象工厂的优点
-
易于交换产品系列:
例如: IFactory factory = new AccessFactory() 在应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不同的产品配置。 -
具体的创建实例过程与客户端分离:客户端是通过它们的抽象接口操作实例,产品的具体类名也被具体工厂实现分离,不会出现在客户代码中。
三、对抽象工厂的思考
试想如果我们此时再增加一张IProject表呢?此时我们需要增加IProject、SqlserverProject、
AccessProject还需要更改IFactory、SqlserverFactory、AccessFactory这三个类,一共需要修改6个类。这样是不是值得我们去思考,对于这么大幅度的改动,该如何将进行优化呢?
- 使用简单工厂改进抽象工厂
UML类图:
- 具体的代码实现:
class DataAccess{
private static final String db = "Sqlserver"; //需要更改数据库的类型
// private static final String db = "Access";
public IUser createUser(){
IUser iUser = null;
switch (db){
case "Sqlserver":
iUser = new SqlserverUser();
break;
case "Access":
iUser = new AccessUser();
break;
}
return iUser;
}
public IDepartment createDepartment(){
IDepartment iDepartment = null;
switch (db){
case "Sqlserver":
iDepartment = new SqlserverDepartment();
break;
case "Access":
iDepartment = new AccessDepartment();
break;
}
return iDepartment;
}
}
public class SimpleFactory {
public static void main(String[] args) {
DataAccess dataAccess = new DataAccess();
IDepartment department = dataAccess.createDepartment();
IUser user = dataAccess.createUser(); //直接得到数据库访问实例没有任何依赖
}
}
但是如上的代码,请读者们进行再次的思考,是否违反了设计模式的开闭原则,如何进行优化呢?剩下的交给读者们自己进行思考,给读者们一个提示那就是反射。
四、总结
- 抽象工厂模式:提供一个创建一系列相关或者相互依赖对象的接口,而无需指定它们具体的类
- 抽象工厂模式是对工厂方法模式的一种扩展和补充。