-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path9.observer_pattern_Csharp.h
141 lines (131 loc) · 4.34 KB
/
9.observer_pattern_Csharp.h
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
135
136
137
138
139
140
141
//
// Created by Tianyi Zhang on 1/4/21.
//
#ifndef DESIGN_PATTERN_9_OBSERVER_PATTERN_CSHARP_H
#define DESIGN_PATTERN_9_OBSERVER_PATTERN_CSHARP_H
#include <iostream>
#include <vector>
#include <memory>
#include <string>
#include <exception>
#include <map>
template<typename T>
struct IObserver{
virtual void onCompleted() = 0;
virtual void onError(std::exception exp) = 0;
virtual void onNext(T value) = 0;
virtual ~IObserver(){};
};
struct UnSubscriber{
virtual void unSubscribe() = 0;
virtual ~UnSubscriber(){};
};
template<typename T>
struct IObservable{
//maybe make use of a unsubscribe method instead of returning a unsubscriber.
virtual std::shared_ptr<UnSubscriber> subscribe(std::shared_ptr<IObserver<T>> observer) = 0;
};
struct Temperature{
public:
void setIndoorTemp(double indoorTemp){
this->indoorTemp = indoorTemp;
changedField["indoorTemp"] = true;
}
void setOutdoorTemp(double outdoorTemp){
this->outdoorTemp = outdoorTemp;
changedField["outdoorTemp"] = true;
}
void setTimeSerial(int timeSerial){
this->timeSerial = timeSerial;
changedField["timeSerial"] = true;
}
double getIndoorTemp(){
return indoorTemp;
}
double getOutdoorTemp(){
return outdoorTemp;
}
int getTimeSerial(){
return timeSerial;
}
bool isDirty(std::string const& field){
return changedField[field] == true;
}
void clean(std::string const& field){
changedField[field] = false;
}
private:
double indoorTemp;
double outdoorTemp;
int timeSerial;
std::map<std::string, bool> changedField;
};
struct TemperatureMonitor : public IObservable<Temperature>
{
std::shared_ptr<UnSubscriber> subscribe(std::shared_ptr<IObserver<Temperature>> observer) override{
if(std::find(observers.begin(), observers.end(), observer) == observers.end()){
observers.push_back(observer);
}
return std::make_shared<UnsubscriberImpl>(observers, observer);
}
void setIndoorTemp(double indoorTemp){
temperature.setIndoorTemp(indoorTemp);
for(auto observer : observers)
observer->onNext(temperature);
temperature.clean("indoorTemp");
}
void setOutdoorTemp(double outdoorTemp){
temperature.setOutdoorTemp(outdoorTemp);
for(auto observer : observers)
observer->onNext(temperature);
temperature.clean("outdoorTemp");
}
void setTimeSerial(int timeSerial){
temperature.setTimeSerial(timeSerial);
for(auto observer : observers)
observer->onNext(temperature);
temperature.clean("timeSerial");
}
void stopMonitor(){
for(auto observer : observers) {
observer->onCompleted();
observers.erase(observers.begin(), observers.end());
}
}
private:
std::vector<std::shared_ptr<IObserver<Temperature>>> observers;
Temperature temperature;
//disposable in csharp
struct UnsubscriberImpl : UnSubscriber{
UnsubscriberImpl(std::vector<std::shared_ptr<IObserver<Temperature>>>& observers,
std::shared_ptr<IObserver<Temperature>> observer){
this->observers = &observers;
this->observer = observer;
}
void unSubscribe(){
if(std::find(observers->begin(), observers->end(), observer) != observers->end()) {
observers->erase(std::find(observers->begin(), observers->end(), observer));
}
}
private:
//possible memory leak here..
std::vector<std::shared_ptr<IObserver<Temperature>>>* observers;
std::shared_ptr<IObserver<Temperature>> observer;
};
};
struct TemperatureReporter : public IObserver<Temperature>{
void onNext(Temperature temperature) override{
if(temperature.isDirty("indoorTemp")){
std::cout<<"indoorTemp : "<<temperature.getIndoorTemp()<<std::endl;
}
if(temperature.isDirty("outdoorTemp")){
std::cout<<"outdoorTemp : "<<temperature.getOutdoorTemp()<<std::endl;
}
if(temperature.isDirty("timeSerial")){
std::cout<<"timeSerial : "<<temperature.getTimeSerial()<<std::endl;
}
}
void onCompleted() override{};
void onError(std::exception exp) override{};
};
#endif //DESIGN_PATTERN_9_OBSERVER_PATTERN_CSHARP_H