Spring5深入浅出篇:Spring工厂设计模式拓展应用

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
可观测可视化 Grafana 版,10个用户账号 1个月
简介: Spring5深入浅出篇:Spring工厂设计模式拓展应用

Spring5深入浅出篇:Spring工厂设计模式拓展应用

简单工厂实现

这里直接上代码举例子

UserService.java

public interface UserService {
    public void register(User user);
    public void login(String name, String password);
}

UserServiceImpl.java

public class UserServiceImpl implements UserService {
    private UserDAO userDAO = new UserDAOImpl();
    public UserDAO getUserDAO() {
        return userDAO;
    }
    public void setUserDAO(UserDAO userDAO) {
        this.userDAO = userDAO;
    }
    @Override
    public void register(User user) {
        userDAO.save(user);
    }
    @Override
    public void login(String name, String password) {
        userDAO.queryUserByNameAndPassword(name, password);
    }
}

UserDAOImpl.java

public class UserDAOImpl implements UserDAO {
    @Override
    public void save(User user) {
        System.out.println("insert into user = " + user);
    }
    @Override
    public void queryUserByNameAndPassword(String name, String password) {
        System.out.println("query User name = " + name+" password = "+password);
    }
}

为了方便测试更直观看到结果UserDAOImpl的方法采用打印一条字符串来体现,下面就通过测试类来调用UserService

测试类

/**
     *  用于测试:工厂类进行解耦合的操作
     */
    @Test
    public void test1() {
       UserService userService = new UserServiceImpl();
        UserService userService = (UserService) BeanFactory.getBean("userService");
        userService.login("name", "suns");
        User user = new User("suns", "123456");
        userService.register(user);
    }

最终结果如下:

可以发现当我们在上图中就出现了耦合,当我们需要重新换一个实现类的时候需要重新修改代码在进行编译部署.下面就通过工厂设计模式来解决这个问题.

创建工厂类

BeanFactory.java

public class BeanFactory {
       public static UserService getUserService(){
    return new UserServiceImpl();
    }
}

这样就通过了工厂类中提供的getUserService方法来获取对象,这样测试类中就彻底没有耦合了,但是new对象的方法写到了工厂类中,下面来看看如何解决.

对象的创建方式

  • 直接调用构造方法 创建对象
UserService userService = new UserServiceImpl();
  • 通过反射的形式 创建对象 解耦合
Class clazz = Class.forName("com.baizhiedu.basic.UserServiceImpl");
UserService userService = (UserService)clazz.newInstance();

重新修改工厂类

BeanFactory.java

