工厂模式设计IOC容器
IOC容器的底层实现其实就是利用工厂设计模式。接下来我们通过工厂设计模式模拟一个小型的IOC容器,让大家对IOC的底层原理更加清晰些。
一、搭建案例程序
1)CustomerDao接口:
package com.yiidian.dao;
public interface CustomerDao {
public void save();
}
2)CustomerDaoMySQLImpl:(模拟MySQL版本的Dao实现)
package com.yiidian.dao.impl;
import com.yiidian.dao.CustomerDao;
/**
*
* @author http://www.yiidian.com
*
*/
public class CustomerDaoMySQLImpl implements CustomerDao {
@Override
public void save() {
System.out.println("把客户数据保存到mysql数据");
}
}
3)CustomerService接口:
package com.yiidian.service;
/**
*
* @author http://www.yiidian.com
*
*/
public interface CustomerService {
public void save();
}
4)CustomerServiceImpl实现类:
package com.yiidian.service.impl;
import com.yiidian.dao.CustomerDao;
import com.yiidian.dao.impl.CustomerDaoImpl;
import com.yiidian.service.CustomerService;
/**
*
* @author http://www.yiidian.com
*
*/
public class CustomerServiceImpl implements CustomerService {
//1.传统方法,直接new对象.
private CustomerDao customerDao = new CustomerDaoImpl();
@Override
public void save() {
customerDao.save();
}
}
5)ActionDemo类(模拟Struts2的Action):
package com.yiidian.web;
import com.yiidian.service.CustomerService;
import com.yiidian.service.impl.CustomerServiceImpl;
/**
*
* @author http://www.yiidian.com
*
*/
public class ActionDemo {
public static void main(String[] args) {
//传统方式调用业务,直接new对象
CustomerService customerService = new CustomerServiceImpl();
customerService.save();
}
}
6)运行ActionDemo的main方法,执行结果为:
二、扩展程序,发现问题
1)给CustomerDao接口添加多一个实现类,CustomerDaoOracleImpl(模拟Oracle的Dao实现):
package com.yiidian.dao.impl;
import com.yiidian.dao.CustomerDao;
/**
*
* @author http://www.yiidian.com
*
*/
public class CustomerDaoOracleImpl implements CustomerDao {
@Override
public void save() {
System.out.println("保存客户数据保存Oracle");
}
}
2)这时我们需要在CustomerServiceImpl类中调用CustomerDaoOracleImpl的方法,需要手动修改代码实现:
package com.yiidian.service.impl;
import com.yiidian.dao.CustomerDao;
import com.yiidian.dao.impl.CustomerDaoOracleImpl;
import com.yiidian.service.CustomerService;
/**
*
* @author http://www.yiidian.com
*
*/
public class CustomerServiceImpl implements CustomerService {
//1.传统方法,直接new对象.
//private CustomerDao customerDao = new CustomerDaoMySQLImpl();
private CustomerDao customerDao = new CustomerDaoOracleImpl(); //(弊端:耦合性太高,修改源代码)
@Override
public void save() {
customerDao.save();
}
}
3)运行ActionDemo,查看结果:
总结问题:我们每次为CustomerDao接口扩展了实现类,业务层需要修改代码才可以实现切换具体的实现类,这种做法为“硬编码”
方式,扩展性不好!接下来开始引用工厂设计模式
改造程序。
三、利用工厂设计模式,改造程序
1)编写一个BeanFactory类,用于读取配置文件,创建程序需要的对象:
package com.yiidian.ioc;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/**
* 创建对象的工厂(模拟简单IOC容器)
* @author http://www.yiidian.com
*
*/
public class BeanFactory {
/**
* 初始化beans.properties文件
*/
private static Properties props = new Properties();
static{
InputStream in = BeanFactory.class.getResourceAsStream("/beans.properties");
try {
props.load(in);
} catch (IOException e) {
e.printStackTrace();
System.out.println("加载beans.properties文件失败");
}
}
/**
* 从工厂获取一个对象
* @return
*/
public static Object getBean(String name){
//根据name创建不同的对象
//1.通过name在properties文件找到类名称
String className = props.getProperty(name);
//2.通过反射构造类的对象
try {
return Class.forName(className).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
2)在src目录编写beans.properties配置文件:
beans.properties:
customerDao=com.yiidian.dao.impl.CustomerDaoMySQLImpl
3)改造CustomerServiceImpl类:
/**
*
* @author http://www.yiidian.com
*
*/
public class CustomerServiceImpl implements CustomerService {
//1.传统方法,直接new对象.
//private CustomerDao customerDao = new CustomerDaoMySQLImpl();
//private CustomerDao customerDao = new CustomerDaoOracleImpl(); //(弊端:耦合性太高,修改源代码)
//2.IOC容器
private CustomerDao customerDao = (CustomerDao) BeanFactory.getBean("customerDao");
@Override
public void save() {
customerDao.save();
}
}
4)运行ActionDemo,这时可以调用Dao程序,这时如果需求切换到CustomerDaoOracleImpl,只需要修改beans.properties,改为:
customerDao=com.yiidian.dao.impl.CustomerDaoOracleImpl
再次运行ActionDemo,可以看到已经成功切换到Oracle的Dao实现啦!
到此为止,BeanFactory就是一个小型的IOC容器,可以创建我们程序中需要的一些对象。
事实上,Spring的IOC容器的底层就是类似BeanFactory的原理
!
热门文章
优秀文章