框架漫谈之spring(一)工厂模式实现程序解耦,spring框架的引出

本文探讨了程序耦合的概念及问题,并通过工厂模式实现了不同层间的解耦。随后介绍了Spring框架如何作为大型工厂帮助开发者进一步简化解耦过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.程序的耦合度

我们来看如下的代码

// 表现层
public class UserController {
    public static void main(String[] args) {
        IUserService userService = new UserServiceImpl();
        userService.saveUser();
    }
}
// 业务实现类接口
public interface IUserService {
    void saveUser();
}
// 业务实现类
public class UserServiceImpl implements IUserService {
    private UserDao userDao = new UserDao();
    public void saveUser() {
        userDao.saveUser();
}
// 持久层接口
public interface IUserDao{
    void saveUser();
}
// 持久层实现类
public class UserDaoImpl implements IUserDao {
    System.out.println("保存一个用户");
}

该程序模拟了某网站注册用户的流程,我们来看上述的程序,表面上来看是没有一点问题的,但仔细的看。表现层与业务层、业务层与持久层紧紧的互相依赖关联,这与我们开发程序的高内聚低耦合原则相违背。我们也来看一看原始的JDBC程序

//注册mysql驱动
DriverManager.deregisterDriver(new com.mysql.jdbc.Driver());

点进jdbc注册驱动的源码可以知道,当加载这个类时候 已经注册,这样相当于注册了两次。从程序的角度的来看即使注册了2次所浪费的效率基本上可以忽略不计。原始的JDBC注册驱动 紧紧的依赖着mysql的jar包,一旦没有mysql的jar包编译时就会报错,所以我们真正写JDBC注册驱动的是用这行代码

//注册mysql驱动  改进了注册2次的问题 并且做到了编译时候不依赖
Class.forName("com.mysql.jdbc.Driver");

从JDBC和上述模拟用户注册的案例来看,当有一个类在编译时候,紧紧依赖于另外一个类的存在.
当没有依赖类存在时,程序不能编译.此时我们就称这两个类有很想的依赖关系,高耦合度
开发中应该遵循的依赖原则:编译时不依赖,运行时在依赖。

2.工厂模式实现程序解耦

使用工厂模式:
工厂为我们创建类的对象,从而解决层和层之间的依赖关系。
这种依赖关系我们也叫,程序的耦合。

package test.factory;
import test.dao.IUserDao;

/**
 * 工厂模式: 用于削减计算机程序耦合
 * 
 * @author ZhuPengWei
 * @Date 2017年9月24日
 */
public class BeanFactory {
    private static BeanFactory factory;
    static {
        factory = new BeanFactory();
    }

    // 单例模式:私有化构造函数
    private BeanFactory() {
    }

    // 提供一个公共方法,获取该类的实例
    public static BeanFactory newInstance() {
        return factory;
    }

    /**
     * 用于生成一个的持久层实现类对象
     * 
     * @return
     */
    public IUserDao getUserDao() {
        try {
            return (IUserDao) Class.forName("test.dao.impl.UserDao").newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

用户业务层实现类也作出如下的改进

public class UserServiceImpl implements IUserService {
    // private IUserDao userDao = new UserDao();
    IUserDao userDao = BeanFactory.newInstance().getUserDao();

    public void saveUser() {
        userDao.saveUser();
    }
}

3.工厂模式改进

仔细的来看,上面的工厂模式存在了大量的问题,首先它在反射创建对象时候使用了硬编码,存在硬编码的问题。其次此工厂模式不利于程序的扩充,首先开发需要写获取持久层的方法以及业务层的方法,一旦有新的解耦需求工厂类就得添加新的方法,这样是十分不利于维护的。下面,将对于这两点进行改进
在类路径下创建bean.properties

USERDAO = test.dao.impl.UserDaoImpl
USERSERVICE =test.service.impl.UserServiceImpl
package test.factory;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.ResourceBundle;


/**
 * 工厂模式: 用于削减计算机程序耦合
 * 
 * @author ZhuPengWei
 * @Date 2017年9月24日
 */
public class BeanFactory {
    // 此类可以通过静态方法获取对象,参数是资源文件的名称(不写程序的扩展名)。
    // 底层是类加载器,因此只能读取类路径下的资源文件(src目录下)。
    private static ResourceBundle bundle = ResourceBundle.getBundle("bean");

    // 定义一个容器,用于存储配置文件中配置的对象
    private static Map<String, Object> beans = new HashMap<String, Object>();

    private static BeanFactory factory;
    static {
        factory = new BeanFactory();
        // 初始化容器
        Enumeration<String> keys = bundle.getKeys();
        while (keys.hasMoreElements()) {
            // 取出每一个key
            String key =  keys.nextElement();
            // 根据key,获取全限定类名
            String classPath = bundle.getString(key);
            try {
                // 根据classPath反射创建类对象
                Object object = Class.forName( classPath).newInstance();
                // 存入map中
                beans.put(key, object);
            } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
                throw new ExceptionInInitializerError("初始化容器失败!");
            }

        }
    }

    // 单例模式:私有化构造函数
    private BeanFactory() {
    }

    // 提供一个公共方法,获取该类的实例
    public static BeanFactory newInstance() {
        return factory;
    }

    /**
     * 根据参数获取Bean对象
     * @param beanName 参数
     * @return Bean对象
     */
    public Object getBean(String beanName){
        return beans.get(beanName);
    }


    /**
     * 用于生成一个的持久层实现类对象
     * 由于返回值是一个固定的接口,所以导致了创建其他类对象时,必须写新的方法
     * @return
     */
    // public IUserDao getUserDao() {
    // try {
    // return (IUserDao) Class.forName("test.dao.impl.UserDao").newInstance();
    // } catch (Exception e) {
    // throw new RuntimeException(e);
    // }
    // }
}
package test.service.impl;

import test.dao.IUserDao;
import test.factory.BeanFactory;
import test.service.IUserService;
/**
 * 用户业务层实现类
 *
 * @author ZhuPengWei
 * @Date  2017年9月24日
 */
public class UserServiceImpl implements IUserService {
    // private IUserDao userDao = new UserDao();
    //IUserDao userDao = BeanFactory.newInstance().getUserDao();

    //改造后的方法:获取bean对象,根据bean名称。得到的对象是Object,需要强转
    private IUserDao userDao  = (IUserDao) BeanFactory.newInstance().getBean("USERDAO");

    public void saveUser() {
        userDao.saveUser();
    }
}

4.spring框架引出

那我们为什么要用spring呢?首先它的好处之一就是方便解耦简化开发。
spring是一个大工厂,可以将所有对象创建和依赖维护交给spring去管理
暂时本文也只是说明了这一个好处。

什么是spring框架?
spring是一个开源框架。它是为了解决企业应用开发的复杂性而创建的,框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为J2EE应用程序开发提供继承的框架。spring使用基本的JAVABean来完成以前只可能由EJB完成的事情。spring的用途也不仅仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从spring中收益。spring的核心就是控制反转(ioc)和面向切面(aop)。简单的来说,spring是一个分层的一站式轻量级开源框架

spring是用来干什么的?
这个介绍的不错

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值