ไม่มีแนวทางการออกแบบ(เช่นdefacto ) ที่ตกลงกันตามปกติสำหรับ MVC มันไม่ยากเลยที่จะทำด้วยตัวเอง แต่ต้องการการวางแผนในชั้นเรียนของคุณรวมถึงเวลาและความอดทน
เหตุผลที่ไม่มีวิธีแก้ปัญหาที่แน่นอนก็คือมีหลายวิธีในการทำ MVC ซึ่งทั้งหมดมีข้อดีและข้อเสีย ดังนั้นจงฉลาดกับมันและทำสิ่งที่เหมาะสมกับคุณที่สุด
ในการตอบคำถามของคุณคุณต้องการแยกตัวควบคุมออกจากมุมมองเช่นกัน (เพื่อให้คุณสามารถใช้ตรรกะกฎธุรกิจเดียวกันสำหรับทั้งแอป Swing และในแอปคอนโซล) ในตัวอย่าง Swing คุณต้องการแยกตัวควบคุมออกจากJWindow
วิดเจ็ตและอะไรก็ตามใน Swing วิธีที่ฉันใช้ในการทำ (ก่อนใช้กรอบงานจริง) คือการสร้างอินเตอร์เฟสสำหรับมุมมองที่คอนโทรลเลอร์ใช้:
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());
}
}
สำหรับวิธีแก้ปัญหานี้ในระหว่างการเริ่มต้นคุณจะต้องลงทะเบียนคอนโทรลเลอร์ในมุมมอง
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
}
}
อาจเป็นความคิดที่ดีที่จะสร้าง IoC-container เพื่อทำการตั้งค่าทั้งหมดสำหรับคุณแทน
ด้วยวิธีนี้คุณสามารถใช้มุมมองคอนโซลเท่านั้นโดยใช้ตัวควบคุมเดียวกัน:
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
}
ส่วนที่สนุกคือวิธีการจัดการกิจกรรม ฉันใช้สิ่งนี้โดยให้มุมมองลงทะเบียนตัวเองกับคอนโทรลเลอร์โดยใช้อินเตอร์เฟสสิ่งนี้ทำได้โดยใช้รูปแบบ Observer (หากคุณใช้. NET คุณจะใช้ตัวจัดการเหตุการณ์แทน) นี่คือตัวอย่างของ "ผู้สังเกตการณ์เอกสาร" แบบง่ายซึ่งจะส่งสัญญาณเมื่อเอกสารถูกบันทึกหรือโหลด
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);
}
}
ด้วยวิธีนี้มุมมองสามารถอัปเดตตัวเองได้อย่างเหมาะสมเนื่องจากกำลังสมัครรับข้อมูลอัปเดตเอกสาร สิ่งที่ต้องทำคือใช้DocumentObserver
อินเทอร์เฟซ:
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
}
// ...
}
ฉันหวังว่าตัวอย่างที่สร้างแรงบันดาลใจเหล่านี้จะช่วยให้คุณมีความคิดเกี่ยวกับวิธีการทำด้วยตัวเอง อย่างไรก็ตามฉันขอแนะนำให้คุณพิจารณาใช้เฟรมเวิร์กใน Java ที่ทำสิ่งต่าง ๆ ให้คุณมากที่สุดมิฉะนั้นคุณจะต้องมีรหัสสำเร็จรูปจำนวนมากที่ใช้เวลาเขียนนาน มีสองสาม Rich Client Platforms (RCP) ที่คุณสามารถใช้เพื่อใช้งานฟังก์ชันพื้นฐานบางอย่างที่คุณต้องการเช่นการจัดการเอกสารทั่วทั้งแอปพลิเคชันและการจัดการเหตุการณ์พื้นฐานมากมาย
มีคู่ที่ฉันนึกได้จากหัวของฉัน: EclipseและNetbeans RCP's
คุณยังต้องพัฒนาตัวควบคุมและรุ่นสำหรับตัวคุณเอง แต่นั่นเป็นเหตุผลที่คุณใช้ ORM ตัวอย่างจะเป็นไฮเบอร์เนต
คอนเทนเนอร์ IoC นั้นยอดเยี่ยม แต่มีกรอบสำหรับเรื่องนี้เช่นกัน เช่นSpring (ซึ่งจัดการข้อมูลได้ดีเช่นกัน)