Oop 设计最佳实践-对象是否应该拥有传递给其构造函数的内容?
我有以下课程:Oop 设计最佳实践-对象是否应该拥有传递给其构造函数的内容?,oop,Oop,我有以下课程: public class SqlCeEventStore: EventStore { private EventStoreDB db; public SqlCeEventStore(EventStoreDB db) { this.db = db; } public void Dispose() { db.Dispose(); } } 我的问题是:我在类的Dispose方法中处理EventStoreDB是否正确,因为它是在构造函数中
public class SqlCeEventStore: EventStore
{
private EventStoreDB db;
public SqlCeEventStore(EventStoreDB db)
{
this.db = db;
}
public void Dispose()
{
db.Dispose();
}
}
我的问题是:我在类的Dispose
方法中处理EventStoreDB
是否正确,因为它是在构造函数中传递给它的(因此,可以想象,在我的类被处理后可以重用)
也就是说,如果我处置了它,我要求正确使用我的类:
using (var store = new SqlCeEventStore(new EventStoreDB)){
{
//...
}
但我可以看到正在使用这种替代呼叫:
using (var db = new EventStoreDB())
using (var store = new SqlCeEventStore(db))
{
//...
}
在这种情况下,我不应该从SqlCeEventStore
类中处理EventStoreDB
一种风格或另一种风格有什么论据吗?我想选择一个并坚持它,我不想掷硬币:)如果EventStoreDB属于SqlEventStore(即它的组成部分),那么它应该由SqlEventStore类构造或与SqlEventStore类合并
如果它的使用超出了SqlEventStore生存期的范围,那么它应该由外部代码创建和处理。这里没有通用规则,而且IMHO也不应该有。不同的对象有不同的寿命,最通用的准则是确保根据对象的寿命一致地管理对象,并且寿命尽可能短 您可以尝试使用以下准则(但在需要时不要害怕偏离):在分配对象的同一范围内处置对象。这条准则适用于许多场景,这正是
using
语句所简化的
如果您有长寿命的对象而没有明显的处置点,不要担心。这很正常。然而,问问你自己:我真的需要这个物体像它那样长寿吗?有没有其他方法可以使寿命缩短?如果您能找到另一种缩短寿命的方法,通常会使对象更易于管理,应该是首选方法
但是,这里没有任何“一条真正的规则”。你不能选择一条并坚持它。用户可以随时选择他想要的东西 但是,请记住,作为通过构造函数传递的对象类,您不承担任何责任
笔记 接下来的讨论非常愚蠢,因为
如果您想使用*new-SqlCeEventStore(new-EventStoreDB))*
强制初始化类,那么为什么不删除这个EventStoreDB参数并在构造函数中实例化变量db呢
变通办法
有一个解决方法-请检查以下内容:
public myClass {
//do not make the constructor public //hide it
private myClass(EventStoreDB db){
this.db = db;
}
//make a public constructor that will call the private one in the way you want
public myClass(){
this(myClass(new EventStoreDB()));
}
}
一般来说,这没有规则,但我同意,因为对象是在您的范围之外创建的,并且是传递给您的,所以您不拥有它 如果您已经创建了它,那么您应该有权做任何您想做的事情(记录调用方的预期行为)
这是经典的东西。我建议,如果人们可以合理地想象这样的情况,即构造的对象将是宇宙中对传入对象感兴趣的最后一个对象,以及在构造函数完成后其他事物希望继续使用传入对象的情况,可能需要有一个构造函数参数来指定新对象是否应该拥有传入的对象的所有权
请注意,如果构造的对象将获得传入对象的所有权,那么即使构造函数抛出异常,也必须确保该对象将被释放。一种方法是将构造函数调用包装在例程中,该例程将在“finally”块中处理传入的对象,除非构造函数已成功完成。Ahhh。。。谢谢我必须承认,“组合与聚合”的区别对我来说从来都不清楚。@Marcel:是的,这是一个棘手的定义,不容易理解。你的处境就是看问题的方式。顺便说一句,现在清楚了吗?;)是的,它是:)我将把这个标记为被接受的答案。很好。我更喜欢在构造函数中注入类依赖的对象,因此我不能这样做,但如果没有该规则,您将是正确的。我不喜欢在类中
new
对象,而是在构造函数中传递依赖项。您编写它的方式是有效的,但它使myClass
更难重用。。。如果一个类扩展了你的类,他将不得不使用super,仅此而已(: