我正在创建一个包含多种通用方法的实用工具类CommonDaoOperations
:Create
,Update
,Delete
。
这不是基类,因为一些DAO更复杂,不能使用这些通用方法,但许多DAO都可以。
我现在正在思考这个丑陋的课程应该如何:
每个DAO /方法创建一个类的实例显然比调用静态方法花费更多,但我很确定这些成本在几乎所有应用程序中都是可以忽略的。
我赞成解决方案2或3,因为非静态类的好处(接口,可以被模拟,可以派生/增强,如果有必要,可以在将来通过构造函数收集参数(与10相比) - 静态类中的参数方法))。
所以我想真正的问题是:我应该将我的实用程序类创建为成员变量,还是按照DAO方法实例化它?
public void Create(User user) {
new CommonDaoOperations().Create(user);
}
public void Delete(User user) {
var daoOps = new CommonDaoOperations();
daoOps.CheckSomething(); // just an example of multiple calls to the class
daoOps.Delete(user);
}
我很想知道其他开发者对这些方法的看法,或者是否还有其他/更好的方法来做到这一点。
修改
刚才意识到我应该更多地考虑方法#3 - 正如Vadim指出的那样,当在每个方法中实例化时,替换具体类会很麻烦,但我可以将其考虑在属性中:
private CommonDaoOperations DaoOps {
get { return new CommonDaoOperations(); }
}
public void Create(User user) {
DaoOps.Create(user);
}
我相信这比上面的片段更具有主要性,但是知道我在DAO中引入了一个'实用程序'类的属性,这可能是代码异味(如Ant P指出的那样)。
摘要
这是一个艰难的决定 - 虽然我接受了Ant P的回答,但Vadim的回答也是合法的。使用哪种方法取决于实用程序类,所有3种方法都有其用途(更新后的#3除外)。至少这是我对提供的答案的看法。
答案 0 :(得分:2)
除非您计划创建特别多的这些对象,否则我认为它不会影响性能。
我更愿意(2)。只需要为每次使用创建它,只需编写代码即可。此外,如果您想要使用某种IOC,请将实用程序类作为参数,更改它的初始化方式,或者只是将类更改为另一个类 - 只需要更改一个成员就可以了。改变所有使用它的地方。
除非你有充分的理由,否则请远离静态或单身。 (一个很好的理由就是开发一个插件或插件,你不能控制你的类的初始化和使用方式)。
答案 1 :(得分:2)
我会对性能影响进行更合格的评论;但是,这是我对每个人的看法:
<强> 1。静态类
这个概念适用于简单的,“不全面”的实用方法,它们不需要真正的可扩展性,但是 - 正如您自己记录的那样 - 您的常见DAO操作将变得更加复杂。这不太可能作为单个静态类进行管理,特别是当它用于多种不同类型的DAO时。
<强> 2。具体类,实例化每个DAO对象
这一切都很好,但是你真的需要实用程序类才能成为单个DAO的成员吗?如果你在DAO的生命周期中需要某种实体类中的某种一致性或状态持久性,我可以理解这一点,但似乎这些方法相当含糊不清(因为它的名称是“实用程序”类)。
留下 3。具体类,按方法实例化。这对我来说似乎是最自然的解决方案。这使您可以灵活地利用具体类的所有优点,如您在问题中所承认的那样,同时将对象的范围限制在需要的位置 - 单个方法调用。
您的课程是否应该演变成整个DAO所需的内容,例如:你突然需要维护对象的状态(或者你需要将它注入到DAO的构造函数中,或者沿着这些行注入其他东西),你总是可以改变实例化的位置(虽然在我看来,如果发生这种情况,你不再有实用程序类了,你需要重新考虑这个类如何适合你的架构。)
答案 2 :(得分:1)
在考虑静态类和具体类之间的差异和用法时,确定需要考虑的含义,例如请参阅可测试性(但这不是那么肯定完全如下所示,但首先要做一些假设:
实例类具有状态,管理状态,并且行为与其内部状态相关,如果操作在某些方面与内部状态无关,则这些是静态方法的真正候选者,但在此之后我会说更多。这是封装的基础,并与 SRP (单一责任原则)同时进行,其中一个类应该只有一个责任,做一件事,不做更多,所以,这给了你一个事实,即方法都直接或间接地与它的内部状态相关
静态类没有也没有管理状态。也许有人会说这根本不是真的,看看单身人士。好吧,单身人士可能很好,但设计为静态类的单身人士太靠近反模式,在这种情况下,单身人士可以像IoC容器一样管理,通过管理一个实例。如果需要,我可以提供一些关于有和没有容器的例子。
嗯,有人说静态类是接近反模式的东西,因为例如可测试性......好吧,这是不正确的,这取决于涉及的静态类和测试的相关性。 我将通过伟大的软件架构师 Udi Dahan 报告一个非常好的例子,例如,在一篇关于域事件的好文章中,他谈到了关于静态类和可测试性之间的其他内容,如果您转到如何提升域事件和使用域事件进行单元测试部分,请在此处链接Domain Events Salvation,他谈到了这一点。
在那之后,正如你所说,关于这两者的另一个不同之处在于内存成本,但其他人则对此有所说明。请记住,像Reshaper这样的工具提出了将不处理状态的实例类/方法转换为静态表示的建议,这有利于内存和使用。
关于你的设计的最后一句话:CommonDaoOperations
似乎是一个真正的静态类,它不处理状态,所以它是一个很好的候选者,成为一个静态类,因为它的性质,它的工作。您可以使用IoC容器将其视为“单例”,并以正确的方式配置该类。有很多方法可以在没有容器的情况下以其他方式实现这一点。这里有一篇简单的文章讨论单例和静态类C# Singleton, Static Class。确实制作一个返回帮助器的属性并不是一个好的设计,并且为get操作返回一个新实例的属性总是一个糟糕的设计,它将有充分理由证明......
所以看看你的设计以及你如何使用帮助类,Udi在上面的链接中所说的话很好地描述了你应该实现的解决方案。