• 设计模式之抽象工厂模式


    利用反射技术简单梳理抽象工厂模式

    工厂模式实现

    通常我们在实际工作中,经常遇到需要访问数据库的场景。
    而常见的数据库又多种多样,怎么样针对不同的数据库来建立不同的数据库连接呢?
    我们可以看下用抽象工厂模式加上反射技术来如何实现。

    首先我们定义基本类,假设数据库中有用户表和部门表,我们定义两张基本的javabean对象。

    package designpattem.abstractfactory;
    
    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;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    package designpattem.abstractfactory;
    
    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;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    针对两个bean对象,我们定义对应的两个访问接口。

    package designpattem.abstractfactory;
    
    public interface IUser {
        public void Insert(User user);
        public User GetUser(int id);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    package designpattem.abstractfactory;
    
    public interface IDepartment {
        public void Insert(Department department);
        public Department GetDepartment(int id);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    同样,我们以sqlserver和access两种不同的数据库来作为样例,来看下怎么访问User和Department
    我们先定义sqlserver的访问user和department的方法

    package designpattem.abstractfactory;
    
    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;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    package designpattem.abstractfactory;
    
    public class SqlserverDepartment implements IDepartment {
    
        @Override
        public void Insert(Department department) {
            System.out.println("在 SQL Server中给Department表增加一条记录。");
        }
        @Override
        public Department GetDepartment(int id) {
            System.out.println("在SQL Server中根据ID得到Department表一条记录");
            return null;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    同理我们定义Access数据库对user和department的访问

    package designpattem.abstractfactory;
    
    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得到Access表一条记录");
            return null;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    package designpattem.abstractfactory;
    
    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;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    好了,前期准备工作都处理完了,我们看下利用反射技术怎么对去创建以及读取user和department数据。

    package designpattem.abstractfactory;
    
    public class DataAccess {
        private static String AssemblyName="designpattem.abstractfactory";
        private static String db="Sqlserver";
    
        public static IUser CreateUser() throws InstantiationException, IllegalAccessException, ClassNotFoundException{
            String className=AssemblyName+"."+db+"User";
            return (IUser)Class.forName(className).newInstance();
        }
        public static IDepartment CreateDepartment() throws InstantiationException, IllegalAccessException, ClassNotFoundException{
            String className=AssemblyName+"."+db+"Department";
            return (IDepartment)Class.forName(className).newInstance();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    定义业务方法

    看在具体业务逻辑中如何使用

    package designpattem.abstractfactory;
    
    public class AbstractFactoryTest {
        public static void main(String[] args) throws Exception {
            //抽象工厂模式
            func1();
        }
    
        public static void func1() throws Exception{
            User user = new User();
            Department dept = new Department();
    
            IUser iu = DataAccess.CreateUser();
            iu.Insert(user);
            iu.GetUser(1);
            IDepartment  id = DataAccess.CreateDepartment() ;
            id.Insert(dept);
            id.GetDepartment(1);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    执行结果

    在 SQL Server中给User表增加一条记录。
    在SQL Server中根据ID得到User表一条记录
    在 SQL Server中给Department表增加一条记录。
    在SQL Server中根据ID得到Department表一条记录
    
    • 1
    • 2
    • 3
    • 4

    结果分析

    抽象工厂模式,提供一个创建一系列相关或者相互依赖对象的接口,而无需指定它们的具体类。  
    
    抽象工厂模式最大的好处便是易于交换产品系列,由于具体工厂类在一个应用中只需要在初始化的时候出现一次,
    这使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不同的产品配置。
    
    
    第二个好处就是它让具体的创建实例过程与客户端分离,客户端是通过他们的抽象接口操纵实例,
    产品的具体类名也被具体工厂的实现分离,不会出现在客户端代码中。
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    https://xmlrambo.github.io/
    https://xmlrambo.gitee.io/

  • 相关阅读:
    面试:聊聊阻塞和非阻塞、协程非阻塞式挂起
    Dobot机械臂的Python Demo
    儿童疫苗接种:安全与注意事项
    Docker 镜像库国内加速的几种方法
    ren域名有价值吗?值不值得投资?ren域名的应用范围有哪些?
    ffmpeg的安装以及使用
    ToDesk等远程软件连接主机无法更改分辨率 - 解决方案
    分享几招教会你怎么给图片加边框
    ESP8266-Arduino编程实例-TMP175数字温度传感器驱动
    skywalking
  • 原文地址:https://blog.csdn.net/ForeverLucky_/article/details/128174836