MVC için genel olarak üzerinde anlaşmaya varılmış (yani defacto ) bir tasarım kılavuzu yoktur. Bunu kendiniz yapmak o kadar da zor değil ama sınıflarınız üzerinde biraz planlama ve çok fazla zaman ve sabır gerektiriyor.
Kesin bir çözüm bulunmamasının nedeni, MVC yapmanın birden fazla yolu olması, hepsinin artıları ve eksileri ile olmasıdır. Bu yüzden akıllı olun ve size en uygun olanı yapın.
Sorunuzu cevaplamak için, aslında denetleyiciyi görünümden de ayırmak istersiniz (böylece hem Swing uygulaması hem de konsol uygulaması için aynı iş kuralı mantığını kullanabilirsiniz). Swing örneğinde, denetleyiciyi Swing'deki JWindow
ve herhangi bir widget'tan ayırmak istiyorsunuz . Eskiden (gerçek çerçeveleri kullanmadan önce) yaptığım yol, denetleyicinin kullandığı görünüm için bir arayüz oluşturmaktır:
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());
}
}
Başlatma sırasında bu çözüm için denetleyiciyi görünüme kaydetmeniz gerekir.
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
}
}
Bunun yerine tüm ayarları yapmak için bir IoC kapsayıcısı oluşturmak iyi bir fikir olabilir.
Her neyse, bu şekilde aynı denetleyicileri kullanarak yalnızca konsol görünümlerini uygulayabilirsiniz:
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
}
İşin eğlenceli kısmı olay işlemenin nasıl yapılacağıdır. Bunu, bir arabirim kullanarak görünümün kendisini denetleyiciye kaydettirmesine izin vererek uyguladım, bu, Gözlemci deseni kullanılarak yapılır (.NET kullanıyorsanız olay işleyicileri kullanırsınız). Burada, bir belgenin ne zaman kaydedildiğini veya yüklendiğini gösteren basit bir "belge gözlemcisi" örneği vardır.
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);
}
}
Bu şekilde görünüm, belge güncellemelerine abone olduğu için kendisini düzgün bir şekilde güncelleyebilir. Tek yapması gereken DocumentObserver
arayüzü uygulamaktır :
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
}
// ...
}
Umarım bu motive edici örnekler size bunu nasıl yapacağınız konusunda bazı fikirler verir. Bununla birlikte, Java'da sizin için çoğu şeyi yapan çerçeveler kullanmayı düşünmenizi önemle tavsiye ederim, yoksa yazmak için uzun zaman alan çok sayıda kaynak koduna sahip olursunuz. Uygulama çapında belge işleme ve çok sayıda temel olay işleme gibi, büyük olasılıkla ihtiyaç duyduğunuz bazı temel işlevleri uygulamak için kullanabileceğiniz birkaç Zengin İstemci Platformu (RCP) vardır.
Aklımdan aklıma gelen bir çift var: Eclipse ve Netbeans RCP'ler.
Hala kendiniz için kontrolör ve modeller geliştirmeniz gerekiyor, ancak bu yüzden bir ORM kullanıyorsunuz. Örnek Hazırda Bekletme olacaktır .
IoC kapları harika ve hepsi de bunun için çerçeveler var. Bu şekilde Spring (aynı zamanda yok olan veriler, diğer şeylerin yanı sıra hem de taşıma).