本文将在 Java 中实现 Hexagonal Architecture 的基本概念。
六边形 架构 :
六边形架构是一种用于设计软件的架构模式。它旨在创建以核心业务逻辑或领域为中心的松散耦合的可互换软件组件。
原则:
在六边形架构中,应用程序包含三个部分:
用户端:
这是用户或任何外部应用程序与应用程序交互的部分。换句话说,应用程序的用户界面。 这部分的例子:
在这里,我们有调用业务流程的参与者。所以这是应用程序的驱动方面。
业务逻辑:
这部分构成了应用程序的核心。它为来自用户界面的请求提供服务。根据请求,它执行一些特定的逻辑,请求逻辑所需的资源,最后将预定义的响应发送回用户界面。定义业务逻辑的主要组件是:
服务器端:
这一面由支持业务逻辑的服务组成。它们中的每一个都有特定的用途,并为业务逻辑层提供资源/数据。 这部分的例子:
所以,在这里,我们有由业务逻辑驱动的参与者。
松耦合和互换性:
现在我们已经了解了系统的基本部分,我们深入研究了部分之间的耦合。到目前为止,我们知道:
因此,只要用户端和交互者之间的契约是固定的,用户端的任何参与者,无论是命令行还是 HTTP API 控制器,都可以调用相同的业务流程。类似地,业务逻辑可以从任何类型的数据源或服务接收实体,只要数据源实现存储库中列出的相同方法即可。换句话说,这些通信必须有一个固定的合同。
在 Java 中,这些合约是使用接口实现的。因此,我们已经可以得出结论,存储库只不过是接口。虽然,用户端可以轻松地从 Interactor 或 Service 类调用方法,而无需 Interactor 类实现接口。但是 Interactor 类可以有其他用户端不应该知道的方法。
总而言之,用户端通过业务逻辑中定义的接口来驱动业务逻辑。业务逻辑通过同样在业务逻辑中定义的接口驱动服务器端。
在六边形架构中,我们称接口为ports。
但是,来自用户端和服务器端的不同参与者有不同的技术实现和数据格式。因此,这些参与者必须调整他们的数据格式和逻辑以从端口或接口调用方法。这就是为什么它们在六边形架构中也被称为适配器。
因此,六边形架构有时被称为端口和适配器架构。
Java 中的示例:
为了理解上述原理,我们将以一个将书籍列表写入标准控制台的命令行应用程序为例。为此,应用程序将在外部文件系统中搜索书籍。组件如下图所示。
让我们实现应用程序的不同方面:
1、业务逻辑或领域:
这是我们的Book 实体:
public class Book {
private int id;
private String name;
private String author;
public Book(int id, String name, String author) {
this.id = id;
this.name = name;
this.author = author;
} // getter 和 setter
}
接口/端口:这是我们的接口:
图书服务:
public IBookService {
List getBookList();
}
书库:
public BookRepository {
List getAllBooks ();
}
交互器或服务类。我们将其称为BookService:
public BookService implements IBookService {
private BookRepository bookRepository; 公共 BookService(BookRepository bookRepository) {
this.bookRepository = bookRepository;
} @Override
public List getBookList() {
return bookRepository.getAllBooks();
}
}
用户端:
这是我们的 ConsoleAdapter。我们将其称为BookConsoleUI:
public class BookConsoleUI {
private IBookService bookService;
public BookConsoleUI(IBookService bookService) {
this.bookService = bookService;
}
public void showBooks() {
List books = bookService.getBookList();
printBooksToConsole(books);
} public void printBooksToConsole(List books) {
// 将书籍打印到控制台的逻辑在这里
}
}
服务器端:
这是我们的文件适配器。我们将其称为FileDataSource:
public FileDataSource implements BookRepository {
@Override
public List getAllBooks() {
return getBooksFromFile().stream()
.map(this::mapBookStringToBook)
.collect(Collectors.toList());
}
public List getBooksFromFile() {
// 从文件中读取图书数据的代码放在这里
}
private Book mapBookStringToBook(String bookString) {
String[] bookDetails = bookString.split(";");
return new Book(Integer.parseInt(bookDetails[0]), bookDetails[1], bookDetails[2]);
}
}
一切都放在一起:
让我们看看如何将应用程序的每一端连接在一起:
// 实例化 FileAdapter
FileDataSource fileDataSource = new FileDataSource();
// 将数据源插入 Interactor
BookService bookService = new BookService(fileDataSource);
// 将交互器或服务插入 ConsoleUI
BookConsoleUI userInterface = new BookConsoleUI(bookService);
// 通过用户界面驱动业务逻辑
userInterface.showBooks();
在这里,我们可以看到,如果我们想要交换数据源,我们只需要实例化该数据源并将其插入 BookService,因为 BookService 将 BookRepository 的引用作为其构造函数参数。
我们看到了如何在 Java 中轻松实现六边形架构的基本方面。该示例的代码可在 GitHub 上 获得。