Theo mô tả về MVP của Martin Fowler ( http://martinfowler.com/eaaDev/uiArchs.html )
Về phần View của MVC, Fowler nói:
Yếu tố đầu tiên của Potel là coi chế độ xem như một cấu trúc của các widget, các widget tương ứng với các điều khiển của mô hình Biểu mẫu và Điều khiển và loại bỏ mọi phân tách chế độ xem / điều khiển. Quan điểm của MVP là một cấu trúc của các vật dụng này. Nó không chứa bất kỳ hành vi nào mô tả cách các vật dụng phản ứng với tương tác của người dùng .
(Tôi nhấn mạnh đậm)
Sau đó của người trình bày:
Phản ứng tích cực đối với hành động của người dùng sống trong một đối tượng người trình bày riêng biệt. Các trình xử lý cơ bản cho các cử chỉ của người dùng vẫn tồn tại trong các tiện ích, nhưng các trình xử lý này chỉ đơn thuần chuyển quyền kiểm soát cho người trình bày .
Người trình bày sau đó quyết định cách phản ứng với sự kiện này. Potel thảo luận về sự tương tác này chủ yếu về mặt hành động trên mô hình, được thực hiện bởi một hệ thống các lệnh và lựa chọn. Một điều hữu ích cần làm nổi bật ở đây là cách tiếp cận đóng gói tất cả các chỉnh sửa cho mô hình trong một lệnh - điều này cung cấp một nền tảng tốt để cung cấp hành vi hoàn tác / làm lại.
(Một lần nữa, tôi nhấn mạnh đậm)
Vì vậy, theo hướng dẫn của Fowler, Chế độ xem của bạn không chịu trách nhiệm cho bất kỳ hành vi nào phản ứng với sự kiện nút; trong đó bao gồm việc tạo một thể hiện của UserInfo
. Trách nhiệm quyết định tạo một đối tượng thuộc về phương thức Người trình bày mà sự kiện UI được chuyển tiếp.
Tuy nhiên, người ta cũng có thể lập luận rằng trình xử lý sự kiện nút của View cũng không chịu trách nhiệm truyền nội dung của bạn textView
, vì Chế độ xem chỉ nên chuyển tiếp sự kiện nút vào Người thuyết trình và không có gì nữa.
Với MVP, chế độ xem phổ biến để thực hiện giao diện mà người trình bày có thể sử dụng để nhận dữ liệu trực tiếp từ chế độ xem (trong khi đảm bảo người trình bày vẫn không tin vào chế độ xem). Vì UserInfo là một POJO đơn giản, nên có thể hợp lệ cho chế độ xem để hiển thị một getter cho UserInfo mà Người trình bày có thể nhận được từ Chế độ xem qua giao diện.
// The view would implement IView
public interface IView {
public UserInfo GetUserInfo();
}
// Presenter
public class AddUserPresenter {
private IView addUserView;
public void SetView(IView view) {
addUserView = view
}
public void onSomethingClicked() {
UserInfo userInfo = addUserView.GetUserInfo();
// etc.
}
}
Làm thế nào khác nhau để chuyển UserInfo
trực tiếp vào chế độ xem bằng trình xử lý sự kiện? Sự khác biệt chính là người trình bày cuối cùng vẫn chịu trách nhiệm về logic khiến cho một UserInfo
đối tượng được tạo ra. tức là sự kiện đã đến với Người trình bày trước khi tạo ra UserInfo
, cho phép Người trình bày đưa ra quyết định.
Hãy tưởng tượng một kịch bản mà bạn có logic của người thuyết trình nơi bạn không muốn nó UserInfo
được tạo ra dựa trên một số trạng thái trong chế độ xem. Ví dụ: nếu người dùng chưa đánh dấu vào hộp kiểm trên chế độ xem hoặc bạn đã kiểm tra xác thực đối với một số trường được thêm vào UserInfo không thành công - người thuyết trình của bạn có thể chứa một kiểm tra bổ sung trước khi gọi GetUserInfo
- tức là
private boolean IsUsernameValid() {
String username = addUserView.GetUsername();
return (username != null && !username.isEmpty());
}
public void onSomethingClicked() {
if (IsUsernameValid()) {
UserInfo userInfo = addUserView.GetUserInfo();
// etc.
}
}
Logic đó vẫn còn bên trong người trình bày và không cần phải thêm vào chế độ xem. Nếu khung nhìn chịu trách nhiệm gọi GetUserInfo()
thì nó cũng sẽ chịu trách nhiệm cho bất kỳ logic nào xung quanh việc sử dụng nó; đó là những gì mô hình MVP đang cố gắng tránh.
Vì vậy, trong khi phương thức tạo ra UserInfo
có thể tồn tại về mặt vật lý trong lớp View, nó không bao giờ được gọi từ lớp View, chỉ từ Người trình bày.
Tất nhiên, nếu việc tạo UserInfo
kết thúc yêu cầu kiểm tra bổ sung đối với nội dung của các tiện ích nhập liệu của người dùng (ví dụ: chuyển đổi chuỗi, xác thực, v.v.), thì tốt hơn là nên hiển thị các getters riêng cho những điều đó để có thể thực hiện chuyển đổi chuỗi / xác thực đặt trong Người trình bày - và sau đó người trình bày tạo của bạn UserInfo
.
Nhìn chung, mục tiêu chính của bạn liên quan đến sự tách biệt giữa Người trình bày / Chế độ xem là đảm bảo rằng bạn không bao giờ cần phải viết logic trong chế độ xem. Nếu bạn thấy mình cần thêm một if
câu lệnh vì bất kỳ lý do gì (ngay cả khi đó là một if
câu lệnh liên quan đến trạng thái của một thuộc tính widget - kiểm tra một hộp văn bản trống hoặc boolean cho một hộp kiểm), thì nó thuộc về người trình bày.
onSomethingClicked()
, vì vậy khi người dùng nhấp vào "cái gì đó", View sẽ gọipresenter.onSomethingClicked()
? Hoặc phương pháp người trình bày của tôi nên được đặt tên là hành động dự định, trong trường hợp của tôiaddUser()
?