假设有一个图书馆系统,其中包含了三个类:Book(书籍)、Library(图书馆)和User(用户)。其中,Book类表示一本书籍,包含了书名、作者等信息;Library类表示一个图书馆,包含了图书馆的名称、地址等信息,同时还有添加书籍、借出书籍等方法;User类表示一个用户,包含了用户的姓名、电话等信息,同时还有借书、还书等方法。下面给出相应的Java代码:
代码语言:javascript复制public class Book {
private String title;
private String author;
private String publisher;
public Book(String title, String author, String publisher) {
this.title = title;
this.author = author;
this.publisher = publisher;
}
// 省略其他方法和属性的定义
}
public class Library {
private String name;
private String address;
private List<Book> books;
public Library(String name, String address) {
this.name = name;
this.address = address;
this.books = new ArrayList<>();
}
public void addBook(Book book) {
books.add(book);
}
public void lendBook(Book book, User user) {
// 省略借出书籍的具体实现
}
// 省略其他方法和属性的定义
}
public class User {
private String name;
private String phone;
private List<Book> borrowedBooks;
public User(String name, String phone) {
this.name = name;
this.phone = phone;
this.borrowedBooks = new ArrayList<>();
}
public void borrowBook(Book book, Library library) {
// 省略借书的具体实现
}
public void returnBook(Book book, Library library) {
// 省略还书的具体实现
}
// 省略其他方法和属性的定义
}
在上述代码中,Book、Library和User三个类之间的关系比较紧密,它们之间的交互比较频繁,没有遵守迪米特法则。下面对该系统进行重构,使用迪米特法则来设计系统。
首先,我们需要引入一个中间对象,来封装Book和User之间的交互。假设该中间对象命名为Borrow,表示借书记录。Borrow对象包含了借书日期、还书日期等信息。同时,Borrow对象还有一个引用Book对象和User对象,用于表示这本书是由哪个用户借阅的。下面给出Borrow类的定义:
代码语言:javascript复制typescriptCopy codepublic class Borrow {
private Date borrowDate;
private Date returnDate;
private Book book;
private User user;
public Borrow(Book book, User user) {
this.book = book;
this.user = user;
this.borrowDate = new Date();
}
public void returnBook() {
this.returnDate = new Date();
// 省略还书后的其他处理
}
// 省略其他方法和属性的定义
}
在上述代码中,Borrow类作为一个中间对象,负责封装Book和User之间的交互。通过引入Borrow类,Book和User之间的交互就变成了间接交互,而不是直接交互。
接下来,我们需要修改Library和User类,使其通过Borrow对象来进行交互。具体地,Library类在借出书籍时,创建一个新的Borrow对象,将这本书和用户信息保存在Borrow对象中。而User类在借书时,先通过Library对象获取这本书的信息,然后创建一个新的Borrow对象,将这本书和用户信息保存在Borrow对象中。下面给出相应的代码:
代码语言:javascript复制typescriptCopy codepublic class Library {
private String name;
private String address;
private List<Book> books;
private List<Borrow> borrows;
public Library(String name, String address) {
this.name = name;
this.address = address;
this.books = new ArrayList<>();
this.borrows = new ArrayList<>();
}
public void addBook(Book book) {
books.add(book);
}
public void lendBook(Book book, User user) {
// 检查这本书是否可借
if (!books.contains(book)) {
throw new IllegalArgumentException("该图书馆没有这本书!");
}
for (Borrow borrow : borrows) {
if (borrow.getBook().equals(book) && borrow.getReturnDate() == null) {
throw new IllegalArgumentException("这本书已经被借走了!");
}
}
// 创建一个新的借书记录
Borrow borrow = new Borrow(book, user);
borrows.add(borrow);
}
// 省略其他方法和属性的定义
}
public class User {
private String name;
private String phone;
private List<Borrow> borrows;
public User(String name, String phone) {
this.name = name;
this.phone = phone;
this.borrows = new ArrayList<>();
}
public void borrowBook(Book book, Library library) {
library.lendBook(book, this);
}
public void returnBook(Book book, Library library) {
for (Borrow borrow : borrows){
if (borrow.getBook().equals(book) && borrow.getReturnDate() == null) {
borrow.returnBook();
return;
}
}
throw new IllegalArgumentException("你没有借过这本书!");
}
// 省略其他方法和属性的定义
}
在上述代码中,Library类的lendBook方法会创建一个新的Borrow对象,将这本书和用户信息保存在Borrow对象中,并将Borrow对象保存到borrows列表中。而User类的borrowBook方法会调用Library类的lendBook方法来借书,然后创建一个新的Borrow对象,将这本书和用户信息保存在Borrow对象中,并将Borrow对象保存到borrows列表中。User类的returnBook方法会遍历borrows列表,查找用户借阅的这本书对应的Borrow对象,并调用Borrow对象的returnBook方法来还书。
通过引入Borrow对象,Book和User之间的交互变成了间接交互,而不是直接交互。这样可以降低类之间的耦合度,提高系统的灵活性和扩展性。此外,Borrow对象还可以承担其他职责,例如记录借书日期和还书日期等信息,方便图书馆管理借阅记录。