控制反转(IoC)
public interface Service1 {
void execute();
} public class Service1Impl implements Service1 { private Service2 service2; public Service1Impl(Service2 service2) {
this.service2 = service2;
} @Override
public void execute() {
System.out.println("Service1 is doing something."); service2.execute();
} } public interface Service2 {
void execute();
} public class Service2Impl implements Service2 { @Override
public void execute() {
System.out.println("Service2 is doing something.");
} } // 工厂类的实现
public class Service2Factory {
public static Service2 getService2Instance() {
return new Service2Impl();
}
} public class Service1Factory {
public static Service1 getService1Instance() {
Service2 service2 = Service2Factory.getService2Instance();
return new Service1Impl(service2);
} } // 测试代码
public class Client {
public void doSomething() {
Service1 service = Service1Factory.getService1Instance();
service.execute();
}
}
-- Service1 is doing something.
-- Service2 is doing something.
- 工厂类泛滥:在实际应用中,经常出现几百个像这样的服务类,如果使用工厂方法模式的话,就可能出现几百个这样的工厂类。因为不知道将来会产生多少子类扩展系统,所以也不能使用静态工厂模式。
- 依赖关系复杂:往往这几百个 Service对象之间存在复杂的依赖关系,工厂类的装配逻辑也随之变得十分复杂。增加了装配这些服务对象的精力,而不能专注于业务功能的开发。
- 不易进行单元测试。
Inversion of Control(控制反转):
- 模板方法模式——父类的模板方法控制子类的方法调用
- 回调的方法也是控制反转的很好应用。
- 在 Java标准库里,查找(binarySearch) 和 排序(sort)这两个方法,他们在执行过程中会调用对象的 compareTo( ) 方法(如果这些对象实现了 java.lang.Comparable 接口的话),或者调用我们所传递的回调接口 java.util.Comparator 对象的 compare( ) 方法来比较大小,最终完成查找/排序操作。
- 框架:框架抽象了通用流程,我们可以通过框架提供的规范(如子类化抽象类或者实现相关的接口,实现相关的交互协议和接口等)就可以把客户化的代码植入流程中,完成各种定制的需求。
- Service Locator(服务定位器)
- Dependency Injection(依赖注入,简写为 DI)
//简单的服务定位器
public class ServiceLocator {
private static ServiceLocator locator;
// 创建 HashMap<String, Object>对象来持有这些服务对象
private Map<String, Object> services = new HashMap<String, Object>(); // 初始化容器
public static void configure() {
load(new ServiceLocator()); // Service1、Service2的对象其实是按照单例创建的
Service2 service2 = new Service2Impl();
locator.services.put("service2", service2);
Service1 service1 = new Service1Impl(service2);
locator.services.put("service1", service1);
} private static void load(ServiceLocator serviceLocator) {
locator = serviceLocator;
} public static Object lookup(String serviceName) {
return locator.services.get(serviceName);
} public static void registerService(String name, Object service) {
locator.services.put(name, service);
}
}
public class Client {
public void doSomething() { Service1 service1 = (Service1) ServiceLocator.lookup("service1");
service1.execute();
} // 测试代码 public static void main(String[] args) {
// 初始化容器
ServiceLocator.configure(); new Client().doSomething();
}
}
- Setter 注入:外部程序通过调用 setting方法为客户对象注入所依赖的对象。(Spring框架是使用反射机制调用 setting方法注入依赖的对象)
- Constructor 注入:通过带参数的构造方法注入依赖对象。
- Annotation 注入:把实例化信息和对象之间的依赖关系信息使用 Annotation注解。
- Interface 注入:客户程序通过实现容器/框架所规范的某些特殊接口,在为客户对象返回这些依赖的对象之前,容器回调这些接口的方法,注入所依赖的服务对象。如:Struts2中的 Action实现了接口 ServletRequesetAware、SessionAware等,只要 Action类实现这些接口,Struts框架就会调用这些接口的相应方法,注入 HttpServletRequest、HttpSession对象。
- Parameter 注入 :外部程序可以通过函数参数,给客户程序注入所依赖的服务对象。
- 其它形式的注入
// ServiceAware 接口
public interface ServiceAware {
void injectService(Service service);
}
// Service 接口及其实现类
public interface Service {
void excute();
}
public class ServiceImpl implements Service { @Override
public void excute() {
System.out.println("Service is doing something...");
} } // 创建简单的接口注入容器
public class InterfaceInjector { private static InterfaceInjector injector;
private Map<Class, Object> services = new HashMap<Class, Object>(); // 安装容器
public static void configure() {
load(new InterfaceInjector());
} public static <T> T getInstance(Class<T> clazz) {
return injector.loadService(clazz);
} private static void load(InterfaceInjector container) {
InterfaceInjector.injector = container; } private <T> T loadService(Class<T> clazz) { Object service = injector.services.get(clazz); if (service != null) {
return (T) service;
} try {
// 创建 clazz类实例
service = clazz.newInstance();
// 通过接口装配依赖的对象,如果对象是 ServiceAware的实例为真
if (service instanceof ServiceAware) {
// 则调用此接口的方法注入 ServiceAware对象
((ServiceAware) service).injectService(new ServiceImpl());
}
injector.services.put(clazz, service);
} catch (Exception e) {
e.printStackTrace();
} return (T) service;
} } // 只要服务类实现这个接口,容器就会注入 Service对象,定义一个 Client类实现该接口
public class Client implements ServiceAware { private Service service; @Override
public void injectService(Service service) {
this.service = service;
} public void doSomething() {
service.excute();
} public static void main(String[] args) {
InterfaceInjector.configure();
Client client = InterfaceInjector.getInstance(Client.class);
client.doSomething();
}
}
-- Service is doing something...
//参数注入
public class Client {
// 外部程序通过函数参数,给客户程序注入所依赖的服务对象
// 采用外部传递 Service对象方式,至于Service如何实例化,它一无所知
public void dosomething(Service service) {
service.excute();
} // 使用方法:外部程序实例化一个 Service实例,传递给 Client的 dosomething(Service service)方法使用
public static void main(String[] args) {
Service service = new ServiceImpl();
new Client().dosomething(service);
}
}
- IoC使得客户专注于客户化的逻辑设计,把程序流程的控制交给外部代码,实现高内聚低耦合目标。
- 把实例化的过程交给框架/容器来处理,使得我们更专注于业务逻辑的开发。
控制反转(IoC)的更多相关文章
- 控制反转IoC简介
控制反转IoC简介 在实际的应用开发中,我们需要尽量避免和降低对象间的依赖关系,即降低耦合度.通常的业务对象之间都是互相依赖的,业务对象与业务对象.业务对象与持久层.业务对象与各种资源之间都存在这样或 ...
- 浅析“依赖注入(DI)/控制反转(IOC)”的实现思路
开始学习Spring的时候,对依赖注入(DI)——也叫控制反转(IOC)—— 的理解不是很深刻.随着学习的深入,也逐渐有了自己的认识,在此记录,也希望能帮助其他入门同学更深入地理解Spring.本文不 ...
- 控制反转IOC的依赖注入方式
引言: 项目中遇到关于IOC的一些内容,因为和正常的逻辑代码比较起来,IOC有点反常.因此本文记录IOC的一些基础知识,并附有相应的简单实例,而在实际项目中再复杂的应用也只是在基本应用的基础上扩展而来 ...
- 控制反转IOC与依赖注入DI
理解 IOC http://www.cnblogs.com/zhangchenliang/archive/2013/01/08/2850970.html IOC 相关实例 的http:// ...
- 控制反转(Ioc)和依赖注入(DI)
控制反转IOC, 全称 “Inversion of Control”.依赖注入DI, 全称 “Dependency Injection”. 面向的问题:软件开发中,为了降低模块间.类间的耦合度,提倡基 ...
- 控制反转IOC与依赖注入DI【转】
转自:http://my.oschina.net/1pei/blog/492601 一直对控制反转.依赖注入不太明白,看到这篇文章感觉有点懂了,介绍的很详细. 1. IoC理论的背景我们都知道,在采用 ...
- 依赖注入(DI)和控制反转(IOC)
依赖注入(DI)和控制反转(IOC) 0X1 什么是依赖注入 依赖注入(Dependency Injection),是这样一个过程:某客户类只依赖于服务类的一个接口,而不依赖于具体服务类,所以客户类只 ...
- iOS控制反转(IoC)与依赖注入(DI)的实现
背景 最近接触了一段时间的SpringMVC,对其控制反转(IoC)和依赖注入(DI)印象深刻,此后便一直在思考如何使用OC语言较好的实现这两个功能.Java语言自带的注解特性为IoC和DI带来了极大 ...
- 个人对【依赖倒置(DIP)】、【控制反转(IOC)】、【依赖注入(DI)】浅显理解
一.依赖倒置(Dependency Inversion Principle) 依赖倒置是面向对象设计领域的一种软件设计原则.(其他的设计原则还有:单一职责原则.开放封闭原则.里式替换原则.接口分离原则 ...
- 【转载】浅析依赖倒置(DIP)、控制反转(IOC)和依赖注入(DI)
原文地址 http://blog.csdn.net/briblue/article/details/75093382 写这篇文章的原因是这两天在编写关于 Dagger2 主题的博文时,花了大量的精力来 ...
随机推荐
- rdlc Report Viewer Configuration Error
主要是web.config没有配置 方法参考http://msdn.microsoft.com/zh-cn/library/ms251661.aspx
- hdu 1176 免费馅饼(数塔类型)
http://acm.hdu.edu.cn/showproblem.php?pid=1176 免费馅饼 Time Limit: 2000/1000 MS (Java/Others) Memory ...
- class str
class str(object): """ str(object='') -> str str(bytes_or_buffer[, encoding[, erro ...
- 找回使用过的QQ头像
多么渴望那双眼睛能在万紫千红中发现自己:然而眼睛从来就不曾对自己留意:于是换种落寞再次接受垂直打击:然后然后的然后尼玛再换个逗比的头像证明老资无所谓老资无所谓嘿嘿: 我们换头像的时候,发现之前的一个最 ...
- iOS 中self和super如何理解?
或许你理解self和super都是指的是类的对象 self指的是本类的对象,而super指的是父类的对象,但是事实情况呢,可能有些和你想象的不一样? 简单看下下面例子: @interface Pe ...
- Java异常处理中finally中的return会覆盖catch语句中的return语句
Java异常处理中finally中的return会覆盖catch语句中的return语句和throw语句,所以Java不建议在finally中使用return语句 此外 finally中的throw语 ...
- MariaDB5.5.32 绿色版下载安装一条龙
1.下载地址: http://ftp.yz.yamagata-u.ac.jp/pub/dbms/mariadb/mariadb-5.5.32/win32-packages/mariadb-5.5.32 ...
- Codeforces Gym 100231G Voracious Steve 记忆化搜索
Voracious Steve 题目连接: http://codeforces.com/gym/100231/attachments Description 有两个人在玩一个游戏 有一个盆子里面有n个 ...
- Codeforces Round #339 (Div. 2) B. Gena's Code 水题
B. Gena's Code 题目连接: http://www.codeforces.com/contest/614/problem/B Description It's the year 4527 ...
- tcpdump抓包分析具体解释
說實在的,對於 tcpdump 這個軟體來說,你甚至能够說這個軟體其實就是個駭客軟體, 因為他不但能够分析封包的流向,連封包的內容也能够進行『監聽』, 假设你使用的傳輸資料是明碼的話,不得了,在 ro ...