Không có hướng dẫn thiết kế thường được thống nhất (ví dụ: defacto ) cho MVC. Nó không hoàn toàn khó để tự làm điều đó nhưng đòi hỏi một số kế hoạch về các lớp học của bạn và rất nhiều thời gian và sự kiên nhẫn.
Lý do không có giải pháp xác định là vì có nhiều cách để làm MVC, tất cả đều có ưu và nhược điểm của chúng. Vì vậy, hãy thông minh về nó và làm những gì phù hợp với bạn nhất.
Để trả lời câu hỏi của bạn, bạn thực sự cũng muốn tách bộ điều khiển khỏi chế độ xem (vì vậy bạn có thể sử dụng cùng logic quy tắc kinh doanh cho cả ứng dụng Swing và trong ứng dụng bảng điều khiển). Trong ví dụ Xoay, bạn muốn tách bộ điều khiển khỏi JWindow
và bất kỳ tiện ích nào trong Xoay. Cách tôi thường làm (trước khi sử dụng khung thực tế) là tạo giao diện cho chế độ xem mà bộ điều khiển sử dụng:
public interface PersonView {
void setPersons(Collection<Person> persons);
}
public class PersonController {
private PersonView view;
private PersonModel model;
public PersonController(PersonView view, PersonModel model) {
this.view = view;
this.model = model;
}
// ... methods to affect the model etc.
// such as refreshing and sort:
public void refresh() {
this.view.setPersons(model.getAsList());
}
public void sortByName(boolean descending) {
// do your sorting through the model.
this.view.setPersons(model.getSortedByName());
}
}
Đối với giải pháp này trong quá trình khởi động, bạn cần đăng ký bộ điều khiển vào khung nhìn.
public class PersonWindow extends JWindow implements PersonView {
PersonController controller;
Model model;
// ... Constructor etc.
public void initialize() {
this.controller = new PersonController(this, this.model);
// do all the other swing stuff
this.controller.refresh();
}
public void setPersons(Collection<Person> persons) {
// TODO: set the JList (in case that's you are using)
// to use the given parameter
}
}
Thay vào đó, có thể là một ý tưởng tốt để tạo một IoC-container để thực hiện tất cả các thiết lập cho bạn.
Dù sao đi nữa, bằng cách này bạn có thể thực hiện các chế độ xem chỉ dành cho bảng điều khiển, sử dụng cùng các bộ điều khiển:
public class PersonConsole implements PersonView {
PersonController controller;
Model model;
public static void main(String[] args) {
new PersonConsole().run();
}
public void run() {
this.model = createModel();
this.controller = new PersonController(this, this.model);
this.controller.refresh();
}
public void setPersons(Collection<Person> persons) {
// just output the collection to the console
StringBuffer output = new StringBuffer();
for(Person p : persons) {
output.append(String.format("%s%n", p.getName()));
}
System.out.println(output);
}
public void createModel() {
// TODO: create this.model
}
// this could be expanded with simple console menu with keyboard
// input and other console specific stuff
}
Phần thú vị là làm thế nào để xử lý sự kiện. Tôi đã thực hiện điều này bằng cách cho phép khung nhìn tự đăng ký với bộ điều khiển bằng giao diện, điều này được thực hiện bằng cách sử dụng mẫu Observer (nếu bạn đang sử dụng .NET, bạn sẽ sử dụng trình xử lý sự kiện thay thế). Dưới đây là một ví dụ về "trình quan sát tài liệu" đơn giản, báo hiệu khi tài liệu đã được lưu hoặc tải.
public interface DocumentObserver {
void onDocumentSave(DocModel saved);
void onDocumentLoad(DocModel loaded);
}
// in your controller you implement register/unregister methods
private List<DocumentObserver> observers;
// register observer in to the controller
public void addObserver(DocumentObserver o) {
this.observers.add(o);
}
// unregisters observer from the controller
public void removeObserver(DocumentObserver o) {
this.observers.remove(o);
}
public saveDoc() {
DocModel model = model.save();
for (DocumentObserver o : observers) {
o.onDocumentSave(model);
}
}
public loadDoc(String path) {
DocModel model = model.load(path);
for (DocumentObserver o : observers) {
o.onDocumentLoad(model);
}
}
Bằng cách đó, chế độ xem có thể tự cập nhật chính xác vì nó đang đăng ký các bản cập nhật tài liệu. Tất cả những gì phải làm là thực hiện DocumentObserver
giao diện:
public class DocumentWindow extends JWindow
implements DocView, DocumentObserver {
//... all swing stuff
public void onDocumentSave(DocModel saved) {
// No-op
}
public void onDocumentLoad(DocModel loaded) {
// do what you need with the loaded model to the
// swing components, or let the controller do it on
// the view interface
}
// ...
}
Tôi hy vọng những ví dụ thúc đẩy này cung cấp cho bạn một số ý tưởng về cách tự làm. Tuy nhiên, tôi thực sự khuyên bạn nên cân nhắc sử dụng các khung công tác trong Java để thực hiện hầu hết mọi thứ cho bạn, nếu không bạn sẽ có rất nhiều mã soạn sẵn mất nhiều thời gian để viết. Có một số Nền tảng khách hàng phong phú (RCP) mà bạn có thể sử dụng để thực hiện một số chức năng cơ bản mà bạn rất cần, chẳng hạn như xử lý tài liệu trên toàn ứng dụng và xử lý nhiều sự kiện cơ bản.
Có một cặp vợ chồng tôi có thể nghĩ ra từ đầu của mình: Eclipse và Netbeans RCP.
Bạn vẫn cần phát triển bộ điều khiển và mô hình cho chính mình, nhưng đó là lý do tại sao bạn sử dụng ORM. Ví dụ sẽ là Hibernate .
Các container IoC là tuyệt vời, nhưng cũng có các khung cho việc này. Chẳng hạn như Spring (cũng xử lý dữ liệu trong số những thứ khác).