Java设计模式之——抽象工厂模式

一、何为抽象工厂模式?

  • 定义:提供一个创建一系列相关或者相互依赖对象的接口,而无需指定它们具体的类.

相信大伙们,看了上面的概念肯定是这样!!!
在这里插入图片描述
这尼玛是啥?(其实小编也是看了好多遍整个概念加上具体的例子才理解掉的)

  • 案例:
    我们举个例子来说明:现在有一个场景,就是需要访问两个数据库(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又是两大不同的分类,所以解决这种涉及到多个产品系列的问题,有一个专门的工厂模式叫做 抽象工厂模式

二、抽象工厂的优点

  1. 易于交换产品系列:
    例如: IFactory factory = new AccessFactory() 在应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不同的产品配置。

  2. 具体的创建实例过程与客户端分离:客户端是通过它们的抽象接口操作实例,产品的具体类名也被具体工厂实现分离,不会出现在客户代码中。

三、对抽象工厂的思考

试想如果我们此时再增加一张IProject表呢?此时我们需要增加IProject、SqlserverProject、
AccessProject还需要更改IFactory、SqlserverFactory、AccessFactory这三个类,一共需要修改6个类。这样是不是值得我们去思考,对于这么大幅度的改动,该如何将进行优化呢?

  1. 使用简单工厂改进抽象工厂
    UML类图:
    在这里插入图片描述
  2. 具体的代码实现:
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();   //直接得到数据库访问实例没有任何依赖
    }
}

但是如上的代码,请读者们进行再次的思考,是否违反了设计模式的开闭原则,如何进行优化呢?剩下的交给读者们自己进行思考,给读者们一个提示那就是反射

四、总结

  1. 抽象工厂模式:提供一个创建一系列相关或者相互依赖对象的接口,而无需指定它们具体的类
  2. 抽象工厂模式是对工厂方法模式的一种扩展和补充。

下一篇 : Java设计模式之——建造者模式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值