public class BeanFactory {
       public static UserService getUserService(){
     UserService userService = null;
        try {                        
            Class clazz = Class.forName("com.baizhiedu.basic.UserServiceImpl");
            userService = (UserService) clazz.newInstance();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return userService;
    }
}

通过反射并不能完全解决耦合的问题,因为这里的全限定类名字符串如果需要修改,也涉及到需要修改源码.这里我们通过读取resources下的properties文件来进行优化

applicationContext.properties

userService = com.baizhiedu.basic.UserServiceImpl

BeanFactory.java

private static Properties env = new Properties();
    static{
        try {
            //第一步 获得IO输入流
            InputStream inputStream = BeanFactory.class.getResourceAsStream("/applicationContext.properties");
            //第二步 文件内容 封装 Properties集合中 key = userService value = com.baizhixx.UserServiceImpl
            env.load(inputStream);
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
public static UserService getUserService() {
        UserService userService = null;
        try {
                                         //com.baizhiedu.basic.UserServiceImpl
            Class clazz = Class.forName(env.getProperty("userService"));
            userService = (UserService) clazz.newInstance();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return userService;
    }

这里就是直接通过配置文件读取对应的全限定类名即可,使我们程序之间的耦合解决.即便是我们还需要解决UserDaoImpl的耦合也是异曲同工,只需要将UserServiceImpl,改成UserDaoImpl

UserDAO解耦

BeanFactory.java

public static UserDAO getUserDAO(){
        UserDAO userDAO = null;
        try {
            Class clazz = Class.forName(env.getProperty("userDAO"));
            userDAO = (UserDAO) clazz.newInstance();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return userDAO;
    }

applicationContext.xml

<bean id="userDAO" class="com.baizhiedu.basic.UserDAOImpl"></bean>

通用工厂实现


可以发现上图代码出现冗余,我们应该对这种重复的代码块进行抽取

通用工厂代码

public class BeanFactory{
 public static Object getBean(String key){
    Object ret = null;
 try {
    Class clazz = Class.forName(env.getProperty(key));
    ret = clazz.newInstance();
 } catch (Exception e) {
  e.printStackTrace();
 }
    return ret;
 }
}

这样只需要在applicationContext.xml中增加对应配置,就可以通过getBean方法传入对应的key从工厂获取到对象了.

@Test
    public void test1() {
        UserService userService = (UserService) BeanFactory.getBean("userService");
        userService.login("name", "suns");
        User user = new User("suns", "123456");
        userService.register(user);
    }

通用工厂的使用方式

1.定义类型(需要创建对象的类)

2.通过配置文件的配置告知工厂(applicationContext.properties)

以key = value的形式

3.通过工厂获得类的对象

Object ret = BeanFactory.getBean("key")

总结

Spring的本质其实就是工厂+配置文件的形式,但是Spring提供的工厂肯定是比我们现在设计的工厂功能要更加强大.

相关文章
|
2天前
|
设计模式 前端开发 JavaScript
【JavaScript 技术专栏】JavaScript 设计模式与实战应用
【4月更文挑战第30天】本文探讨JavaScript设计模式在提升开发效率和代码质量中的关键作用。涵盖单例、工厂、观察者、装饰器和策略模式,并通过实例阐述其在全局状态管理、复杂对象创建、实时数据更新、功能扩展和算法切换的应用。理解并运用这些模式能帮助开发者应对复杂项目,提升前端开发能力。
|
2天前
|
Java 应用服务中间件 测试技术
深入探索Spring Boot Web应用源码及实战应用
【5月更文挑战第11天】本文将详细解析Spring Boot Web应用的源码架构,并通过一个实际案例,展示如何构建一个基于Spring Boot的Web应用。本文旨在帮助读者更好地理解Spring Boot的内部工作机制,以及如何利用这些机制优化自己的Web应用开发。
29 3
|
2天前
|
安全 Java 开发者
深入理解Spring Boot配置绑定及其实战应用
【4月更文挑战第10天】本文详细探讨了Spring Boot中配置绑定的核心概念,并结合实战示例,展示了如何在项目中有效地使用这些技术来管理和绑定配置属性。
14 1
|
1天前
|
设计模式 XML Java
第五篇 设计模式的选择和应用 - 智慧选择与合理实践
第五篇 设计模式的选择和应用 - 智慧选择与合理实践
|
2天前
|
前端开发 Java 测试技术
Java一分钟之Spring MVC:构建Web应用
【5月更文挑战第15天】Spring MVC是Spring框架的Web应用模块,基于MVC模式实现业务、数据和UI解耦。常见问题包括:配置DispatcherServlet、Controller映射错误、视图解析未设置、Model数据传递遗漏、异常处理未配置、依赖注入缺失和忽视单元测试。解决这些问题可提升代码质量和应用性能。注意配置`web.xml`、`@RequestMapping`、`ViewResolver`、`Model`、`@ExceptionHandler`、`@Autowired`,并编写测试用例。
51 3
|
2天前
|
开发框架 监控 Java
深入探索Spring Boot的监控、管理和测试功能及实战应用
【5月更文挑战第14天】Spring Boot是一个快速开发框架,提供了一系列的功能模块,包括监控、管理和测试等。本文将深入探讨Spring Boot中监控、管理和测试功能的原理与应用,并提供实际应用场景的示例。
15 2
|
2天前
|
设计模式 JavaScript 算法
js设计模式-策略模式与代理模式的应用
策略模式和代理模式是JavaScript常用设计模式。策略模式通过封装一系列算法,使它们可互换,让算法独立于客户端,提供灵活的选择。例如,定义不同计算策略并用Context类执行。代理模式则为对象提供代理以控制访问,常用于延迟加载或权限控制。如创建RealSubject和Proxy类,Proxy在调用RealSubject方法前可执行额外操作。这两种模式在复杂业务逻辑中发挥重要作用,根据需求选择合适模式解决问题。
|
2天前
|
Java Spring 容器
深入理解Spring Boot启动流程及其实战应用
【5月更文挑战第9天】本文详细解析了Spring Boot启动流程的概念和关键步骤,并结合实战示例,展示了如何在实际开发中运用这些知识。
18 2
|
2天前
|
设计模式 算法 Java
设计模式在Java开发中的应用
设计模式在Java开发中的应用
18 0
|
2天前
|
JavaScript Java 开发者
Spring Boot中的@Lazy注解:概念及实战应用
【4月更文挑战第7天】在Spring Framework中,@Lazy注解是一个非常有用的特性,它允许开发者控制Spring容器的bean初始化时机。本文将详细介绍@Lazy注解的概念,并通过一个实际的例子展示如何在Spring Boot应用中使用它。
21 2