Rozważmy standardową aplikację Win32:

  1. #include <windows>
  2. LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  3. {
  4. switch(msg)
  5. {
  6. //przyjmujemy zdarzenia od systemu, np. WM_PAINT
  7. }
  8. }
  9. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
  10. {
  11. //Tworzymy klasę okna, okno i wyświetlamy go
  12. //Na końcu pętla komunikatów
  13. }

Nasza aplikacja będzie się składać z wielu klas warstwy biznesowej (logiki), a także klasy widoku. Chcemy oddzielić logikę od prezentacji, przy czym musimy zapewnić interfejs do komunikacji obustronnej między tymi warstwami. Widok chce operować na modelu, a model na widoku. Jakiego wzorca użyć, aby zapewnić właściwy podział zadań i nie utrudnić sobie życia?

Zadania kontrolera i widoku w MVC

Kontroler - przyjmuje dane wejściowe od użytkownika, reaguje na poczynania, aktualizuje model, odświeża widok
Widok - opisuje, jak wyświetlić pewną część modelu w ramach interfejsu użytkownika

Zadania kontrolera i widoku w MVP

Widok - wyświetla dane i przekazuje komendy użytkownika (zdarzenia) do prezentera i działa na tych danych
Prezenter - nadzoruje model i widok, pobiera dane z modelu, formatuje je i przekazuje widokowi do wyświetlenia

Można również pozwolić na obustronną komunikację między modelem a widokiem za pomocą metod publicznych. Jeśli pozwalamy widokowi na bezpośredni dostęp do modelu, czemu nie na odwrót? aarambo.gif

Kontroler zgodnie z definicją przyjmuje dane wejściowe. Taką funkcję pełni WndProc. Problem w tym, że procedura okna jest statyczna i ściśle związana z oknem - czyli widokiem! Na siłę można użyć jej do obsługi wielu okien, bo uchwyt do okna przychodzi jako argument. Jeśli przeniesiemy ją z widoku do kontrolera, a okno tworzymy w widoku, widok będzie musiał znać jej nazwę (nie musi być WndProc) oraz dołączyć pliki nagłówkowe kontrolera, co jest sprzeczne z ideą niezależności warstw - widok ani model ma nic nie wiedzieć o kontrolerze, chyba że można sobie pozwolić na wyjątek smile.gif

Przykład interakcji: wybieramy opcję w menu. System wysyła zdarzenie, które obsługujemy w WndProc. Może zajść potrzeba wykonania akcji zarówno w widoku i modelu. Jeśli obciążymy tym klasę widoku, będzie zawierać dużo logiki - odwołań do modelu, interpretacji danych wejściowych...

Podsumowując, powstają pytania:

1. Jakich wzorców użyć w aplikacjach okienkowych?
2. Jakie powinny być kompetencje poszczególnych warstw w aplikacji Win32?
3. Jak powinna wyglądać komunikacja między warstwami i przepływ danych wejściowych?