Design Pattern --- (2) Observer Pattern === [TOC] ## What's a problem would be solved with observer pattern? The polling problem.This is a one-to-one or one-to-many communication method. ### How does polling work? Suppose there are two users,the client and the server,the server will immediately update the information if client's state has been changed ,therefore,the update method keeps asking about currently client's state. Obviously,the method that keeps asking is not only annoying but also slow,and we now just consider one-to-one case ,when the project is gonna grow to one-to-many,the client may blow up. ## How does observer pattern do ? Contrary to the above solution,the client can sent a message to all of servers in list while its state has been changed,it can push actively instead of poll passively. ## How does observer pattern do in practice? ![Big Picture](https://imgur.com/RL6Dng5.jpg "Big Picture") ↑ **Big Picture** IObservable is able to observe,in other words,it has information that determines the state. * add function: When we call this function,it will add a new observer to the list. * remove function: As we know what the add function does,the remove function will remove the observer that exist in the list. * ==Notify function:== This function is a key function ,if we understand how does the notify function do,then we already understand observer pattern. So,the notify function is being called immediately when the state changes,it will **notify all observers** in the list **to update the state**. * getState function: In order to get information from the sensors and sent to observers,therefore,the update function is gonna call the getState function,this is why Concrete_observer needs to import(has a) Concrete_observable. * update function: Because we want to get the information from IObservable by getState function,therefore,we will new a IObservable object in the update constructor. ## Implement ### java Files configuration : * **Lab4** * **classes** * weatherStation.class * mainexe.class * phone.class * **interface** * **IObserve** * IObserve.class * IObservable.class * IObservable.java * IObserve.java * phone.java * mainexe.java * weatherStation.java * IObservable ``` java= import IObserve.*; public interface IObservable { void add(IObserve o); void remove(IObserve o); void Notify(); } ``` * IObserve ``` java= package IObserve; public interface IObserve { void update(); } ``` * weatherStation ``` java= import java.util.*; import IObserve.*; public class weatherStation implements IObservable { List<IObserve> observes = new ArrayList<>(); public static double temp = 36; @Override public void add(IObserve o) { this.observes.add(o); } @Override public void remove(IObserve o) { this.remove(o); } public void Adjust(double k) { temp += k; } public void Notify() { for(IObserve o: observes) { o.update(); } } public double getState() { return temp; } } ``` * phone ```java= import IObserve.*; public class phone implements IObserve { weatherStation server ; public phone(weatherStation server) { this.server = server ; } public void update() { System.out.println(server.getState()); } } ``` * mainexe ```java= import IObserve.*; public class mainexe { public static void main(String arg[]) { weatherStation s1 =new weatherStation(); phone apple = new phone(s1); phone samsung = new phone(s1); s1.add(apple); s1.add(samsung); while(true) { s1.Adjust(2.0); if(s1.temp > 37) { System.out.println("bebe"); s1.Notify(); } s1.Adjust(-2.1); } //when the state changes, //weatherStation will notify all of the observers that in the list, //and observers are gonna update. //Output : /* bebe 38.0 38.0 bebe 37.9 37.9 bebe 37.8 37.8 bebe 37.699999999999996 37.699999999999996 bebe 37.599999999999994 37.599999999999994 bebe 37.49999999999999 37.49999999999999 bebe 37.39999999999999 37.39999999999999 bebe */ } } ``` ### c++ ```cpp #include <iostream> #include <vector> using namespace std; class IObserver { public: IObserver(){} virtual ~IObserver(){} virtual void update()= 0; }; class IObservable { public: IObservable(){} virtual ~IObservable(){} virtual void addO(IObserver* o) = 0; virtual void removeO(IObserver* o)= 0; virtual void notifyO()= 0; }; class weatherSation : public IObservable { public: weatherSation(double t):temp(t){} virtual ~weatherSation(){} virtual void addO(IObserver* o); virtual void removeO(IObserver* o); virtual void notifyO(); double getTemp(); void setTemp(double t); vector<IObserver*> OBs; private: double temp; }; void weatherSation::setTemp(double t) { this->temp = t; this->notifyO(); } double weatherSation::getTemp() { return this->temp; } void weatherSation::addO(IObserver* o) { this->OBs.push_back(o); } void weatherSation::removeO(IObserver* o) { //vector is not able to support remove a specific element // this->OBs.erase(*o); } void weatherSation::notifyO() { for(auto& o : this->OBs) o->update(); } class phone : public IObserver { public: phone(weatherSation* _ws):WS(_ws){} virtual ~phone(){} virtual void update(); weatherSation* WS; }; void phone::update() { cout << this->WS->getTemp() << "\n"; } int main() { weatherSation* WS1 = new weatherSation(35.5); IObserver* apple = new phone(WS1); IObserver* samsung = new phone(WS1); cout << "One phone\n"; WS1->addO(apple); WS1->setTemp(77.7); WS1->setTemp(35.5); cout << "new phone\n"; WS1->addO(samsung); WS1->setTemp(87.8); return 0; } ``` ## Reference https://www.youtube.com/watch?v=_BpmfnqjgzQ&list=PLrhzvIcii6GNjpARdnO4ueTUAVR9eMBpc&index=2 ###### tags: `Design Pattern` `Java` `教學`