我们的应用程序大量使用工厂来吐出对象,但我常常想知道它们是否总是非常必要,并且创建一个“已知对象”的实例作为bean并不是更好。争论的焦点是开发人员经常自定义这些返回对象的实现(这些对象以其接口类型返回),并且由于我们在技术上并不“确切”知道我们得到的内容,因此最好使用工厂。我正处于需要创建工厂的地步,这需要接口,类实现,然后是工厂。我的目标不会改变 - 它确实是一个具有特定目的的具体对象......我不应该只是实例化一个获取并设置状态的bean吗?我试图避免过早的泛化。
答案 0 :(得分:3)
工厂或依赖注入解决方案的整个目的是减少客户端与对象的运行时类型之间的耦合。确实,客户端必须知道接口和数据源,但现在源可以自由返回实现接口的任何类型。它还允许您将运行时类型的知识封装在一个地方 - 只有工厂或依赖注入解决方案需要知道。
在生成运行时代理以实现声明性事务时,这很有用。从客户的角度来看,他们正在处理界面。工厂可以生成管理客户端事务的代理。
一旦键入“new”,客户端就会在运行时使用编译类型。更改它意味着更改客户端。如果你有很多地方在你的代码中称为“new”,这可能是一个维护问题。
我什么时候打电话给“新”?我认为在一个方法中适当地实例化当它们超出范围时将被GC化的本地对象。该方法创建它们,使用它们,然后它们就完成了。我不会在那里使用工厂或DI解决方案。
也许你应该关闭你的工厂并考虑像Spring,Guice或PicoContainer这样的依赖注入解决方案。
答案 1 :(得分:2)
有一个工厂方法暗示 - 但并不总是意味着 - 该对象没有公共默认构造函数。这个想法是,如果有一个工厂方法(例如),你不应该绕过它并直接创建一个。
在最简单的情况下,没有理由使用公共构造函数而不是返回新对象的公共静态方法,并且该对象只有私有/受保护的构造函数。
话虽如此,有些情况下您需要拥有公共默认构造函数,或者不使用它们非常不方便。示例包括使用Spring的BeanWrapper。某些方法需要默认构造函数。使用JavaBeans接口需要它。没有它,反射可能很尴尬(这是前两个原因的一部分),等等。
在那些情况下,除非您的工厂返回一个接口并且该类实现了接口,否则拥有工厂可能没什么价值。然后,还可以说,大多数(如果不是全部)返回类型(和参数类型)应该是接口而不是类,但这是一个完全独立的参数。
拥有工厂的另一个潜在缺点是它可能会降低可测试性,因为工厂可能会产生依赖或修改某种形式的外部状态的恼人倾向。这不一定是这种情况,但是,例如,这段代码:
Calendar cal = Calendar.getInstance();
VS
Calendar cal = new GregorianCalendar();
根据本地化/国际化,会有不同的结果。