一、什麼是洋蔥架構
洋蔥架構(Onion Architecture)是由Jeffrey Palermo提出的一種軟件架構模式,用於實現可擴展、可維護和可測的應用程序。
它的基本思想是將應用程序分為多個層,每個層都依賴於下一層,並通過依賴注入實現。
這種層次結構就像一個洋蔥,每一層都像是裹在洋蔥外層的一層,通過不斷向內擴展,就能構建出一個穩定、可擴展的應用程序架構。
二、洋蔥架構的結構
洋蔥架構可以分為四個主要的層:
1. UI層
UI層是應用程序的用戶接口部分,可以是Web應用、桌面應用或移動設備應用。
UI層負責與用戶交互,接收用戶輸入,向外部系統顯示信息、狀態等。但它並不負責任何業務邏輯,它只是將請求轉發給下一層。
2. 應用程序層
應用程序層包含應用程序的業務邏輯和應用程序流程。它接收由UI層傳遞過來的請求,將數據處理後傳遞到下一層。
應用程序層中的方法需要具備可復用性,它們應該是獨立的,這樣可以在其它應用程序中重複使用。
3. 領域層
領域層定義了業務邏輯和實體。它是業務處理的核心,包含了業務邏輯的實現代碼。
領域層的主要作用是封裝所有與業務相關的代碼,並對外表現出一套乾淨、簡單的接口。因此它需要與具體的技術實現解耦,以便於將來的維護和替換。
4. 基礎設施層
基礎設施層提供了應用程序所需的所有支持,例如數據庫、文件系統、網絡連接和郵件等。
基礎設施層負責將領域層和外部系統連接起來,它是業務邏輯和外部系統之間的橋樑,為領域層提供必要的支持。
三、洋蔥架構的優點
洋蔥架構的優點主要有以下幾點:
1. 可擴展性
由於每個層都是獨立的,它們之間的耦合很鬆散,容易擴展。可以在每個層中添加更多的組件或邏輯,而不影響其它層的功能。
2. 可測試性
洋蔥架構可以很容易地進行單元測試、集成測試和功能測試,因為每個層都是可測試的。
3. 可維護性
由於業務邏輯封裝在領域層中,所以更容易進行維護、修復和升級。
4. 可重用性
由於每個層都是獨立的,因此它們可以在多個項目中重複使用。
四、示例代碼
1. 用戶服務接口
public interface IUserService
{
bool ValidateUserCredentials(string username, string password);
User GetUserById(int id);
IEnumerable GetAllUsers();
void CreateUser(User user);
}
2. 用戶服務實現
public class UserService : IUserService
{
private readonly IUserRepository userRepository;
public UserService(IUserRepository userRepository)
{
this.userRepository = userRepository;
}
public bool ValidateUserCredentials(string username, string password)
{
return userRepository
.GetUserByUsername(username)?
.Password
.Equals(password) ?? false;
}
public User GetUserById(int id)
{
return userRepository.GetUserById(id);
}
public IEnumerable GetAllUsers()
{
return userRepository.GetAllUsers();
}
public void CreateUser(User user)
{
userRepository.CreateUser(user);
}
}
3. 用戶倉儲接口
public interface IUserRepository
{
User GetUserById(int id);
IEnumerable GetAllUsers();
void CreateUser(User user);
User GetUserByUsername(string username);
}
4. 用戶倉儲實現
public class UserRepository : IUserRepository
{
private readonly ApplicationDbContext context;
public UserRepository(ApplicationDbContext context)
{
this.context = context ?? throw new ArgumentNullException(nameof(context));
}
public User GetUserById(int id)
{
return context.Users.FirstOrDefault(u => u.Id == id);
}
public IEnumerable GetAllUsers()
{
return context.Users.ToList();
}
public void CreateUser(User user)
{
context.Users.Add(user);
context.SaveChanges();
}
public User GetUserByUsername(string username)
{
return context.Users.FirstOrDefault(u => u.Username.Equals(username, StringComparison.OrdinalIgnoreCase));
}
}
5. 控制器
[ApiController]
public class UserController : ControllerBase
{
private readonly IUserService userService;
public UserController(IUserService userService)
{
this.userService = userService;
}
[HttpPost]
[Route("api/users")]
public IActionResult CreateUser([FromBody] CreateUserRequest request)
{
var user = new User { Username = request.Username, Password = request.Password };
userService.CreateUser(user);
return Ok();
}
[HttpGet]
[Route("api/users")]
public IActionResult GetAllUsers()
{
var users = userService.GetAllUsers();
var userDtos = users.Select(u => new UserDto { Id = u.Id, Username = u.Username });
return Ok(userDtos);
}
[HttpGet]
[Route("api/users/{id}")]
public IActionResult GetUserById(int id)
{
var user = userService.GetUserById(id);
var userDto = new UserDto { Id = user.Id, Username = user.Username };
return Ok(userDto);
}
[HttpPost]
[Route("oauth/token")]
public IActionResult GetToken([FromBody] GetTokenRequest request)
{
if (userService.ValidateUserCredentials(request.Username, request.Password))
{
return Ok(new { AccessToken = "dummyAccessToken" });
}
else
{
return Unauthorized();
}
}
}
原創文章,作者:CQCRV,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/334551.html
微信掃一掃
支付寶掃一掃