-
编写jdbc的工程代码用于分析程序的耦合
添加依赖 <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql - connec tor- java</artifactId> <version>5.1.7</version> </dependency> </ dependencies>
//copy下来的代码,与下面项目不是同一个 public class JdbcDemo1 { public static void main(String[] args) throws Exception{ //1.注册驱动 DriverManager.registerDriver(new com.mysql.jdbc.Driver()); //2.获取连接 Connection conn = DriverManager.getConnection( "jdbc :mysql://localhost:3307/mydb","root","980106WSK"); //3.获取操作数据库的预处理对象 PreparedStatement pstm = conn.prepareStatement("select * from account"); //4.执行SQL,得到结果集 ResultSet rs = pstm.executeQuery(); //5.遍历结果集 while(rs.next()){ System.out.print1n(rs.getString("name")); } //6.释放资源 rs.close() ; pstm.close(); conn.close();
-
编译期依赖
将依赖注释掉程序报错Error: (14, 56) java :程序包com.mysql. jdbc不存在
Compilatien conpleted with 1 ertor and 0 waringe in 2s 648ms(编译时遇到错误)
-
程序的耦合和解耦的思路分析
- 耦合 : 程序间的依赖关系
- 类之间的依赖
- 方法间的依赖
- 解耦 : 降低程序间的依赖关系
- 实际开发中 ,应该做到:
- 编译期不依赖
- 运行时才依赖
- 解耦思路 :
- 使用反射来创建对象,而避免使用new关键字
- 通过读取配置文件来获取要创建的对象全限定类名
- 耦合 : 程序间的依赖关系
-
曾经代码中的问题分拆
private IitemsDao iitemsDao = new ItemsDaoImpl(); IitemsService iitemsService = new ItemsServiceImpl();
业务层调用持久层,表现层调用业务层,使用new关键字的依赖关系有很强的耦合性,使我们代码的独立性很差
-
编写工厂类和配置文件
- BeanFactory类
/** * 一个创建Bean对象的工厂 * * Bean:在计算机英语中,有可重用组件的含义。 * JavaBean:用java语言编写的可重用组件。 * javabean >实体类 * 它就是创建我们的service和dao对象的。 * * 第一个:需要一个配置文件来配置我们的service和dao * 配置的内容:唯一标识=全限定类名 (key=value) * 第二个:通过读取配置文件中配置的内容,反射创建对象 * 我的配置文件可以是xml也可以是properties */ public class BeanFactory{ }
- bean.properties配置文件
itemsDao=com.qfetu.dao.impl.ItemsDaoImpl itemsService=com.qfetu.service.impl.ItemsServiceImpl
-
工厂模式解耦
- BeanFactory类
/** * 一个创建Bean对象的工厂 * * Bean:在计算机英语中,有可重用组件的含义。 * JavaBean:用java语言编写的可重用组件。 * javabean >实体类 * 它就是创建我们的service和dao对象的。 * * 第一个:需要一个配置文件来配置我们的service和dao * 配置的内容:唯一标识=全限定类名 (key=value) * 第二个:通过读取配置文件中配置的内容,反射创建对象 * 我的配置文件可以是xml也可以是properties */ public class BeanFactory { //定义一个Properties对象 private static Properties properties; //使用静态代码块为properties对象赋值 static { try { //实例化对象 properties = new Properties();//有些耦合是无法避免的,我们不能做到完全消除 //获取properties文件的流对象 //InputStream is = new FileInputStream(); 这里不要用FileInputStream,而是使用类加载器的形式 InputStream is = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties"); properties.load(is); } catch (Exception e) { throw new ExceptionInInitializerError("初始化properties失败");//这里抛出一个初始化异常,Error } } /** * 根据Bean的名称获取bean对象 * @param beanName * @return */ public static Object getBean(String beanName){ Object bean = null; try { String beanPath = properties.getProperty(beanName); bean = Class.forName(beanPath).newInstance(); } catch (Exception e) { e.printStackTrace(); } return bean; } }
//IitemsService iitemsService = new ItemsServiceImpl(); IitemsService iitemsService = (IitemsService)BeanFactory.getBean("itemsService"); //private IitemsDao iitemsDao = new ItemsDaoImpl(); private IitemsDao iitemsDao = (IitemsDao)BeanFactory.getBean("itemsDao");
-
分析工厂模式中的问题并改造
- 多例
for (int i = 0; i < 5; i++) { IitemsService iitemsService = (IitemsService)BeanFactory.getBean("itemsService"); System.out.println(iitemsService); }
打印结果
此时的对象是多例的,对象被创建多次,执行效率没有单例对象高
-
单例
只被创建一次,从而类中的成员也就只会初始化一次,有线程问题,但是在Service和Dao层是没有类成员的,所以不存在线程问题
bean = Class.forName(beanPath).newInstance();//每次都会调用默认构造函数创建对象
-
分析
通过对单例的分析,显然并不需要多例,只需要每一次都是同一个对象就够了,所以对这个方法进行调整,调整的前提是对象只能newInstance()一次.如果你创建之后不存起来,根据java的垃圾回收机制,它会在长时间不用时被回收,当下一次再使用时,就没有了,所以需要在对象创建出来后马上存起来
-
工厂模式解耦的升级版
- 修改后的BeanFactory类
/** * 一个创建Bean对象的工厂 * * Bean:在计算机英语中,有可重用组件的含义。 * JavaBean:用java语言编写的可重用组件。 * javabean >实体类 * 它就是创建我们的service和dao对象的。 * * 第一个:需要一个配置文件来配置我们的service和dao * 配置的内容:唯一标识=全限定类名 (key=value) * 第二个:通过读取配置文件中配置的内容,反射创建对象 * 我的配置文件可以是xml也可以是properties */ public class BeanFactory { //定义一个Properties对象 private static Properties properties; //定义一个Map,用于存放我们要创建的对象,我们把它称之为容器 private static Map<String,Object> beans; //使用静态代码块为properties对象赋值 static { try { //实例化对象 properties = new Properties();//有些耦合是无法避免的,我们不能做到完全消除 //获取properties文件的流对象 //InputStream is = new FileInputStream(); 这里不要用FileInputStream,而是使用类加载器的形式 InputStream is = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties"); properties.load(is); //实例化容器 beans = new HashMap<String,Object>(); // 取出配置文件中所有的Key Enumeration keys = properties.keys(); // 遍历枚举 while (keys.hasMoreElements()){ // 取出每个Key String key = keys.nextElement().toString(); // 根据key获取value String beanPath = properties.getProperty(key); //反射创建对象 Object value = Class.forName(beanPath).newInstance(); //把key和value存入容器中 beans.put(key,value); } } catch (Exception e) { throw new ExceptionInInitializerError("初始化properties失败");//这里抛出一个初始化异常,Error } } /** * 根据bean的名称获取对象 * @param beanName * @return */ public static Object getBean(String beanName){ return beans.get(beanName); } /* *//** * 根据Bean的名称获取bean对象 * @param beanName * @return *//* public static Object getBean(String beanName){ Object bean = null; try { String beanPath = properties.getProperty(beanName); bean = Class.forName(beanPath).newInstance(); //每次都会调用默认构造函数创建对象 } catch (Exception e) { e.printStackTrace(); } return bean; }*/ }
打印结果
在使用Map将对象存进去之后会发现,后续使用后就不需要再反复创建