forked from ahotko/c-sharp-code-examples
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ObserverPattern.cs
134 lines (113 loc) · 3.83 KB
/
ObserverPattern.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
using System;
using System.Collections.Generic;
namespace CodeSamples.Patterns.Behavioral
{
#region Observable classes and interfaces
//Also ISubject
interface IObservable
{
bool Attach(IObserver observer);
bool Detach(IObserver observer);
void Notify();
//used, when higher abstraction is used (class ConcreteObserverAbstract)
int GetValueForAbstract();
}
interface IObserver
{
void Update();
void UpdateWithObservableParam(IObservable observable);
void UpdateWithResultParam(ValuesClass values);
}
class ValuesClass
{
public int Value { get; set; } = 12;
}
class ConcreteObservable : IObservable
{
private List<IObserver> _observers = new List<IObserver>();
public bool Attach(IObserver observer)
{
_observers.Add(observer);
return true;
}
public bool Detach(IObserver observer)
{
_observers.Remove(observer);
return true;
}
public int GetValueForAbstract()
{
return 5;
}
public int GetValueForClass()
{
return 3;
}
public void Notify()
{
foreach (IObserver observer in _observers)
{
observer.Update();
observer.UpdateWithObservableParam(this);
observer.UpdateWithResultParam(new ValuesClass());
}
}
}
class ConcreteObserverAbstract : IObserver
{
readonly IObservable _observable = null;
public ConcreteObserverAbstract(IObservable observable)
{
_observable = observable;
_observable.Attach(this);
}
public void Update()
{
Console.WriteLine($"Abstract Update w/o params: {_observable.GetValueForAbstract()}");
}
public void UpdateWithObservableParam(IObservable observable)
{
Console.WriteLine($"Abstract Update with IObservable parameter: {observable.GetValueForAbstract()}");
}
public void UpdateWithResultParam(ValuesClass values)
{
Console.WriteLine($"Abstract Update with ValuesClass parameter: {values.Value}");
}
}
//ConcreteObserver vs. ConcreteObserverAbstract:
// ConcreteObserver has a class as parameter in constructor, so any mesthod, not defined in interface can be called
// ConcreteObserverAbstract has an interface, so only methods in interface can be called
class ConcreteObserver : IObserver
{
ConcreteObservable _observable = null;
public ConcreteObserver(ConcreteObservable observable)
{
_observable = observable;
_observable.Attach(this);
}
public void Update()
{
Console.WriteLine($"Update w/o params: {_observable.GetValueForAbstract()}, Concrete: {_observable.GetValueForClass()}");
}
public void UpdateWithObservableParam(IObservable observable)
{
Console.WriteLine($"Update with IObservable parameter: {observable.GetValueForAbstract()}");
}
public void UpdateWithResultParam(ValuesClass values)
{
Console.WriteLine($"Update with ValuesClass parameter: {values.Value}");
}
}
#endregion
public class ObserverPatternSample : SampleExecute
{
public override void Execute()
{
Section("Observer Pattern");
var observable = new ConcreteObservable();
var concreteObserver = new ConcreteObserver(observable);
var concreteObserverAbstract = new ConcreteObserverAbstract(observable);
observable.Notify(); //Notify() is usually called from inside the class, when and where the change happens...
}
}
}