2009-09-18 9 views
5

Pracuję nad budowaniem aplikacji MVP (C# Winforms). Moja początkowa wersja to Critique my simple MVP Winforms app ... Teraz zwiększam złożoność. Podzieliłem kod, aby obsługiwać dwa oddzielne pola tekstowe na dwie pary widoków/prezentacji. Jest to banalny przykład, ale chodzi o to, aby poznać szczegóły wielu prezenterów, którzy dzielą ten sam model.Udostępnianie modelu w aplikacji WinForce MVP

Moje pytania są o modelu:

  1. Ja w zasadzie za pomocą właściwości zmieniono zdarzenie podniesione przez model powiadamiania poglądy, że coś się zmieniło. Czy to dobre podejście? Co jeśli dojdzie do punktu, w którym mam 100 lub 1000 właściwości? Czy nadal jest to praktyczne?

  2. Czy tworzenie wystąpienia modelu w każdym z prezenterów przy użyciu prawidłowego podejścia jest zgodne z   NoteModel _model = NoteModel.Instance  ? Zauważ, że chcę się upewnić, że wszyscy prezenterzy dzielą te same dane.

  3. Jeśli jest lepszym rozwiązaniem, jestem otwarty na sugestie ....

Mój kod wygląda następująco:

NoteModel.cs

public class NoteModel : INotifyPropertyChanged 
{ 
    private static NoteModel _instance = null; 

    public static NoteModel Instance 
    { 
     get { return _instance; } 
    } 

    static NoteModel() 
    { 
     _instance = new NoteModel(); 
    } 

    private NoteModel() 
    { 
     Initialize(); 
    } 

    public string Filename { get; set; } 
    public bool IsDirty { get; set; } 
    public readonly string DefaultName = "Untitled.txt"; 

    string _sText; 
    public string TheText 
    { 
     get { return _sText; } 
     set 
     { 
      _sText = value; 
      PropertyHasChanged("TheText"); 
     } 
    } 

    string _sMoreText; 
    public string MoreText 
    { 
     get { return _sMoreText; } 
     set 
     { 
      _sMoreText = value; 
      PropertyHasChanged("MoreText"); 
     } 
    } 

    public void Initialize() 
    { 
     Filename = DefaultName; 
     TheText = String.Empty; 
     MoreText = String.Empty; 
     IsDirty = false; 
    } 

    private void PropertyHasChanged(string sPropName) 
    { 
     IsDirty = true; 

     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(sPropName)); 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
} 

TextEditorPresenter .cs

public class TextEditorPresenter 
{ 
    ITextEditorView _view; 
    NoteModel _model = NoteModel.Instance; 

    public TextEditorPresenter(ITextEditorView view)//, NoteModel model) 
    { 
     //_model = model; 
     _view = view; 
     _model.PropertyChanged += new PropertyChangedEventHandler(model_PropertyChanged); 
    } 

    void model_PropertyChanged(object sender, PropertyChangedEventArgs e) 
    { 
     if (e.PropertyName == "TheText") 
      _view.TheText = _model.TheText; 
    } 

    public void TextModified() 
    { 
     _model.TheText = _view.TheText; 
    } 

    public void ClearView() 
    { 
     _view.TheText = String.Empty; 
    } 
} 

TextEditor2Presenter.cs jest zasadniczo taki sam, z wyjątkiem tego, że działa pod numerem _model.MoreText zamiast _model.TheText.

ITextEditorView.cs

public interface ITextEditorView 
{ 
    string TheText { get; set; } 
} 

ITextEditor2View.cs

public interface ITextEditor2View 
{ 
    string MoreText { get; set; } 
} 
+0

+1 Świetne pytanie. Mam to samo w głowie. – Marcel

Odpowiedz

3
  1. Takie podejście jest dobre. Jednakże, jeśli patrzysz na posiadanie setek (tysięcy nawet!) Właściwości, to myślę, że możesz mieć klasę Boga (anty-wzór). Nie ma zbyt wielu dobrych klas ze 100 właściwościami. Zamiast tego rozważ podzielenie swojego modelu na mniejsze klasy. Co więcej, nie musisz mieć osobnego wydarzenia dla każdej nieruchomości. Jeśli model zostanie w ogóle zmieniony, możesz wystrzelić jedno zdarzenie (które może zawierać informacje opisujące zmianę), a widoki mogą z niego korzystać.
  2. Unikałbym używania wzorca Singleton, chyba że jesteś pewien, że chcesz go zastosować. Zamiast tego zmień konstruktor dla wszystkich swoich widoków, aby przejął instancję modelu.
+0

1. Sądzę, że trochę przesadziłem. Mógłbym przewidzieć 100 rzeczy, które chcę śledzić. Moją myślą o modelu byłaby wtedy enkapsulacja i agregacja, więc byłoby to coś w stylu Model.ComplexThing1 (z 10 właściwościami) i Model.ComplexThing2 (z 4 właściwościami), itp. 2. Chyba nie jestem pewien, czy Chcę, żeby to się stało. Skąd mam wiedzieć? Moje rozumienie tego modelu polega na tym, że jest to ostateczne źródło informacji przechowywanych w czasie wykonywania. W takim przypadku powinna istnieć tylko jedna instancja modelu, prawda? –

+0

@Keith: Różnica polega na tym, że "tam ** powinno ** zawsze być tylko jedną instancją modelu", a "tam ** może ** być tylko jedną instancją modelu". Możesz użyć instancji singleton (small 's'!) Po prostu tworząc pojedynczą instancję w fabryce itp., Ale używaj tylko Singleton (duże "S"!), Gdy ** musisz **. –

+0

@Johan Gerell: Jak "używasz tylko ... kiedy musisz": Czy w tym kontekście jest coś złego w Singletonie? – Marcel

1

Pamiętaj, że w dowolnej aplikacji warstwowej normalne jest, że model domeny przekracza wszystkie warstwy.

  1. Tak więc, chciałbym mieć swój prezenter zdać instancji notatkę do widzenia (co bez wątpienia jest Kontrola jakiegoś), a następnie niech Databinding przez BindingSource przejąć. Po użyciu wiązania danych elementy sterujące automatycznie nasłuchują zdarzenia PropertyChanged i będą odpowiednio aktualizowane bez potrzeby stosowania dodatkowego kodu z Twojej strony.Powiadomienie oparte na zdarzeniach jest odpowiednim zastosowaniem tutaj, bez względu na to, ile obiektów jest monitorowanych, ponieważ tylko obiekty, którym zależy na zmianie, podejmą działanie (w przeciwieństwie do tego, że wiele obiektów podejmuje działania niepotrzebnie).

  2. Zazwyczaj otrzymuje się instancje encji z niższej warstwy. Na przykład można wdrożyć usługę, która zwraca instancje Note. Za każdym razem, gdy poprosisz tę usługę o uwagę # 3, zwraca to samo wystąpienie uwagi, które zostało utworzone z utrwalonych danych. Możesz dodatkowo dodać kolejny element do warstwy biznesowej, aby uzupełnić prezenterów - może to być wywołanie WorkItem lub kontrolera. Wszyscy prezenterzy mogliby zapoznać się z ich instancją WorkItem, aby uzyskać aktualną instancję Note, na której użytkownik będzie pracował.

uważam patrząc na przykłady, w jaki sposób Composite Application bloku (lub CAB) korzysta z tych wzorców do tworzenia inteligentnych aplikacji klienckich. To wszystko wzorce projektowe i zasady OO, których wdrożenie jest warte wysiłku.

1
  • Na Pytanie 1: Wdrożenie INotifyPropertyChanged wydaje mi się dobrym pomysłem. Prawdopodobnie jednak podzieliłbyś wiele właściwości na klasy.
  • Do pytania 2: Obecnie używam wzorca Singleton do udostępniania mojego modelu MVP wielu prezenterów. Jak na razie jestem szczęśliwy, ponieważ gwarantuje to, że naprawdę istnieje tylko jeden przypadek mojego modelu.
Powiązane problemy