关键词:factory pattern , Dependency Injection(DI), Guice(pronounced “juice” )
参考:
【1】维基DI :http://en.wikipedia.org/wiki/Dependency_injection
【2】一篇博文:http://www.blogjava.net/xylz/archive/2009/xylz/archive/2009/12/23/307092.html
阐述问题:Why Guice exist && What is DI
正文:
Listing1-1code写的是厨子需要的一个随机产生祝福语的功能。
Listing1-2code是使用GOF factory pattern
这里 service就是 FortuneService,它被定义成了一个接口。
FortuneServiceImpl是它的一个实现类。
这里client就是Chef
//Listing1-1
public interface FortuneService {
String randomFortune();
}
public class FortuneServiceImpl implements FortuneService {
private static final List<String> MESSAGES =
Arrays.asList(
"Today you will have some refreshing juice.",
"Larry just bought your company."
);
public String randomFortune() {
return MESSAGES.get(new Random().nextInt(MESSAGES.size()));
}
}
//Listing 1-2
public class Chef {
private FortuneService fortuneService;
public Chef() {
this.fortuneService = FortuneServiceFactory.getFortuneService();
}
public void makeFortuneCookie() {
new FortuneCookie(fortuneService.randomFortune());
}
}
public class FortuneServiceFactory {
private FortuneServiceFactory() {}
private static FortuneService fortuneService = new FortuneServiceImpl();
public static FortuneService getFortuneService() {
return fortuneService;
}
public static void setFortuneService(FortuneService mockFortuneService) {
fortuneService = mockFortuneService;
}
}
代码1-3就是对上面的一个测试代码,但这出现了两个问题
问题1:我们得先实例化一个FortuneService使用FortuneServiceFactory.setFortuneService()注入到FortuneServiceFactory中
问题2:另外我们需要在finally中恢复原来FortuneService的值,不然就有数据污染。
于是,DI就出现了,DI是如何解决这个问题的呢
key sentence也就是DI的主要思想是 :
instead of pulling your dependencies in(例如代码1-3), you opt toreceivethem from someplace
[思想引用自好莱坞:don't call us,we'll call u]
DI的优势P14页列了几条,但是没特别明白,为什么尽量不使用static方法
再往下走
Listing1-4就是使用了DI修改过的chef,与1-2相比,1-4的chef采用构造函数注入的方法,将FortuneService作为参数进行初始化。
Listing1-5就是对应的使用DI思想的unit test,代码简练很多,并且没有了static方法,也不用在finally内部做数据恢复。
但是问题还是存在的,既然chef构造函数有一个FortuneService作为参数,于是我们在实例一个chef之前需要实例一个FortuneService。这是我理解代码1-6是什么意思。
于是,GUICE就出现了,GUICE是如何解决这个问题的呢
Guice可以不使用factory而是使用几个简单的配置就完成了注入工作,在需要注入的地方书写@Inject
Listing1-7就是展示如何使用inject语法就加了一行@Inject
Listing1-8是对应的test,没有变化
然后剩下就是define a module告诉哪里需要implementation工作
Listing 1-9展示了其中一种方法,语法非常好读。
最后就是总结:目的就是写出maintanable、好测试的代码,又要摆脱工厂模式、又要DI巴拉巴拉