在現代軟體架構中,不同型別的類扮演著不同的角色,共同構成了一個清晰、模組化和可維護的系統。以下是對實體類(Entity)、數據傳輸物件(DTO)、領域物件(Domain Object)、持久化物件(Persistent Object)、業務物件(Business Object)、應用物件(Application Object)、資料訪問物件(Data Access Object, DAO)、服務層(Service Layer)和控制器層(Controller Layer)的總體介紹
不同領域作用
POJO (Plain Old Java Object)
定義:POJO 是一個簡單的Java物件,它不繼承任何特定的類或實現任何特定的介面,除了可能實現
java.io.Serializable
介面。它通常用於表示資料,不包含業務邏輯。案例的體現:
UserEntity
類可以看作是一個POJO,因為它主要包含資料欄位和標準的建構函式、getter和setter方法。UserDTO
類也是一個POJO,它用於傳輸資料,不包含業務邏輯。
VO (Value Object)
定義:VO 是一個代表某個具體值或概念的物件,通常用於表示傳輸資料的結構,不涉及複雜的業務邏輯。
VO(View Object)的特點:
展示邏輯:VO通常包含用於展示的邏輯,例如格式化的日期或貨幣值。
用戶界面相關:VO設計時會考慮用戶界面的需求,可能包含特定於檢視的屬性。
可讀性:VO可能包含額外的描述性資訊,以提高用戶界面的可讀性。
實體類(Entity)
作用:代表資料庫中的一個表,是資料模型的實現,通常與資料庫表直接對映。
使用場景:當需要將應用程式的資料持久化到資料庫時使用。
數據傳輸物件(DTO)
作用:用於在應用程式的不同層之間傳輸資料,特別是當需要將資料從服務層傳輸到表示層或客戶端時。
使用場景:進行數據傳輸,尤其是在遠端呼叫或不同服務間的資料交換時。
領域物件(Domain Object)
作用:代表業務領域的一個實體或概念,通常包含業務邏輯和業務狀態。
使用場景:在業務邏輯層處理複雜的業務規則時使用。
持久化物件(Persistent Object)
作用:與資料儲存直接互動的物件,通常包含資料訪問邏輯。
使用場景:執行資料庫操作,如CRUD(建立、讀取、更新、刪除)操作。
業務物件(Business Object)
作用:封裝業務邏輯和業務資料,通常與領域物件互動。
使用場景:在業務邏輯層實現業務需求時使用。
應用物件(Application Object)
作用:封裝應用程式的執行時配置和狀態,通常不直接與業務邏輯相關。
使用場景:在應用程式啟動或執行時配置時使用。
資料訪問物件(Data Access Object, DAO)
作用:提供資料訪問的抽象介面,定義了與資料儲存互動的方法。
使用場景:需要進行資料持久化操作時,作為資料訪問層的一部分。
服務層(Service Layer)
作用:包含業務邏輯和業務規則,協調應用程式中的不同元件。
使用場景:處理業務邏輯,執行業務用例。
控制器層(Controller Layer)
作用:處理使用者的輸入,呼叫服務層的方法,並返回響應結果。
使用場景:處理HTTP請求和響應,作為Web應用程式的前端和後端之間的中介。
案例介紹
使用者註冊:
DTO:使用者註冊資訊的傳輸。
Entity:使用者資訊在資料庫中的儲存形式。
Service Layer:驗證使用者資訊、加密密碼等業務邏輯。
商品展示:
Entity:資料庫中的商品資訊。
DTO:商品資訊的傳輸物件,可能包含圖片URL等不需要儲存在資料庫的欄位。
Service Layer:獲取商品列表、篩選和排序商品等。
訂單處理:
Domain Object:訂單的業務領域模型,包含訂單狀態等。
Business Object:訂單處理的業務邏輯。
DAO:訂單資料的持久化操作。
配置載入:
Application Object:應用程式的配置資訊,如資料庫連線字串。
API響應:
Controller Layer:處理API請求,呼叫服務層,返回DTO作為響應。
案例程式碼
檢視物件(VO)
一個訂單系統,我們需要在用戶界面展示訂單詳情:
// OrderDTO - 數據傳輸物件 public class OrderDTO { private Long id; private String customerName; private BigDecimal totalAmount; // Constructors, getters and setters } // OrderVO - 檢視物件 public class OrderVO { private Long id; private String customerFullName; // 格式化後的顧客姓名 private String formattedTotal; // 格式化後的總金額,如"$1,234.56" private String orderDate; // 格式化後的訂單日期 // Constructors, getters and setters public OrderVO(OrderDTO dto) { this.id = dto.getId(); this.customerFullName = formatName(dto.getCustomerName()); this.formattedTotal = formatCurrency(dto.getTotalAmount()); this.orderDate = formatDateTime(dto.getOrderDate()); } private String formatName(String name) { // 實現姓名格式化邏輯 return name; } private String formatCurrency(BigDecimal amount) { // 實現貨幣格式化邏輯 return "$" + amount.toString(); } private String formatDateTime(Date date) { // 實現日期時間格式化邏輯 return new SimpleDateFormat("yyyy-MM-dd").format(date); } }
實體類(Entity)
package com.example.model; import javax.persistence.*; @Entity @Table(name = "users") public class UserEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false, unique = true) private String username; @Column(nullable = false) private String password; // Constructors, getters and setters public UserEntity() {} public UserEntity(String username, String password) { this.username = username; this.password = password; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
數據傳輸物件(DTO)
package com.example.dto; public class UserDTO { private Long id; private String username; // Constructors, getters and setters public UserDTO() {} public UserDTO(Long id, String username) { this.id = id; this.username = username; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } }
領域物件(Domain Object)
package com.example.domain; public class UserDomain { private Long id; private String username; // Business logic methods public UserDomain() {} public UserDomain(Long id, String username) { this.id = id; this.username = username; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } // Additional domain-specific methods }
領域物件通常包含業務領域內的概念和邏輯。在訂單系統中,這可能包括訂單狀態、訂單項、總價等。
package com.example.domain; import java.util.List; public class OrderDomain { private String orderId; private List<OrderItemDomain> items; // 訂單項列表 private double totalAmount; private OrderStatus status; // 訂單狀態 // Constructors, getters and setters public OrderDomain(String orderId, List<OrderItemDomain> items) { this.orderId = orderId; this.items = items; this.totalAmount = calculateTotalAmount(); this.status = OrderStatus.PENDING; // 預設狀態為待處理 } private double calculateTotalAmount() { double total = 0; for (OrderItemDomain item : items) { total += item.getPrice() * item.getQuantity(); } return total; } // 業務邏輯方法,例如更新訂單狀態 public void processPayment() { // 處理支付邏輯 if (/* 支付成功條件 */) { this.status = OrderStatus.PAYMENT_COMPLETED; } } // 更多業務邏輯方法... }
持久化物件(Persistent Object)
package com.example.model; public class UserPersistent extends UserEntity { // Methods to interact with persistence layer, extending UserEntity }
業務物件(Business Object)
package com.example.service; public class UserBO { private UserDomain userDomain; public UserBO(UserDomain userDomain) { this.userDomain = userDomain; } // Business logic methods public void performBusinessLogic() { // Implement business logic } }
OrderBO
業務物件通常封裝業務邏輯,可能包含領域物件,並提供業務操作的方法。
package com.example.service; import com.example.domain.OrderDomain; public class OrderBO { private OrderDomain orderDomain; public OrderBO(OrderDomain orderDomain) { this.orderDomain = orderDomain; } // 執行訂單處理的業務邏輯 public void performOrderProcessing() { // 例如,處理訂單支付 orderDomain.processPayment(); // 其他業務邏輯... } // 更多業務邏輯方法... }
應用物件(Application Object)
package com.example.config; public class AppConfig { private String environment; private String configFilePath; public AppConfig() { // Initialize with default values or environment-specific settings } // Methods to handle application configuration public void loadConfiguration() { // Load configuration from files, environment variables, etc. } // Getters and setters }
資料訪問物件(Data Access Object)
package com.example.dao; import com.example.model.UserEntity; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface UserDAO extends JpaRepository<UserEntity, Long> { // Custom data access methods if needed UserEntity findByUsername(String username); }
- OrderDAO
DAO 提供資料訪問的抽象介面,定義了與資料儲存互動的方法。在Spring Data JPA中,可以繼承JpaRepository
並新增自定義的資料訪問方法。
package com.example.dao; import com.example.domain.OrderDomain; import org.springframework.data.jpa.repository.JpaRepository; public interface OrderDAO extends JpaRepository<OrderDomain, String> { // 主鍵型別為String // 自定義資料訪問方法,例如根據訂單狀態查詢訂單 List<OrderDomain> findByStatus(OrderStatus status); }
服務層(Service Layer)
package com.example.service; import com.example.dao.UserDAO; import com.example.dto.UserDTO; import com.example.model.UserEntity; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class UserService { private final UserDAO userDAO; @Autowired public UserService(UserDAO userDAO) { this.userDAO = userDAO; } public UserDTO getUserById(Long id) { UserEntity userEntity = userDAO.findById(id).orElseThrow(() -> new RuntimeException("User not found")); return convertToDTO(userEntity); } private UserDTO convertToDTO(UserEntity entity) { UserDTO dto = new UserDTO(); dto.setId(entity.getId()); dto.setUsername(entity.getUsername()); return dto; } // Additional service methods }
OrderService
服務層協呼叫戶輸入、業務邏輯和資料訪問。它使用DAO進行資料操作,並可能使用業務物件來執行業務邏輯。
package com.example.service; import com.example.dao.OrderDAO; import com.example.domain.OrderDomain; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service public class OrderService { private final OrderDAO orderDAO; @Autowired public OrderService(OrderDAO orderDAO) { this.orderDAO = orderDAO; } public List<OrderDomain> findAllOrders() { return orderDAO.findAll(); } public OrderDomain getOrderById(String orderId) { return orderDAO.findById(orderId).orElseThrow(() -> new RuntimeException("Order not found")); } public void processOrderPayment(String orderId) { OrderDomain order = getOrderById(orderId); OrderBO orderBO = new OrderBO(order); orderBO.performOrderProcessing(); // 更新訂單狀態等邏輯... } // 更多服務層方法... }
控制器層(Controller Layer)
package com.example.controller; import com.example.dto.UserDTO; import com.example.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/users") public class UserController { private final UserService userService; @Autowired public UserController(UserService userService) { this.userService = userService; } @GetMapping("/{id}") public UserDTO getUser(@PathVariable Long id) { return userService.getUserById(id); } // Additional controller endpoints }
總結
這些不同型別的類和層共同構成了一個分層的軟體架構,每一層都有其特定的職責和功能。這種分層方法有助於降低系統的複雜性,提高程式碼的可維護性和可擴充套件性。透過將業務邏輯、資料訪問和用戶界面分離,開發人員可以獨立地更新和測試每個部分,從而提高開發效率和應用程式的穩定性。