Spring中使用工厂模式解耦详解

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: Spring中使用工厂模式解耦详解

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站点击跳转浏览。


解耦 降低程序之间的耦合性


为什么要降低程序之间的耦合性


**原因很简单。当耦合度很高时,在代码维护过程中修改一个地方会涉及到很多地方。如果耦合关系不是澄清修改期间,后果可能是灾难性的,特别是对于有许多变化的项目需求和多人协作开发和维护,修改一个地方会导致模块的错误一直运行稳定,如果是严重的,将导致一个恶性循环,问题永远不能完全解决,开发和测试正与各种各样的问题作斗争。最终会导致项目延迟,降低用户满意度,增加成本。而且也提高了程序的复用性


引入类之间的耦合性


在我们学习jdbc访问数据库时,具体流程是

首先在maven里面导入依赖


<packaging>jar</packaging>
    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
    </dependencies>


然后就是jdbc的实现过程:

1.注册驱动

2.获取连接

3.获取操作数据库的预处理对象

4.执行SQL,得到结果集

5.遍历结果集

6.释放资源

具体代码如下:


public class Jdbc {
    public static void main(String[] args) throws  Exception{
        //1.注册驱动
  //  DriverManager.registerDriver(new com.mysql.jdbc.Driver());
        Class.forName("com.mysql.jdbc.Driver");
        //2.获取连接
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","1234");
        //3.获取操作数据库的预处理对象
        PreparedStatement pstm = conn.prepareStatement("select * from account");
        //4.执行SQL,得到结果集
        ResultSet rs = pstm.executeQuery();
        //5.遍历结果集
        while(rs.next()){
            System.out.println(rs.getString("name"));
        }
        //6.释放资源
        rs.close();
        pstm.close();
        conn.close();
    }
}

第一种创建驱动方式


进行分析,上面代码中被注释的那句代码

DriverManager.registerDriver(new com.mysql.jdbc.Driver());

如果把pom里面的依赖注释就相当于没有jar包,然后我们进行编译

则不能编译,会是一个错误,如图所示:


第二种创建驱动方式


Class.forName(“com.mysql.jdbc.Driver”);

这句代码就只依赖于一个字符串而不是一个驱动类。

这样子当jar包不存在时,就是一个异常而不是一个错误。这样子就是避免的类之间的耦合性



但是产生一个新的问题,导致这个字符串在类中写死了如果换成其他数据库的话,就还要改代码,所以我们要通过配置文件来获取要创建的对象全限定类名,然后再用反射来创建对象

所以 解耦的思路:

第一步:使用反射来创建对象,而避免使用new关键字。
第二步:通过读取配置文件来获取要创建的对象全限定类名


实际开发中:

应该做到:编译期不依赖,运行时才依赖。


业务层Service调用持久层Dao时的耦合性


Dao层


userdao层的接口

public interface IUserDao {
    void save();
}

userdao层的实现类


package Dao.IMPL;
import Dao.IUserDao;
public class UserDao implements IUserDao {
    public void save() {
        System.out.println("hello");
    }
}

UserService的接口


package Service;
public interface IUserService {
    void save();
}

UserService的实现类


package Service.IMPL;
import Dao.IMPL.UserDao;
import Service.IUserService;
public class UserService implements IUserService {
    //private将这个对象私有化
    //因为dao是一个接口的实现类  接口是不是实例化的 但是可以创建一个接口的实现类对象
    private IUserDaodao=new UserDao();
    public void save() {
        System.out.println("hello");
    }
}

private IUserDaodao=new UserDao(); 这句代码就是Service层调用Dao层,当我们把UserDao的代码去除之后,程序就出现报错,不能编译成功,说明程序之间的耦合性太强了。


工厂模式解耦合


上面的service层调用dao层的耦合性太强之后我们可以参考之前的jdbc里面的步骤。


第一步:使用反射来创建对象,而避免使用new关键字。
 第二步:通过读取配置文件来获取要创建的对象全限定类名

所以我们可以通过工厂来进行一个解耦

BeanFactory:个创建Bean对象的工厂


什么是Bean


在计算机英语中,有可重用组件的含义,可重用的意思是一个servlet可能有多个service 一个service中可能有多个dao.一个servicc或者一个dao都是一个Bean


第一步:需要一个配置文件来配置我们的service和dao 配置的内容:唯一标识=全限定类名(key=value)


我们创建一个Bean.properties也可以是一个Bean.xml,在这里我们在resources里面创建一个Bean.properties记录里面的全限定类名


UserService=Service.IMPL.UserService
UserDao=Dao.IMPL.UserDao

第二步通过读取配置文件中配置的内容,反射创建对象


