正确实现依赖注入的一种方法是将对象创建与业务逻辑分开.通常,这涉及使用Factory进行对象创建.
到目前为止,我从未认真考虑过使用工厂,所以如果这个问题看起来有点简单,我会道歉:
在我遇到的工厂模式的所有示例中,我总是看到没有参数化的非常简单的示例.例如,这是一个工厂从Misko Hevery偷来的优秀如何思考"新"操作员文章.
class ApplicationBuilder { House build() { return new House(new Kitchen( new Sink(), new Dishwasher(), new Refrigerator()) ); } }
但是,如果我希望我建造的每个房子都有名字,会发生什么?如果我按如下方式重新编写此代码,我还在使用工厂模式吗?
class ApplicationBuilder { House build( const std::string & house_name) { return new House( house_name, new Kitchen(new Sink(), new Dishwasher(), new Refrigerator()) ); } }
请注意我的Factory方法调用已更改为:
ApplicationBuilder builder; House * my_house = builder.build();
对此:
ApplicationBuilder builder; House * my_house = builder.build("Michaels-Treehouse");
顺便说一句:我认为将对象实例化与业务逻辑分离的概念很棒,我只想弄清楚如何将它应用于我自己的情况.令我困惑的是,我看到的Factory模式的所有示例都没有将任何参数传递给build()函数.
要清楚:在我需要实例化它之前,我不知道房子的名称.
我已经看过很多使用一组固定参数的例子,比如你的名字示例,并且我自己也使用过它们,我看不出它有什么问题.
但是有很多理由说很多教程或小文章都避免显示工厂将参数转发给构造的对象:实际上不可能转发任意数量的参数(即使是像6个参数这样的理智限制).您转发的每个参数都必须被接受const T&
,T&
如果您想要通用它.
但是,对于更复杂的示例,您需要一组指数增长的重载(对于每个参数,const和非对象版本),并且根本不可能完美转发(例如,临时转发为临时转发).对于下一个解决问题的C++标准:
class ApplicationBuilder { templateHouse *build( T&&... t ) { return new House( std::forward (t)..., new Kitchen(new Sink(), new Dishwasher(), new Refrigerator()) ); } };
那样,你可以打电话
builder.build("Hello", 13);
它会回来
new House("Hello", 13, new Kitchen(new Sink(...
阅读我上面链接的文章.
我不明白为什么将这个参数添加到你的工厂是错误的.但请注意,您最终不应添加许多参数,这些参数可能对工厂创建的所有对象都没有用.如果你这样做,你将失去很多工厂的优势!
不仅可以接受,而且将参数传递给工厂方法也很常见.看看一些例子.通常,参数是告诉工厂要做什么的类型,但是没有理由不能添加构建对象所需的其他信息.我觉得你做的很好.