首页 > 其他分享 >(十三)抽象工厂模式

(十三)抽象工厂模式

时间:2022-11-25 22:25:11浏览次数:38  
标签:十三 id 工厂 Override 抽象 User Department IDepartment public

1 概述

抽象工厂模式(Abstract Factory),提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

  • AbstractProductAAbstractProductB是两个抽象产品,而ProductA1ProductA2ProductB1ProductB2就是对两个抽象产品的具体分类的实现。

  • AbstractFactory是一个抽象工厂接口,它里面应该包含所有的产品创建的抽象方法。而ConcreteFactory1ConcreteFactory2就是具体的工厂。

  • 通常是在运行时刻再创建一个ConcreteFactory类的实例,这个具体的工厂再创建具有特定实现的产品对象,也就是说,为创建不同的产品对象,客户端应使用不同的具体工厂。

2 示例

User类,表示User表。

public class User {
}

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

public 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("在SqlServer中给User表增加一条记录");
    }

    @Override
    public User getUser(int id) {
        System.out.println("在SqlServer中根据id得到User表一条记录");
        return null;
    }
}

AccessUser类,用于访问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类,表示Department表。

public class Department {
}

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

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

SqlserverDepartment类,用于访问SQL Server的Department。

public class SqlServerDepartment implements IDepartment {
    @Override
    public void insert(Department department) {
        System.out.println("在SqlServer中给Department表增加一条记录");
    }

    @Override
    public Department getDepartment(int id) {
        System.out.println("在SqlServer中根据id得到Department表一条记录");
        return null;
    }
}

AccessDepartment类,用于访问Access的Department。

public class AccessDepartment implements IDepartment {
    @Override
    public void insert(Department department) {
        System.out.println("在Access中给Department表增加一条记录");
    }

    @Override
    public Department getDepartment(int id) {
        System.out.println("在Access中根据id得到Department表一条记录");
        return null;
    }
}

IFactory接口,定义一个创建访问User表和Department表对象的抽象的工厂接口。

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 class Client {
    public static void main(String[] args) {
        User user = new User();
        Department department = new Department();

        // 只需确定实例化哪一个数据库访问对象给 factory
        IFactory factory = new SqlServerFactory();

        // 则此时已与具体的数据库访问解除了依赖
        IUser iu = factory.createUser();
        iu.insert(user);
        iu.getUser(1);

        factory = new AccessFactory();
        IDepartment id = factory.createDepartment();
        id.insert(department);
        id.getDepartment(1);
    }
}

输出入下。

在SqlServer中给User表增加一条记录
在SqlServer中根据id得到User表一条记录
在Access中给Department表增加一条记录
在Access中根据id得到Department表一条记录

Process finished with exit code 0

3 优缺点

优点:

  • 易于交换产品系列,由于具体工厂类在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不同的产品配置。

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

缺点

  • 增加一个抽象产品时,要增加多个具体产品实现,而且抽象工厂和各具体工厂都要更改。

    例如,要增加项目表Project,那就至少要增加三个类,IProject、SqIserverProject、AccessProject,还需要更改IFactory、SqlserverFactory和 AccessFactory 才可以完全实现。

  • 每次定义工厂时,都要指定具体的实例化工厂。

    例如:lFactory factory =new SqlserverFactoryO;

4 改进

用简单工厂改进,DataAccessc用反射技术,取代IFactory、SqlserverFactory和AccessFactory。

这里感觉保留IFactory,用DataAccess实现IFactory接口也挺好的。

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Properties;

public class DataAccess {
    private String db;

    public DataAccess() {
        try {
            // 读取配置文件
            InputStream inputStream = DataAccess.class.getClassLoader().getResourceAsStream("dbConfig.properties");
            // 设置编码
            InputStreamReader isr = new InputStreamReader(inputStream, "UTF-8");
            Properties properties = new Properties();
            properties.load(isr);
            db = properties.getProperty("db");

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public IUser creatUser() {
        IUser iu = null;
        try {
            // 利用反射创建对象
            Class cl = Class.forName(db + "User");
            iu = (IUser) cl.newInstance();
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
        return iu;
    }

    public IDepartment creatDepartment() {
        IDepartment id = null;
        try {
            Class cl = Class.forName(db + "Department");
            id = (IDepartment) cl.newInstance();
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
        return id;
    }
}

配置文件dbConfig.properties

db = 抽象工厂模式.SqlServer

输出入下。

在SqlServer中根据id得到User表一条记录
在SqlServer中给User表增加一条记录
在SqlServer中根据id得到Department表一条记录
在SqlServer中给Department表增加一条记录

Process finished with exit code 0

参考书籍:
《大话设计模式》

标签:十三,id,工厂,Override,抽象,User,Department,IDepartment,public
From: https://www.cnblogs.com/dalelee/p/16915863.html

相关文章