一、什么是耦合
程序之间的依赖关系:
①类之间的依赖
②方法之间的依赖
注意:
不可能完全的消除依赖关系,而只能是降低程序之间的依赖关系
二、解耦
降低程序之间的依赖关系:
1.解决类之间的依赖关系:
①通过读取配置文件来获取要创建对象的全限定类名
②使用反射来创建类的对象,尽量避免new关键字的使用
三、问题引出
1.新建Maven项目
2.修改配置文件,添加如下代码,让程序打包成Jar包的形势
jar
3.开始编写实验代码,整体架构如下:
3.持久层接口
package com.huhai.Dao;
/**
*持久层接口
*/
public interface IAccountDao {
public abstract void save();
}
4.持久层接口实现类
package com.huhai.Dao.Impl;
import com.huhai.Dao.IAccountDao;
/**
* 持久层实现类
*/
public class AccountDaoImpl implements IAccountDao {
public void save() {
System.out.println("数据保存成功");
}
}
5.业务层接口
package com.huhai.Service;
/**
*业务层接口
*/
public interface ISaveAccountService {
public abstract void save();
}
6.业务层接口实现类
package com.huhai.Service.Impl;
import com.huhai.Dao.Impl.AccountDaoImpl;
import com.huhai.Service.ISaveAccountService;
/**
* 业务层实现类
*/
public class AccountServiceImpl implements ISaveAccountService {
private AccountDaoImpl accountDao = new AccountDaoImpl();
public void save() {
accountDao.save();
}
}
7.表现层
package com.huhai;
import com.huhai.Service.Impl.AccountServiceImpl;
public class Realize {
private static AccountServiceImpl accountService;
public static void main(String[] args) {
accountService = new AccountServiceImpl();
accountService.save();
}
}
可以看出,它们之间的依赖关系非常严重,因此需要解耦
四、使用工厂模式降低程序耦合度
1.项目架构
2.工厂类:
package com.huhai.Factory;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/**
* 一个创建Bean对象的工厂
* 它就是创建Server和Dao对象的
*/
public class BeanFactory {
/**
* 定义Properties对象
*/
private static Properties properties;
/**
* 使用静态代码段为properties赋值
*/
static {
/**
* 实例化对象
*/
properties = new Properties();
/**
* 获取properties流对象
* 最好不要直接new,因为传路径的时候,路径是一个容易出错的地方
* 因为配置文件在resources根目录下,所以可以直接填写文件名字bean.properties作为参数
* 使用类加载器来获得文件的路径
*/
InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
try {
properties.load(in);
} catch (IOException e) {
/**
* 配置文件如果出错,则没有必要继续运行
* 抛出错误,终止整个程序
*/
throw new ExceptionInInitializerError("初始化异常");
}
}
/**
* 使用工厂模式创建对象
* 因为返回的对象不一定是一个类,所以返回值类型为Object或者泛型
* 根据bean的名称获取bean对象
*/
public static Object getBean(String beanName){
/**
* 初始化返回对象
*/
Object bean = null;
/**
* 根据传入的beanName参数获取properties中的对应类的全限定类名
*/
String beanPath = properties.getProperty(beanName);
try {
bean = Class.forName(beanPath).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return bean;
}
}
工厂类升级版——工厂类的单例模式
package com.huhai.Factory;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
/**
* 一个创建Bean对象的工厂
* 它就是创建Server和Dao对象的
*/
public class BeanFactory {
/**
* 定义Properties对象
*/
private static Properties properties;
/**
* 定义一个Map,使之能够存放已经实例化的对象
* 该Map即为容器
* 该容器的建造是为了完成工厂的类的单例模式
*/
private static Map beans;
/**
* 使用静态代码段为properties赋值
*/
static {
try {
/**
* 实例化对象
*/
properties = new Properties();
/**
* 获取properties流对象
* 最好不要直接new,因为传路径的时候,路径是一个容易出错的地方
* 因为配置文件在resources根目录下,所以可以直接填写文件名字bean.properties作为参数
* 使用类加载器来获得文件的路径
*/
InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
properties.load(in);
/**
* 配置文件如果出错,则没有必要继续运行
* 抛出错误,终止整个程序
*/
/**
*
*/
beans = new HashMap();
Enumeration keys = properties.keys();
/**
* 遍历所有的keys
*/
while(keys.hasMoreElements()){
String key = keys.nextElement().toString();
//根据配置文件得到指定类的全限定类名
String property = properties.getProperty(key);
//使用反射实例化对象
Object obj = Class.forName(property).newInstance();
//将对象放进仓库
beans.put(key, obj);
}
}catch (Exception e){
throw new ExceptionInInitializerError("初始化properties失败!");
}
}
/**
* 使用工厂模式创建对象
* 因为返回的对象不一定是一个类,所以返回值类型为Object或者泛型
* 根据bean的名称获取bean对象
*/
public static Object getBean(String beanName){
//根据bean的名称获取bean单例对象
return beans.get(beanName);
}
}
3.持久层接口
package com.huhai.Dao;
/**
*持久层接口
*/
public interface IAccountDao {
public abstract void save();
}
4.持久层接口实现类
package com.huhai.Dao.Impl;
import com.huhai.Dao.IAccountDao;
/**
* 持久层实现类
*/
public class AccountDaoImpl implements IAccountDao {
public void save() {
System.out.println("数据保存成功");
}
}
5.业务层接口
package com.huhai.Service;
/**
*业务层接口
*/
public interface IAccountService {
public abstract void save();
}
6.业务层接口实现类
package com.huhai.Service.Impl;
import com.huhai.Dao.IAccountDao;
import com.huhai.Factory.BeanFactory;
import com.huhai.Service.IAccountService;
/**
* 业务层实现类
*/
public class AccountServiceImpl implements IAccountService {
/**
* 使用工厂模式创建对象,降低程序耦合度
*/
private IAccountDao accountDao = (IAccountDao)BeanFactory.getBean("accountDaoImpl");
public void save() {
accountDao.save();
}
}
7.表现层
package com.huhai;
import com.huhai.Factory.BeanFactory;
import com.huhai.Service.IAccountService;
public class Realize {
public static void main(String[] args) {
/**
* 为了解耦,使用工厂模式创建对象
*/
IAccountService accountService = (IAccountService) BeanFactory.getBean("accountServiceImpl");
accountService.save();
System.out.println(accountService);
}
}
8.bean.properties配置文件
#键(key)用小写
accountServiceImpl=com.huhai.Service.Impl.AccountServiceImpl
accountDaoImpl=com.huhai.Dao.Impl.AccountDaoImpl