Czy istnieje zbiór wspólnie uzgodnionych wytycznych projektowych dotyczących oddzielania klas Model od klas View / Controller w aplikacji Java Swing? Nie martwię się tak bardzo, że Widok / Kontroler nic nie wie o Modelu, jak na odwrót: Chciałbym zaprojektować mój Model tak, aby nic nie wiedział o javax.swing. Idealnie powinien mieć prosty interfejs API umożliwiający sterowanie nim przez coś tak prymitywnego jak CLI. Luźno mówiąc, powinien to być „silnik”.
Przekazywanie zdarzeń GUI do modelu nie jest zbyt trudne - Wykonawcy akcji mogą wywoływać interfejs API modelu. Ale co z tym, kiedy model wprowadza własne zmiany stanu, które muszą zostać odzwierciedlone z powrotem w GUI? Do tego właśnie służy „słuchanie”, ale nawet „słuchanie” nie jest całkowicie bierne; wymaga, aby model wiedział o dodaniu detektora.
Szczególny problem, który skłonił mnie do myślenia, dotyczy kolejki plików. Po stronie GUI znajduje się DefaultListModel
za JList
, a niektóre elementy GUI do wyboru plików z systemu plików i dodania ich do JList. Po stronie modelu chce usunąć pliki z dolnej części tej „kolejki” (powodując ich zniknięcie z listy JList) i przetworzyć je w jakiś sposób. W rzeczywistości kod modelu jest już napisany - obecnie utrzymuje ArrayList<File>
i udostępnia add(File)
metodę publiczną . Ale nie mam pojęcia, jak sprawić, by mój model działał z View / Controller bez pewnych ciężkich, specyficznych dla Swinga modyfikacji modelu.
Jestem bardzo nowy zarówno w programowaniu w Javie, jak i GUI, zawsze do tej pory programowałem „wsadowo” i „back-end” - stąd moje zainteresowanie utrzymaniem ścisłego podziału między modelem a interfejsem użytkownika, jeśli jest to możliwe i czy może być nauczonym.
Odpowiedzi:
Nie ma powszechnie uzgodnionych (tj. Defacto ) wytycznych projektowych dla MVC. Nie jest to wcale takie trudne, ale wymaga planowania na zajęciach oraz dużo czasu i cierpliwości.
Powodem, dla którego nie ma określonego rozwiązania, jest to, że istnieje wiele sposobów na MVC, wszystkie z ich zaletami i wadami. Bądź więc mądry i rób to, co najbardziej ci odpowiada.
Aby odpowiedzieć na twoje pytanie, faktycznie chcesz również oddzielić kontroler od widoku (abyś mógł używać tej samej logiki reguł biznesowych zarówno dla aplikacji Swing, jak i konsoli). W przykładzie Swing chcesz oddzielić kontroler od
JWindow
i dowolnego widgetu w Swing. Sposób, w jaki kiedyś to robiłem (przed użyciem rzeczywistych frameworków), to stworzenie interfejsu dla widoku używanego przez kontroler:W przypadku tego rozwiązania podczas uruchamiania należy zarejestrować kontroler w widoku.
Dobrym pomysłem może być utworzenie kontenera IoC w celu wykonania całej konfiguracji.
W każdym razie w ten sposób możesz zaimplementować widoki tylko na konsolę, używając tych samych kontrolerów:
Zabawne jest to, jak obsługiwać zdarzenia. Zaimplementowałem to, pozwalając widokowi zarejestrować się w kontrolerze za pomocą interfejsu, odbywa się to za pomocą wzorca Observer (jeśli używasz platformy .NET, zamiast tego używałbyś programów obsługi zdarzeń). Oto przykład prostego „obserwatora dokumentów”, który sygnalizuje zapisanie lub załadowanie dokumentu.
W ten sposób widok może się poprawnie zaktualizować, ponieważ subskrybuje aktualizacje dokumentu. Wystarczy zaimplementować
DocumentObserver
interfejs:Mam nadzieję, że te motywujące przykłady podadzą kilka pomysłów, jak to zrobić samodzielnie. Jednak zdecydowanie radzę rozważyć użycie frameworków w Javie, które wykonują większość rzeczy za Ciebie, w przeciwnym razie skończy się dużo kodu, który zajmuje dużo czasu, aby napisać. Istnieje kilka bogatych platform klienta (RCP), które można wykorzystać, które implementują niektóre podstawowe funkcje, które najprawdopodobniej będą potrzebne, takie jak obsługa dokumentów w całej aplikacji i wiele podstawowych czynności związanych z obsługą zdarzeń.
Z głowy mogę wymyślić kilka: RCP Eclipse i Netbeans .
Nadal musisz opracować dla siebie kontrolery i modele, ale właśnie dlatego używasz ORM. Przykładem może być Hibernacja .
Kontenery IoC są fajne, ale istnieją też ramy dla tego. Takich jak Spring (który zajmuje się także przetwarzaniem danych, między innymi).
źródło
Uważam, że czasami musimy iść na kompromis
Jak mówisz, byłoby wspaniale, gdybyśmy mogli propagować powiadomienia o zmianach w sposób dorozumiany bez obserwowanego obiektu posiadającego jawną infrastrukturę do tego. W przypadku popularnych języków imperatywnych, takich jak Java, C #, C ++, ich architektura uruchomieniowa jest na razie zbyt lekka. Rozumiem przez to, że nie jest to obecnie część specyfikacji języka.
W twoim konkretnym przypadku nie wydaje mi się, aby zdefiniowanie / użycie jakiegoś ogólnego interfejsu, takiego jak INotifyPropertyChanged (jak w c #), było złym posunięciem , ponieważ i tak nie jest ono automatycznie łączone z widokiem - po prostu mówi, że jeśli zmienię, powiem wam .
Ponownie zgadzam się, że byłoby wspaniale, gdybyśmy nie musieli sami definiować powiadomienia o zmianie, ale z drugiej strony, jeśli byłoby to domniemane dla wszystkich klas, mogłoby to spowodować obciążenie ogólne.
źródło