控制反转(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 主题的博文时,花了大量的精力来 ...
随机推荐
- Educational Codeforces Round 5 E. Sum of Remainders (思维题)
题目链接:http://codeforces.com/problemset/problem/616/E 题意很简单就不说了. 因为n % x = n - n / x * x 所以答案就等于 n * m ...
- HDU2838Cow Sorting(树状数组)
题目意思是说给你一列数,每次可以将相邻的两个数交换,这一步的代价是这两个数的和,求将所有数排好序的最少代价. 题解: 我们可以这么思考,由于每次都是交换相邻的两个数,所以将一个数放到它自己的位置去后, ...
- 手把手教你玩转SOCKET模型之重叠I/O篇(上)
“身为一个初学者,时常能体味到初学者入门的艰辛,所以总是想抽空作点什么来尽我所能的帮助那些需要帮助的人.我也希望大家能把自己的所学和他人一起分享,不要去鄙视别人索取时的贪婪,因为最应该被鄙视的是不肯付 ...
- Adding Multithreading Capability to Your Java Applications
src: http://www.informit.com/articles/article.aspx?p=26326&seqNum=3 Interrupting Threads A threa ...
- PostQuitMessage, PostThreadMessage( WM_QUIT )
http://blogs.msdn.com/b/oldnewthing/archive/2005/11/04/489028.aspx Why is there a special PostQuitMe ...
- ARM Cortex-M instructions
ARM Cortex-M instruction sets ARMCortex-M Thumb Thumb-2 Hardwaremultiply Hardwaredivide Saturatedmat ...
- PL/pgSQL学习笔记之六
http://www.postgresql.org/docs/9.1/static/plpgsql-declarations.html 39.3.1. 声明函数参数 传递给函数的参数被用 $1.$2等 ...
- MySQL Profile
1:查看MySQL当前版本是否支持profile mysql> SELECT @@HAVE_PROFILING; +------------------+ | @@HAVE_PROFILING ...
- OSG 实现跟随节点的相机(转)
本章教程将继续使用回调和节点路径(NodePath)来检索节点的世界坐标. 本章目标: 在一个典型的仿真过程中,用户可能需要从场景中的各种车辆和人物里选择一个进行跟随.本章将介绍一种将摄像机“依附 ...
- 简单的新浪微博OAuth认证实现
System.setProperty("weibo4j.oauth.consumerKey", Weibo.CONSUMER_KEY); System.setProperty(&q ...