package factory;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
public class BeanFactory {
    //读取配置文件
    //定义一个静态Properties对象
    private static Properties props;
//    //定义一个Map,用于存放我们要创建的对象。我们把它称之为容器
    //多例变单例
    private static Map<String,Object> beans;
    //使用静态代码块为Properties对象赋值
    static {
        try {
            //实例化对象
            props = new Properties();
            //获取properties文件的流对象
            //这个时候不能用new FileInputStream因为这这个时候的相对路肩和绝对路径都不管用
            //we工程部署src没有了   相对路径不能用 绝对路径也不行
            //要用类加载器来进行操作
            InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
            //加载一个流对象
            props.load(in);
//            //实例化容器
            beans = new HashMap<String,Object>();
//            //取出配置文件中所有的Key
            Enumeration keys = props.keys();
//            //遍历枚举
            while (keys.hasMoreElements()){
//                //取出每个Key
                String key = keys.nextElement().toString();
//                //根据key获取value
                String beanPath = props.getProperty(key);
//                //反射创建对象
                Object value = Class.forName(beanPath).newInstance();
//                //把key和value存入容器中
                beans.put(key,value);
            }
        }catch(Exception e){
            //抛出一个初始化错误  后面直接执行不了
            throw new ExceptionInInitializerError("初始化properties失败!");
        }
    }
    /**
     * 根据bean的名称获取对象  用Object类型做返回值
     * @param beanName
     * @return
     */
    public static Object getBean(String beanName){
        return beans.get(beanName);


这样之后,我们再调用dao层时就可以把在BeanFactory里面创建


private IUserDao dao= (IUserDao) BeanFactory.getBean("UserDao");


同样调用service代码也发生变化


IUserService service= (IUserService) BeanFactory.getBean("UserService");


这样之后,再把删除就只报异常,而且如果需要更改代码里面的值,我们就只用更改配置文件里面的代码这样就可以更加快速的进行更改操作。


新创建一个公众号 Rockey小何同学 想相互交流的同学可以关注一下哈! 感谢支持!

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
3月前
|
消息中间件 Java 开发者
【颠覆想象】Spring Boot重构未来:解耦与隔离,打造坚不可摧的微服务帝国!
【8月更文挑战第29天】本文通过构建电子商务平台的具体案例,深入探讨了如何利用 Spring Boot 实现服务间的解耦与隔离。文章详细介绍了依赖注入、模块化设计及异步通信等关键技术,并提供了具体代码示例。通过依赖注入,对象间耦合得以降低;模块化设计使各功能域独立,降低系统复杂度;异步通信则利用消息队列提升系统吞吐量与响应速度。这些方法不仅优化了系统架构,还加快了开发进程。
68 0
|
5月前
|
Java 开发者 Spring
Spring Boot 实现解耦和隔离的技术指南
【6月更文挑战第13天】Spring Boot 作为一种流行的 Java 框架,通过其强大的依赖注入和配置管理功能,使得开发者可以轻松实现模块之间的解耦和隔离
87 3
|
1月前
|
Java Spring
Spring从入门到入土(解耦的实现过程)
这篇文章详细讲解了在Spring框架中实现解耦的多种方法,包括使用接口、配置文件、BeanFactory模式以及单例模式,旨在降低代码间的依赖关系,提高程序的可维护性和扩展性。
29 0
Spring从入门到入土(解耦的实现过程)
|
1月前
|
JSON 前端开发 Java
Spring Boot框架中的响应与分层解耦架构
在Spring Boot框架中,响应与分层解耦架构是两个核心概念,它们共同促进了应用程序的高效性、可维护性和可扩展性。
51 3
|
3月前
|
Java 开发者 Spring
Spring Boot大法好:解耦、隔离、异步,让代码‘活’起来,性能飙升的秘密武器!
【8月更文挑战第29天】解耦、隔离与异步是Spring Boot中的关键设计原则,能大幅提升软件的可维护性、扩展性和性能。本文通过示例代码详细探讨了这些原则的应用:依赖注入和面向接口编程实现解耦;模块化设计与配置文件实现隔离;`@Async`注解和`CompletableFuture`实现异步处理。综合运用这些原则,可以显著提升软件质量和性能,使系统更加健壮、灵活和高效。
38 0
|
6月前
|
XML Java 数据格式
[Spring 基础] 掌握Spring DI,轻松解耦你的应用
[Spring 基础] 掌握Spring DI,轻松解耦你的应用
|
设计模式 Java uml
彻底搞懂Spring状态机原理,实现订单与物流解耦
状态模式的UML类图如下图所示。
307 0
|
设计模式 前端开发 Java
【Spring】工厂模式
【Spring】工厂模式
|
前端开发 JavaScript Java
浅谈Spring的相关概念性问题 IOC DI AOP 工厂模式 单例
浅谈Spring的相关概念性问题 IOC DI AOP 工厂模式 单例
145 0
|
设计模式 Java Spring
java spring设计模式 之 工厂模式
java spring设计模式 之 工厂模式