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提供的工厂肯定是比我们现在设计的工厂功能要更加强大.

相关文章
|
1月前
|
设计模式 算法 C++
【C++ 泛型编程 进阶篇】C++元模板编程与设计模式的结合应用教程(二)
【C++ 泛型编程 进阶篇】C++元模板编程与设计模式的结合应用教程
26 0
|
29天前
|
设计模式 编解码 C++
【ffmpeg 视频播放】深入探索:ffmpeg视频播放优化策略与设计模式的实践应用(一)
【ffmpeg 视频播放】深入探索:ffmpeg视频播放优化策略与设计模式的实践应用
47 0
|
25天前
|
安全 Java 数据安全/隐私保护
【深入浅出Spring原理及实战】「EL表达式开发系列」深入解析SpringEL表达式理论详解与实际应用
【深入浅出Spring原理及实战】「EL表达式开发系列」深入解析SpringEL表达式理论详解与实际应用
54 1
|
29天前
|
设计模式 存储 缓存
【ffmpeg 视频播放】深入探索:ffmpeg视频播放优化策略与设计模式的实践应用(二)
【ffmpeg 视频播放】深入探索:ffmpeg视频播放优化策略与设计模式的实践应用
27 0
|
5天前
|
设计模式 Java 数据库连接
Spring Framework 6 中的设计模式
Spring Framework 6 中的设计模式
17 1
|
5天前
|
设计模式 算法 Java
Java中的设计模式及其应用
【4月更文挑战第18天】本文介绍了Java设计模式的重要性及分类,包括创建型、结构型和行为型模式。创建型模式如单例、工厂方法用于对象创建;结构型模式如适配器、组合关注对象组合;行为型模式如策略、观察者关注对象交互。文中还举例说明了单例模式在配置管理器中的应用,工厂方法在图形编辑器中的使用,以及策略模式在电商折扣计算中的实践。设计模式能提升代码可读性、可维护性和可扩展性,是Java开发者的必备知识。
|
20天前
|
存储 安全 Java
Spring Security应用讲解(Java案列演示)
Spring Security应用讲解(Java案列演示)
|
25天前
|
Prometheus 监控 Cloud Native
Spring Boot 应用可视化监控
Spring Boot 应用可视化监控
15 0
|
25天前
|
设计模式 Java 数据库连接
9种设计模式在Spring中的运用
9种设计模式在Spring中的运用
61 0
|
26天前
|
设计模式 算法 中间件
【C++ 可调用对象的应用】C++设计模式与现代编程技巧:深入可调用对象的世界
【C++ 可调用对象的应用】C++设计模式与现代编程技巧:深入可调用对象的世界
111 1