Wzorzec obserwator (observer), czy robię to dobrze?

Odpowiedz Nowy wątek
2019-08-29 08:22
0

Mam wątpliwości co do implementacji wzorca obserwator z całkowitą separacją warstw.

Poniższy przykład nie jest rzeczywistym projektem, a jedynie przykładem obrazującym o co mi chodzi

I mojej solucji posiadam dwie warstwy projektowe:

  • Desktop (views, view models, models)
  • Service biblioteka(z obserwatorami)

Mój view model subjektem zapisującym obserwatorów.

Kod w VM:

    interface ISubject
        {
            void Subscribe(IObserverService observer);
            void Unsubscribe(IObserverService observer);
            void Notify();
        }
    public class MainWindowViewModel : ViewModelBase, ISubject
        {
            private readonly IControlsService _controlsService;
            private readonly IObserverService _observer1;
            private readonly IObserverService _observer2;
            private ArrayList _observers;

            public MainWindowViewModel(
            IControlsService controlsService,
            IObserver1 observer1,
            IObserver2 observer2)
            {
                _observer1 = observer1;
                _observer2 = observer2;

                ObserverCommand = new DelegateCommand(OnObserverCommand);

                InitProgram();
            }

            private void InitProgram()
            {
                _observers = new ArrayList();

                _observers.Add(_observer1);
                _observers.Add(_observer2);
            }

            public List<IObserverService> Observers { get; set; }

            private void OnSwitchCommand(object obj)
            {
                if (Jeden == true)
                {
                    UiModel = _controlsService.SwitchOff();
                }
                else
                {
                    UiModel = _controlsService.SwitchOn();
                }
            }

            private void OnObserverCommand(object obj)
            {
                SomeValue++;
            }

            public void Subscribe(IObserverService observer)
            {
                Observers.Add(observer);
            }

            public void Unsubscribe(IObserverService observer)
            {
                Observers.Remove(observer);
            }

            public void Notify()
            {
                Observers.ForEach(x => x.Update(SomeValue));
            }

            public ICommand ObserverCommand { get; private set; }

            private int _someValue;
            public int SomeValue
            {
                get => _someValue;
                set
                {
                    _someValue = value;
                    InformObservers();
                }
            }

            private void InformObservers()
            {
                foreach (IObserverService x in _observers)
                {
                    x.Update(SomeValue);
                }
            }
        }

I prosty obserwator:

    public interface IObserverService
        {
            void Update(int someValue);
        }
    public class Observer1 : IObserver1, IObserverService
        {
            public string ObserverName { get; private set; }
            public Observer1(string name)
            {
                this.ObserverName = name;
            }
            public void Update(int someValue)
            {
                MessageBox.Show("New value: " + someValue.ToString() + " for " + ObserverName);
            }
        }

Observer2 jest taki sam jak powyżej.

Obecnie mam wątpliwości jak powinien wyglądać mój konstruktor, jeśli chciałbym utworzyć nowego obserwatora z nazwą, dla przykładu new Observer1("observer1 name"). Czy mój konstruktor powinien wyglądać tak?

    public MainWindowViewModel()
            {
                _observerService = observerService;
                IObserverService observer1 = new ObserverService("name1");
                IObserverService observer2 = new ObserverService("name2");

                SwitchCommnad = new DelegateCommand(OnSwitchCommand);
                ObserverCommand = new DelegateCommand(OnObserverCommand);

                InitProgram();
            }

Czy to podejście jest poprawne? I da się testować?

edytowany 5x, ostatnio: bakunet, 2019-08-29 12:51

Pozostało 580 znaków

2019-08-29 12:27
0

W czym to jest lepsze od wbudowanych w C# zdarzeń?


"HUMAN BEINGS MAKE LIFE SO INTERESTING. DO YOU KNOW, THAT IN A UNIVERSE SO FULL OF WONDERS, THEY HAVE MANAGED TO INVENT BOREDOM."
Ale ja się zgadzam, i nawet INotifyPropertyChanged jest lepsze, ale dłubię sobie we wzorcach i próbuję je przenieść do świata rzeczywistego, czysto teoretyzując, ciekaw jestem jak to zrobić. - bakunet 2019-08-29 12:49
Ale po co przenosić wzorzec, który jest wbudowany w język? :) - somekind 2019-08-29 12:56
Żeby się przekonać czy mi się uda i zrobić to dobrze :) - bakunet 2019-08-29 12:56

Pozostało 580 znaków

2019-08-29 13:00
0
somekind napisał(a):

W czym to jest lepsze od wbudowanych w C# zdarzeń?

Mogę się mylić ale w eventach chyba łatwiej o wycieki pamięci. Jeśli się mylę to mnie poprawcie :)

edytowany 2x, ostatnio: szydlak, 2019-08-29 13:01

Pozostało 580 znaków

2019-09-02 10:31
2
szydlak napisał(a):
somekind napisał(a):

W czym to jest lepsze od wbudowanych w C# zdarzeń?

Mogę się mylić ale w eventach chyba łatwiej o wycieki pamięci. Jeśli się mylę to mnie poprawcie :)

To jest jedno i to samo, w obu wypadkach masz wyciek jeśli nie odepniesz niepotrzebnego już obserwatora.
A skoro jest to jedno i to samo, po co używać bardziej rozwlekłego zapisu skoro mamy w c# eventy i delegaty?

Swoją drogą klasyczna wersja obserwatora nie do końca się przyjęła, Ralph Johnson w swojej prezentacji 20 lat ze wzorcami projektowymi przyznaje że lepszym pomysłem jest przesyłanie informacji o tym co się zmieniło do obserwatora, niż sytuacja w której to obserwator odpytuje obiekt obserwujący o nowe wartości po otrzymaniu powiadomienia.

Czyli obsługa eventów w WinfForms czy WPF jest najlepszy przykładem poprawnie zaimplementowanego wzorca obserwator zgodnie z tym co oferuje język C#, a nie to co tutaj kombinujesz.


Java to taki C# tyle że z gorszą składnią.

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0