【问题标题】:Placing methods to retrieve data related to a class in a separate class or not将检索与某个类相关的数据的方法放在单独的类中或不放置
【发布时间】:2012-12-09 14:32:28
【问题描述】:

考虑以下简化的类:

class Book {
   string title;
   Author author;
}

足够简单。但是,当添加像getBookFromDatabase(int bookId) 这样的方法时,应该将其作为static 方法放在同一个类中,而不是单独(即)BookManager-class

使用示例:

Book b = Book.getBookFromDatabase(42);

对比

Book b = BookManager.getBookFromDatabase(42);

我确实意识到这在某种程度上是一个口味问题,但是遵循 OOP 准则的最佳方法是什么?

【问题讨论】:

    标签: c# java oop coding-style


    【解决方案1】:

    我更喜欢使用Repository 从后备存储中重新水化对象。以下内容可能是一个很好的起点。

    public interface IBookRepository{
        Book Load(int id);
        void Save(Book book);
    } 
    

    通过这种方式,您可以拥有多个不同的存储库实现,而不必依赖于使用数据库。例如,您可能有一个可用于测试的 InMemoryBookRepository 和一个用于类似生产环境的 DatabaseBookRepository

    在风格上,我也会避免使用静态方法,例如:

    BookManager.getBookFromDatabase(42);
    

    测试更难,生成的代码更紧密地耦合在一起,这将使测试和更改变得更加困难。

    您可以查看StackOverflow question,了解在哪里可以了解有关实施存储库的更多信息。 MicrosoftMartin Fowler 也更详细地描述了它。

    【讨论】:

      【解决方案2】:

      就个人而言,我喜欢“Manager”类方法。它分离了逻辑,因此Book 不必知道如何获取自身。此外,BookManager 在这里可以是单例 - 直到实际需要获取 Book 时才被实例化。

      此外,BookManager 可以执行额外的簿记任务(没有双关语),例如缓存,或者可能有一些 Book 事件需要在全局级别订阅。

      【讨论】:

        【解决方案3】:

        我相信使用单独的类会更好。这可能是 BookManager,但也许有更适合图书馆或书店之类的工作的东西。该对象应包含对数组或 ArrayList 中书籍的引用(我建议使用 ArrayList),如下所示:

        public class BookManager {
            ArrayList<Book> books = new ArrayList<Book>();
        
            public Book getBook(int index) {
                return books.get(index);
            }
        
            public void addBook(Book book) {
                books.add(book);
            }
        }
        

        【讨论】:

          【解决方案4】:

          这取决于。

          如果您的所有Book 类的行为都是存储从数据库中检索的字段,那么您可能更简单地添加从数据库中获取数据的行为,即同一类上的getBookFromDatabase(int bookId),因为所有的班级都关心从数据库中检索一本书并将其连贯地呈现给程序的其余部分。

          但是,如果您打算让您的 Book 类具有其他行为,也许是特定于您的应用程序的某些 Book 业务逻辑,那么将 业务逻辑持久化逻辑

          这里的指导启发式应该是Single Responsibility Principle,关于它的还有plenty of other questions on stackoverflow

          另外请记住,在单独但相关的注释中,static methods are death to testability

          【讨论】:

            【解决方案5】:

            您的两种方法都使用本质上非 OOP 的静态方法。最好的解决方案是拥有一个BookDatabase 对象,并且该对象应授予对其包含的书籍的非静态访问权限。

            这将解决静态方法带来的问题。例如,如果您将来有两个或更多 BookDatabases 怎么办?使用静态方法,这会变得混乱。使用数据库对象,您只需拥有更多此类(或子类)的实例来处理不同的数据库。

            【讨论】:

              【解决方案6】:

              我假设您的 Book 类是域/业务类,因此将从数据库中检索数据的责任放在类本身上,您正在创建数据库和业务层之间的高度耦合,这与良好设计的原则。

              我会推荐你​​阅读http://en.wikipedia.org/wiki/GRASP_(object-oriented_design)

              如果您愿意,请获取一份

              应用 UML 和模式:面向对象分析、设计和迭代开发简介 - Craig Larman 着 ISBN13:978-0131489066

              这本书是最受欢迎的软件开发书籍之一,强烈推荐。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2012-05-22
                • 2010-09-27
                相关资源
                最近更新 更多