去年我在我的一个游乐场项目中实现了一个简单的类作为IOC容器(不太像那样),一些专业人士告诉我在测试代码时会遇到一些问题(太静脉分享什么确切地说是问题!!)
虽然我自己总是使用IOC框架,但我想知道为什么这种方法很糟糕?
我甚至使用这种方法编写了许多测试(使用模拟框架)并且从未出现过问题。
我想要你对此设计问题的想法:
public class IocContainer{
private static IocContainer instance;
private IocContainer(){
}
public static IocContainer getInstance()
{
if(instance == null){
instance = new IocContainer();
}
return instance;
}
public ChatPresenter getChatPresenter(ChatView chatView)
{
return new ChatPresenterImpl(chatView, getChatRepo() , getMessagingService());
}
private ChatRepo getChatRepo()
{
return new ChatRepoImpl(getDbHelper(), getRemoteService());
}
private MessagingService getMessagingService()
{
return new MessagingServiceImpl()
}
private DbHelper getDbHelper()
{
return new DbHelperImpl();
}
private RemoteService getRemoteService()
{
return new RemoteServiceImpl();
}
}
如你所见,我只能访问getChatPresenter,我在下面的视图中使用它,效果很好。
ChatPresenter presenter = IocContainer.getInstance().getChatPresenter(this)
代码处理控制反转而没有任何紧密耦合(使用接口)。
我想知道这种方法有什么不对吗? (我想从技术角度来看答案,因为我已经知道使用Ioc容器库更容易拥有更多功能,如范围等等......)
实际上我想知道这种方法将来会遇到的任何问题和限制吗?
残忍并杀了我:D
答案 0 :(得分:1)
总结评论记录:
您的方法看起来像Martin Fowler所描述的服务定位器:http://martinfowler.com/articles/injection.html#InversionOfControl
Martin描述的代码与您的代码之间存在重大差异:您的代码直接创建服务实例,因此更像是工厂而不是注册表。
控制反转的基本思想/目标是通过减少依赖性来减少耦合,如果容器依赖于服务实现(它需要直接调用构造函数),则不会发生这种情况。因此,你的问题中的实施有点反对这个基本思想。
依赖于实现的缺点之一是无需重新编译容器就无法替换服务。如果您最有可能永远不会有不同的实现,那可能不是问题,但如果您可能需要它,服务注册表会更有用。
注册表通常提供注册服务实现并根据请求提供服务的方法。哪个交付取决于您的需求,但它可以像第一个实现一样简单或更复杂,例如通过匹配一些参数(对于某些想法,看看CDI注入点参数和替代品)。
注册表通常附有一些配置注册表的方法,例如:通过配置文件或类路径扫描(自动查找存在的插件)。但是,编写一些配置注册表的代码也可能就足够了。这一切都取决于你需要摆脱什么样的耦合(解决你面临的问题)以及哪种耦合是可以接受的。