在构造函数中返回一个新对象或初始化成员变量?

3
我们有一个数据提供程序类,它为数据库中的每个聚合返回存储库。
让我们考虑以下情况:
public class DataProvider {
    public IBookRepository Books { get { retun new BookRepository(); } }
    public IAuthorRepository Authors { get { retun new AuthorRepository(); } }
}

正如您所看到的,每次调用成员 DataProvider.Books.DoBANANAS(); 我们都会返回给定对象的新实例:

与之相反。

public class DataProvider {
    public IBookRepository Books { get; }
    public IAuthorRepository Authors { get; }

    public DataProvider()
    {
        Books = new BookRepository();
        Authors = new AuthorRepository();
    }
}

现在调用 `DataProvider.Books.BANANAS();` 会减少 CPU / 内存的负担吗?

我刚刚实现了两个版本,它们出奇地都工作了!

但我的经验告诉我 版本1很糟糕。然而,我有足够的时间来完全优化和实现最终产品。(这是在研究小组工作的好处之一)


3
这两个例子在语义上并不相同。它们的行为非常不同,不仅在内存使用或速度上有一些细微的差异。我猜您不打算使用第一个例子所做的事情。 - dtb
1
两个版本的行为差异非常大(至少根据你提供的例子),比较这两种做不同事情的解决方案可能不公平。你应该先决定确切的行为和语义,然后再考虑性能(仅在实际问题存在时)。 - Daniel Brückner
2个回答

3
展示的实现方式在构建和管理对象方面有所不同。在第一个示例中,每次在DataProvider上调用属性时都会创建一个新的存储库。如果存储库保存任何状态(例如获取的对象的缓存),则与第二个示例相比,您将获得非常不同的行为,因为每次状态都将重置为其默认值。
从您说两个版本都可以工作的事实来看,我猜测存储库对象不持有状态,只是数据库调用的代理。在这种情况下,它可能没有太大的区别。
然而,这两种方法的性能和内存占用情况非常不同。虽然过早地进行优化是一件坏事,并且通常是浪费时间的,但我不认为这是这样,因为在每次属性调用时创建一个新的存储库显然可能会成为性能问题,或者更糟糕的是,如果您将状态引入存储库,则可能会引入难以跟踪的错误。创建较少的对象最终会对垃圾收集器造成较小的压力,但除非您创建数百万个对象,否则差异将微不足道。
总之,第二个示例是更好的选择,我认为现在没有真正的问题。

谢谢您的回复。您猜对了,我的存储库根本没有保持状态。 另一个问题:将DataProvider设置为“静态”会有什么区别吗? 我不需要每次访问数据库或任何其他提供程序中的数据时都创建和实例化DataProvider。 - Faizan S.
这要看情况。将 DataProvider 设为静态实例可能会使得获取它变得更加容易,但同时也会使得测试变得更加困难。 - adrianbanks
在更深入地研究了该主题之后(因为度假原因,回复晚了),我发现我下意识地试图实现“UnitOfWork”原则。这正是我想要的,经过进一步研究,我发现这正是我正在寻找的东西。再次感谢您的绝佳答案! - Faizan S.

2

第一个示例每次创建一个新的XXXRepository对象实例,而第二个示例返回对已经存在的对象的句柄,因此第二个示例应该执行得更好,并且使用的CPU更少,因为不需要分配新的内存。

更大的问题是,除非存储库类完全是静态的或其他什么东西,否则这2种情况会产生完全不同的结果。如果存储库类是到数据库的某种接口,则选项1不需要是线程安全的,而选项2需要是线程安全的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接