一、Ioc的定義
IOC是Inversion of Control的縮寫,控制反轉的含義。表示對象控制權的轉移,將對象創建、銷毀等移交到Ioc容器來管理,使用該對象的調用者,也需要到Ioc容器中獲取該對象。
下面我們就開始創建自己的Ioc容器來管理和創建對象了。
二、傳統模式下代碼的實現
2.1 我們使用idea創建一個空的maven項目,並建立好一個簡單的三層調用目錄和類,如圖所示:
dao層:數據訪問層
service層:業務層
ui層:暴露給外部使用的層
2.2 補全代碼,使用傳統的new調用的來編寫代碼
(1)dao層的代碼:
接口定義:
public interface IAccountDao {
void saveAccount();
}
實現類:
package org.study.dao.impl;
import org.study.dao.IAccountDao;
public class AccountDaoImpl implements IAccountDao {
@Override
public void saveAccount() {
System.out.println("保存了...");
}
}
(2)service層代碼
接口類:
package org.study.service;
public interface IAccountService {
void saveAccount();
}
實現類:
package org.study.service.impl;
import org.study.dao.IAccountDao;
import org.study.dao.impl.AccountDaoImpl;
import org.study.service.IAccountService;
public class AccountServiceImpl implements IAccountService {
@Override
public void saveAccount() {
IAccountDao accountDao=new AccountDaoImpl();
accountDao.saveAccount();
}
}
(3)ui層代碼
package org.study.ui;
import org.study.service.IAccountService;
import org.study.service.impl.AccountServiceImpl;
public class Client {
public static void main(String[] args) {
IAccountService accountService = new AccountServiceImpl();
accountService.saveAccount();
}
}
(4)代碼編寫完成后,我們的代碼目錄、以及最終運行效果如下圖:
代碼目錄:
運行結果:
2.3 問題分析
我們的代碼如期地正確運行了,但是問題也比較明顯,代碼耦合度高,ui層依賴於service層,service層依賴與dao層。
有沒有好的辦法,能降低我們模塊間的耦合呢,下面我們通過工廠模式創建對象,降低對象間的耦合。
三、使用工廠方法來管理對象、創建對象
3.1 引入beanFactory類,來讀取配置文件,創建對象
(一)編寫配置文件bean.properties,將要管理的類放入配置文件中
accountDao=org.study.dao.impl.AccountDaoImpl
accountService=org.study.service.impl.AccountServiceImpl
(二)編寫beanFactory類,讀取配置文件,並創建對象,代碼如下
package org.study.factory;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
public class beanFactory {
private static final Map<String,String> beanProperties= new HashMap<>();
static {
InputStream inputStream= beanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
Properties properties =new Properties();
try {
properties.load(inputStream);
Enumeration<String> names =(Enumeration<String> )properties.propertyNames();
while (names.hasMoreElements()) {
String key = names.nextElement();
String value = properties.getProperty(key);
beanProperties.put(key, value);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public Object getBean(String name){
String value = beanProperties.get(name);
if (value!=null){
try {
return Class.forName(value).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
}
該類提供了一個方法getBean,該方法通過key來創建對象;
3.2 改造原來的Service層和ui層方法
改造后的代碼層次如下:
(1)改造AccountServiceImpl的類,通過beanFactory創建accountDao,代碼如下:
package org.study.service.impl;
import org.study.dao.IAccountDao;
import org.study.factory.beanFactory;
import org.study.service.IAccountService;
public class AccountServiceImpl implements IAccountService {
@Override
public void saveAccount() {
IAccountDao accountDao=(IAccountDao) beanFactory.getBean("accountDao");
accountDao.saveAccount();
}
}
(2)改造ui層的類,通過beanFactory創建accountService,代碼如下:
IAccountService accountService = (IAccountService) beanFactory.getBean("accountService");
accountService.saveAccount();
運行代碼,結果如下:
四、總結
一、第一種方式編寫代碼是我們常見的方式,缺點是代碼間的耦合度高,一個類強依賴於另一個類。
二、第二種方式,我們將對象的創建都放到工廠類里來執行,類之間只依賴於接口,不依賴於具體的實現;通過此方式,我們降低了對象之間的耦合,可以隨時修改接口的實現類;缺點是,對象的創建過程變得更復雜了,不那么直觀。
三、beanFactory是一個簡單的ioc容器類,我們的對象都通過這個容器創建,功能也很單一。
下一篇,我們開始引入spring框架幫我們管理對象,讓我們一起學習spring中的ioc。