0. 媒介
在软件工程范畴,依靠注入(Dependency Injection)是用于完成掌握反转(Inversion of Control)的最罕见的体式格局之一。本文重要引见依靠注入道理和罕见的完成体式格局,重点在于引见这类年青的设想形式的实用场景及上风。
1. 为何须要依靠注入
掌握反转用于解耦,解的究竟是谁和谁的耦?这是我在最初相识依靠注入时刻发生的第一个题目。
下面我援用Martin Flower在诠释引见注入时运用的一部分代码来申明这个题目。
public class MovieLister { private MovieFinder finder; public MovieLister() { finder = new MovieFinderImpl(); } public Movie[] moviesDirectedBy(String arg) { List allMovies = finder.findAll(); for (Iterator it = allMovies.iterator(); it.hasNext();) { Movie movie = (Movie) it.next(); if (!movie.getDirector().equals(arg)) it.remove(); } return (Movie[]) allMovies.toArray(new Movie[allMovies.size()]); } ... }
public interface MovieFinder { List findAll(); }
我们建立了一个名为MovieLister的类来供应须要的影戏列表,它moviesDirectedBy要领供应依据导演名来搜刮影戏的体式格局。真正担任搜刮影戏的是完成了MovieFinder接口的MovieFinderImpl,我们的MovieLister类在组织函数中建立了一个MovieFinderImpl的对象。
如今看来,一切都不错。然则,当我们愿望修正finder,将finder替换为一种新的完成时(比方为MovieFinder增添一个参数表明Movie数据的泉源是哪一个数据库),我们不仅须要修正MovieFinderImpl类,还须要修正我们MovieLister中建立MovieFinderImpl的代码。
这就是依靠注入要处置惩罚的耦合。这类在MovieLister中建立MovieFinderImpl的体式格局,使得MovieLister不单单议依靠于MovieFinder这个接口,它还依靠于MovieListImpl这个完成。 这类在一个类中直接建立另一个类的对象的代码,和硬编码(hard-coded strings)以及硬编码的数字(magic numbers)一样,是一种致使耦合的坏滋味,我们能够把这类坏滋味称为硬初始化(hard init)。同时,我们也应当像记着硬编码一样记着,new(对象建立)是有毒的。
Hard Init带来的重要害处有两个方面:1)上文所述的修正其完成时,须要修正建立处的代码;2)不便于测试,这类体式格局建立的类(上文中的MovieLister)没法零丁被测试,其行动和MovieFinderImpl牢牢耦合在一起,同时,也会致使代码的可读性题目(“假如一段代码不便于测试,那末它肯定不便于浏览。”)。
2. 依靠注入的完成体式格局
依靠注入实在并不奇异,我们一样平常的代码中许多都用到了依靠注入,但很少注重到它,也很少主动运用依靠注入举行解耦。这里我们简朴引见一下赖注入完成三种的体式格局。
2.1 组织函数注入(Contructor Injection)
这是我以为的最简朴的依靠注入体式格局,我们修正一下上面代码中MovieList的组织函数,使得MovieFinderImpl的完成在MovieLister类以外建立。如许,MovieLister就只依靠于我们定义的MovieFinder接口,而不依靠于MovieFinder的完成了。
public class MovieLister { private MovieFinder finder; public MovieLister(MovieFinder finder) { this.finder = finder; } ... }
2.2 setter注入
相似的,我们能够增添一个setter函数来传入建立好的MovieFinder对象,如许一样能够防止在MovieFinder中hard init这个对象。
public class MovieLister { s... public void setFinder(MovieFinder finder) { this.finder = finder; } }
2.3 接口注入
接口注入运用接口来供应setter要领,其完成体式格局以下。
首先要建立一个注入运用的接口。
public interface InjectFinder { void injectFinder(MovieFinder finder); }
以后,我们让MovieLister完成这个接口。
class MovieLister implements InjectFinder { ... public void injectFinder(MovieFinder finder) { this.finder = finder; } ... }
末了,我们须要依据差别的框架建立被依靠的MovieFinder的完成。
3. 末了
依靠注入降低了依靠和被依靠范例间的耦合,在修正被依靠的范例完成时,不须要修正依靠范例的完成,同时,关于依靠范例的测试,能够更轻易的运用mocking object替换原有的被依靠范例,以到达对依靠对象自力举行单元测试的目标。
末了须要注重的是,依靠注入只是掌握反转的一种完成体式格局。掌握反转另有一种罕见的完成体式格局称为依靠查找。
以上就是php为何要用依靠注入?的细致内容,更多请关注ki4网别的相干文章!