抽象工厂模式

本文详细介绍了抽象工厂模式的概念,并通过一个具体的数据库访问案例展示了其在用户和部门表操作中的应用。文章讨论了简单工厂和抽象工厂的区别,并分析了抽象工厂模式的优缺点。在面对增加新数据库支持的需求时,提出使用简单工厂进行改进,降低了代码的维护成本,实现了更好的解耦。最后,文章提到了改进后方案的潜在问题及其解决方案。
摘要由CSDN通过智能技术生成

抽象工厂模式

定义

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

UML图

在这里插入图片描述
在这里插入图片描述

简单工厂、工厂和抽象工厂区别

转自链接
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

用例

User类:用户类

public class User {
    private Integer id;
}

IUser接口:用于客户端访问,解除与具体数据库i访问的耦合。

interface IUser{
    void insert(User user);
    User getUser(int id);
}

SqlserverUser类:访问SQL Server的User

public class SqlServerUser implements IUser{
    @Override
    public void insert(User user) {
        System.out.println("在SQL Server中给User表增加一条记录");
    }
 
    @Override
    public User getUser(int id) {
        System.out.println("在SQL Server中根据ID得到User表一条记录");
        return null;
    }
}

Access User:访问Access的User

public class AccessUser implements IUser{
    @Override
    public void insert(User user) {
        System.out.println("在Access中给User表增加一条记录");
    }
 
    @Override
    public User getUser(int id) {
        System.out.println("在Access中根据ID得到User表一条记录");
        return null;
    }
}

Department类:部门类

public class Department{
    private Integer id;
}

IDepartment接口:用于客户端访问,解除与具体数据库访问的耦合

public interface IDepartment{
    void insert(Department department);
    Department getDepartment(int id);
}

SqlServerDepartment类:用于访问SqlServer的Department。

public class SqlServerDepartment implements IDepartment{
    @Override
    public void insert(Department department){
        System.out.println("在SQL Server中给Department表增加一条记录");
    }
 
    @Override
    public void getDepartment(int id){
        System.out.println("在SQL Server中根据ID得到Department表一条记录");
    }
}

Access Department :访问Access的Department

public class AccessDepartment implements IDepartment{
    @Override
    public void insert(Department department){
        System.out.println("在Access中给Department表增加一条记录");
    }
 
    @Override
    public User getDepartment(int id){
        System.out.println("在Access中根据ID得到Department表一条记录");
        return null;
    }
}

IFactory接口:定义一个创建访问User表对象的抽象的工厂接口

public interface IFactory{
    IUser createUser();
    IDepartment createDepartment();
}

SqlServerFactory类:实现IFactory接口,实例化SqlServerUser和SqlServerDepartment。

public class SqlServerFactory implements IFactory{
    @Override
    public IUser createUser(){
        return new SqlServerUser();
    }
 
    @Override
    public IDepartment createDepartment(){
        return new SqlServerDepartment();
    }
}

AccessFactory类:实现IFactory接口,实例化AccessUser和AccessDepartment。

public class AccessFactory implements IFactory{
    @Override
    public IUser createUser(){
        return new AccessUser();
    }
 
    @Override
    public IDepartment createDepartment(){
        return new AccessDepartment();
    }
}

客户端代码

public static void main(String[] args){
	User user = new User();
	Department dept = new Department();
    IFactory factory = new SqlServerFactory();
    //IFactory factory = new AccessFactory();
    IUser iu = factory.createUser();//此时已经和具体的数据库解除了依赖
    iu.insert(user);
    iu.getUser(1);

    IDepartment id = factory.createDepartment();
    id.insert(dept);
    id.getDepartment(1);
}

优点

  1. 易于交换产品系列,由具体工厂类,例如IFactory factory = new SqlServerFactory(),在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,他只需要改变具体工厂即可使用不同的配置。
  2. 它让具体的创建实例过程与客户端分离,客户端是通过它们的抽象接口操纵实例,产品具体类名也被具体工厂的实现分离,不会出现在客户端代码中。就像刚才的例子,客户端所认识的只有IUser和IDepartment,至于使用SQL server实现还是Access实现就不知道了。

缺点

比如要增加一个Department表就要增加很多类,IDepartment,SqlServerDepartment,MySqlDepartment,还需要更改IFactory、SqlServerFactory和MySqlFactory才可以完全实现。而且我们的客户端程序不止一个,很多地方都会用到IUser和IDepartment,如果100个地方要切换数据库就要改动100处代码。

用简单工厂来改进抽象工厂

去除IFactory、SqlServerFactory和MySqlFactory三个工厂类,用一个简单工厂DataAccess类实现:

public class DataAccess{
    private final static String db = "SqlServer";//选择数据库
//    private final static String db = "Access";
    public static IUser createUser(){
        IUser result = null;
        switch (db){
            case "SqlServer":
                result = new SqlServerUser();
                break;
            case "Access":
                result = new AccessUser();
                break;
            default:
                break;
        }
        return result;
    }
 
    public static IDepartment createDepartment(){
        IDepartment result = null;
        switch (db){
            case "SqlServer":
                result = new SqlServerDepartment();
                break;
            case "Access":
                result = new AccessDepartment();
                break;
            default:
                break;
        }
        return result;
    }
}

客户端代码:没有出现一个SqlServer或者Mysql的字样,实现了完全解耦。

public static void main(String[] args) {
	User user = new User();
	Department dept = new Department();
	
    IUser iu = DataAccess.createUser();//此时已经和具体的数据库解除了依赖
    iu.insert(user);
    iu.getUser(1);

    IDepartment id = factory.createDepartment();
    id.insert(dept);
    id.getDepartment(1);
}

UML图

在这里插入图片描述

缺点

比如增加一个Oracle数据库访问,本来抽象工厂增加一个OracleFactory工厂类就可以了,现在就比较麻烦了,需要在DataAccess类的每个switch语句中加case。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值