您的Book 对象是所谓的“域对象”。它唯一的职责就是提供所谓的“业务逻辑”。例如:它有一个由类成员定义的状态,并且它可以包含与状态交互的类方法(用于计算等)。没有其他对象应该知道内部业务逻辑的实现。
现在,域对象也称为“模型”。但这可能有点令人困惑。为什么?因为“模型”实际上是一个层。它由三个子层组成:
因此,在您的情况下,域对象 Book 看起来像这样:
public class Book {
private long ID;
private String details;
public Book() { ... }
// Setters/getters...
}
那么你也会有一个数据映射器 (BookDataMapper):
public class BookDataMapper {
private DbAdapter adapter;
private Set<Book> books;
public BookDataMapper(DbAdapter adapter) {
// Assign DbAdapter object to the adapter class member.
}
public void select(long bookId) {
// 1. Fetch book record from db by bookId and using the injected db adapter.
// 2. Map fetched db record to a Book object using mapBook().
// 3. Add Book object to books using addBook().
}
public void insert(Book book) {
// 1. Read the class members of object book.
// 2. Inject the values in an INSERT SQL statement as parameters.
// 3. Run the INSERT query and return last insert id.
// 4. Assign the last insert id to book's ID class member.
// 4. Return book.
}
public void update(Book book) { ... }
public void delete(Book book) { ... }
public void mapBook(array bookRecord){
// 1. Create a plain Book object.
// 2. Read bookRecord array and map each field to the corresponding
// class member of the Book object.
// 3. Return mapped Book object.
}
public void addBook(Book book){
// Add book to books collection.
}
}
您也可以为数据访问定义更高的抽象层,例如BookRepository。您还可以/应该在其中移动藏书(代码):
public class BookRepository {
private BookDataMapper bookMapper;
public BookRepository(BookDataMapper bookMapper) {
// Assign BookDataMapper object to the bookMapper class member.
}
public void find(long bookId) {
// 1. Use bookMapper to fetch book record from the storage by bookId.
// Notice that I said storage, not db: per definition, a repository
// hides the details regarding the storage type. The user (client)
// knows only that the book is placed... somewhere.
// 2. Return the fetched book object.
}
public void store(Book book) {
// 1. Use bookMapper to store the book.
// 2. Return the book (with last insert id in it).
}
public void update(Book book) { ... }
public void remove(Book book) { ... }
}
最后,定义一个服务 (BookBorrowingService) 来管理用户想从图书馆借书时的图书借阅流程:
public class BookBorrowingService {
private UserCardRepository userCardRepository;
private BookRepository bookRepository;
public BookBorrowingService(UserCardRepository userCardRepository, BookRepository bookRepository) {
// 1. Assign UserCardRepository object to the userCardRepository class member.
// 2. Assign BookRepository object to the bookRepository class member.
}
public void borrowBook(long userCardId, long bookId) {
// 1. Use userCardRepository and the given card id to find the user card.
// 2. Validate the card based on its details. If successfull go further.
// If not, then return corresonding response to user.
// 3. Use bookRepository and the given book id to find the book.
// 4. Return the fetched book object.
}
}
然后,在主体部分将所有部分绑定在一起:
// Create and share db connection(s).
// Create and share adapter(s).
// Create mappers.
// Create repositories.
BookBorrowingService bookBorrowingService = new BookBorrowingService(userCardRepository, bookRepository);
Book book = borrowBook(123, 4567890);
回答您的问题:
以这种方式构建代码的优点是,每个类都有很好的分隔职责,符合Single Responsibility Principle。例如,域对象的职责应该只是业务逻辑,而不是数据访问。所以,简而言之,这个SOLID 原则与您的第一种方法相矛盾。你也可以说发生了separation of concerns。
使用上述方法的唯一缺点是您必须编写更多代码。
注意事项:
- 我不使用 Java 编程。这就是我没有实现更多代码的原因。
- 使用依赖注入容器。
- 忘记静态、全局、单例。
- 使用接口而不是具体实现。
祝你好运!