我正在空闲时间在一个简单的数据存储项目中使用它来围绕工厂模式。我们的想法是使用简单的数据并使用VB.NET中的简单工厂模式将其保存到数据库中。我认为我对模式本身有一个基本的了解,然而,我正在努力的是如何干净地将工厂类融入到体系结构中。我对这个项目有一个标准的3层架构,看起来基本上是这样的:
演示
-Presentation.Common
-Presentation.DataStorageWebAppName
商业
-BusinessLayer.Common
-BusinessLayer.DataStorageAppName
数据
-DataLayer.Common
-DataLayer.DataStorageAppName
通用
-Common
-Common.DataStorageAppName
接口
-Interfaces.Common
-Interfaces.DataStorageAppName
为了突出显示我在设计应用程序时遇到问题的特定情况,让我举一个例子。假设在业务层中,我在名为Foo的BusinessLayer.DataStorageAppName DLL中创建了一个类。它有一个接口,IFoo,它位于Interfaces.DataStorageAppName DLL中。要使用简单的工厂模式通过它的接口IFoo创建类Foo的实例,现在,我在BusinessLayer.DataStorageAppName中创建一个Factory类,并编写一个共享/静态方法来通过IFoo接口给我一个实例。后来,据我所知,我可以决定换掉这个Factory类返回的对象而不必做其他事情(理论上)。
为了达到目的,这是有效的,但看起来很有趣的是我现在被迫创建了几个Factory类:基本上每个DLL一个,这样我就可以避免循环引用了。有没有一种更简洁的方法来实现这些工厂类,而不需要使用第三方解决方案,如城堡windsor等等。似乎我在这里缺少一个基本概念。在负责分发对象实例的体系结构中,似乎应该可以拥有一个“存储库”,如果你愿意的话。
提前谢谢!
答案 0 :(得分:1)
我采取了一种更简单的方法。我定义了一个Entity类,我有一个生成实体列表的工厂(List< Entity>)。我告诉工厂我想要取回什么类型,它假定类型为表,属性为列,生成sql,获取数据,填充类型的新实例列表。
工厂还可以接收Entity对象并使用反射来更新其在数据库中的值。
现在我唯一需要做的就是为给定的数据库创建一组Entity类,BTW也是数据传输对象。
答案 1 :(得分:1)
为什么你的IFoo实现和返回它的工厂方法不能存在于BusinessLayer的单独程序集中(因此你可以从所有客户端程序集中引用这个新程序集)?如果有原因,是否有可能在BusinessLayer中定义IFoo(因此不需要引用接口程序集)?
如果您的界面确实需要可以从业务层以外访问,并且实现确实依赖于业务层,那么您需要查看的内容不仅仅是工厂方法。您可以使用控制/依赖注入反转的一些原则来更好地分离关注点。
[编辑以回应O.P.的后续回答] IMO的工厂方法不足以被视为IoC方法。最好的方法是封装特定实现的构造,在多个地方重用或简单地用于sweep it under the rug。对我来说缺少的是依赖性的破坏:因为你的工厂方法生活在与调用它相同的程序集中,为了更改返回的具体类型,你需要重新编译。考虑以下两者之间的区别:
public class FooConsumer1
{
public void DoStuff()
{
IFoo myFoo = new Foo();
myFoo.Bar();
}
}
和
public class FooConsumer2
{
public void DoStuff()
{
IFoo myFoo = FooFactory.getFoo();
myFoo.Bar();
}
}
public class FooFactory
{
public static IFoo GetFoo()
{
return new Foo();
}
}
第二个优点是,如果您在多个地方创建一个IFoo,那么在创建SuperFoo类来替换Foo时,只有一个地方可以更改它。此外,只有一个地方放置逻辑,如果它将以某种方式动态决定两个实现之间。另一个优点是,如果构造函数复杂/丑陋,或需要一些额外的代码来查找配置设置等,那么它会隐藏所有远离使用它的方法。
然而,这些都不是(至少在我看来)帮助你打破这个方法与它使用的具体实现之间的依赖关系。
答案 2 :(得分:0)
如果他们处理不同的问题,那么拥有几个工厂类并不一定非常时髦。我建议不要使用静态工厂方法,而是创建您使用的工厂的实例。然后工厂自己可以实现接口,也许一些功能消失了。