java中解耦合_简单分析程序中耦合和解耦合

什么是程序的耦合

耦合性(Coupling),也叫耦合度,是对模块间关联程度的度量。耦合的强弱取决于模块间接口的复杂性、调用模块的方式以及通过界面传送数据的多少。模块间的耦合度是指模块之间的依赖关系,包括控制关系、调用关系、数据传递关系。模块间联系越多,其耦合性越强,同时表明其独立性越差( 降低耦合性,可以提高其独立性)。耦合性存在于各个领域,而非软件设计中独有的,但是我们只讨论软件工程中的耦合。在软件工程中,耦合指的就是就是对象之间的依赖性。对象之间的耦合越高,维护成本越高。因此对象的设计应使类和构件之间的耦合最小。软件设计中通常用耦合度和内聚度作为衡量模块独立程度的标准。划分模块的一个准则就是高内聚低耦合。

简单来说就是,减少模块之间的依赖性,提高程序的独立性

通常,我们在一个程序中,调用另外一个程序的方法,我们一般都会想到用new这个关键词,在学习Spring之前,我们在ServiceImpl中调用DAO中的方法,我们一般会这样写

private IAccountDAO dao = new IAccountDAOImpl();

这样的代码写多了之后会大大的增加程序的耦合度,没有遵循开发中的高内聚,低耦合的开发思想,极大的增加了代码的维护难度,非常不利于代码的维护和调式,所以我们想到在Java发射中我们学过通过newInstance() 对象来获得实例,所以我们可以,通过反射来降低代码之间的耦合度。

但是,要想通过newInstance() 来获取对象的实例就必须得到该类的全限定类名,所以,我们考虑用XML或者是Properties,但是由于properties较为简单,所以此处我们选用properties。

代码如下

//IAccountDAO.java

public interface IAccountDAO {

void saveAccount();

}

//IAccountDAOImpl.java

public class IAccountDAOImpl implements IAccountDAO {

@Override

public void saveAccount() {

System.out.println("账户保存成功");

}

}

//IAccountService.java

public interface IAccountService {

void saveAccount();

}

//IAccountServiceImpl.java

public class IAccountServiceImpl implements IAccountService {

//private IAccountDAO dao = new IAccountDAOImpl();

IAccountDAO dao = (IAccountDAO) BeanFactory.getBean("IAccountDAO");

@Override

public void saveAccount() {

dao.saveAccount();

System.out.println(i);

}

}

//BeanFactory.java

public class BeanFactory {

//定义一个Properties对象

private static Properties properties;

static {

try {

InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");

properties = new Properties();

properties.load(in);

} catch (IOException e) {

throw new ExceptionInInitializerError("初始化properties异常");

}

}

public static Object getBean(String beanName) {

Object bean = null;

try {

//通过beanName获取该类的全限定类名

String property = properties.getProperty(beanName);

//实例化properties

bean = Class.forName(property).newInstance();//每次都会调用默认构造函数创建对象

} catch (InstantiationException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

return bean;

}

}

//Client.java

public class Client {

public static void main(String[] args) {

//IAccountService service = new IAccountServiceImpl();

IAccountService service = (IAccountService) BeanFactory.getBean("IAccountService");

service.saveAccount();

}

}

#bean.properties文件

#需要一个唯一标识来配置我们的Service和Dao,配置内容:唯一标识=全限定类名(key=value)

IAccountService=com.toulan.service.impl.IAccountServiceImpl

IAccountDAO=com.toulan.dao.impl.IAccountDAOImpl

运行结果

660a3e5f0f1944e1638e8bf78b06259a.png

我们发现我们并没有像以前写的那样通篇全是通过new 来实例化对象,减少了代码之间的耦合度。

现在我们将代码进行少许的修改,然后再次运行,修改的代码如下

//IAccountServiceImpl.java

public class IAccountServiceImpl implements IAccountService {

//private IAccountDAO dao = new IAccountDAOImpl();

IAccountDAO dao = (IAccountDAO) BeanFactory.getBean("IAccountDAO");

public int i = 1;

@Override

public void saveAccount() {

dao.saveAccount();

System.out.println(i);

i++;

}

}

//Client.java

public class Client {

public static void main(String[] args) {

//IAccountService service = new IAccountServiceImpl();

IAccountService service = null;

for (int i=0;i<5;i++) {

service = (IAccountService) BeanFactory.getBean("IAccountService");

System.out.println(service);

service.saveAccount();

}

}

}

运行结果

9c7764e2fa3448df1e0ba756456c9767.png

通过运行结果我们发现,虽然我们在for循环里面什么也没做,但是结果中我们发现打印出来的对象都不一样,但是我们期望它是一样的,不一样的原因是因为每次调用newInstance() 这个方法它都会执行该类的无参构造器,从而来创建一个新的对象。其实我们不太需要每次都来创建一个对象,而每次创建一个新的对象,对内存的消耗也是不小的,所以我们可以考虑使用单例模式,但是newInstance() 每次调用都会创建一个新的对象,所以如果我们的同一对象使用多次,我们可以考虑只newInstance 一次,但是如果我们创建一个对象而长时间不去使用它,那么就会因为Java的垃圾回收机制导致该对象被回收,导致我们下次使用的时候对象已经被回收而导致无法使用,所以,我们要将实例化的对象装入一个新的容器之中去,那么,我们就可以定义一个Map,用于存放相对应的键值,所以代码修改如下:

//BeanFactory.java

public class BeanFactory {

//定义一个Properties对象

private static Properties props;

//定义一个Map,用于存放我们要创建的对象。我们把它称之为容器

private static Map beans;

//使用静态代码块为Properties对象赋值

static {

try {

//实例化对象

props = new Properties();

//获取properties文件的流对象

InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");

props.load(in);

//实例化容器

beans = new HashMap();

//取出配置文件中所有的Key

Enumeration keys = props.keys();

//遍历枚举

while (keys.hasMoreElements()){

//取出每个Key

String key = keys.nextElement().toString();

//根据key获取value

String beanPath = props.getProperty(key);

//反射创建对象

Object value = Class.forName(beanPath).newInstance();

//把key和value存入容器中

beans.put(key,value);

}

}catch(Exception e){

throw new ExceptionInInitializerError("初始化properties失败!");

}

}

/**

* 根据bean的名称获取对象

* @param beanName

* @return

*/

public static Object getBean(String beanName) {

return beans.get(beanName);

}

}

运行结果

561798cebbe80777079d02aad14ce597.png

7316bf0c777745f430cf09f80a4d2955.png

4a668feaa3018a2e1706f07e5002bcc8.png

LOL_toulan

发布了37 篇原创文章 · 获赞 20 · 访问量 7824

私信

关注

标签:和解,对象,分析程序,public,IAccountService,new,耦合,IAccountDAO,properties

来源: https://blog.csdn.net/LOL_toulan/article/details/104135224

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值