1. 程式人生 > 其它 >設計模式——觀察者模式

設計模式——觀察者模式

設計模式——觀察者模式

觀察者模式定義一對多的關係的依賴關係,當一個對像的狀態改變時,所有依賴它的對都都將收到通知,並被自動更新。就好像你在幹活兒,你的組長、主管、經理都在看著你、觀察你。當你的狀態變化時就通知他們所有人,他們做出相應的處理,你就是被觀察的目標。要實現觀察都模式,我們需要定義目標類,觀察者類。


import java.util.ArrayList;
import java.util.List;
//定義一個觀察目標類
public class Subject {
   //定義一個列表,儲存所有觀察者,當狀態發生改變時通知他們
   private List<Observer> observers 
      = new ArrayList<Observer>();
   //狀態
   private int state;
 
   public int getState() {
      return state;
   }
 
   public void setState(int state) {
      this.state = state;
      notifyAllObservers();
   }
   //新增觀察者的介面
   public void attach(Observer observer){
      observers.add(observer);      
   }
 //狀態改變時的通知介面,遍歷所有觀察者,並呼叫更新介面
   public void notifyAllObservers(){
      for (Observer observer : observers) {
         observer.update();
      }
   }  
}
//定義一個抽像觀察者類
public abstract class Observer {
   //觀察目標
   protected Subject subject;
   //更新介面
   public abstract void update();
}
//定義具體的觀察者比如經理、主管、組長
public class Manager extends Observer{
    public Manager(Subject subject){
        this.subject = subject;
        this.subject.attach(this);
    }
    @Override
    public void update(){
        System.out.println("我是經理,我收到了員工的通知");
    }
}
//組長
public GroupLeader extends Observer{
    public GroupLeader(Subject subject){
        this.subject = subject;
        this.subject.attach(this);
    }
    @Override
    public void update(){
        System.out.println("我是組長,我收到了員工的通知");
    }
}
//使用示例
public class Demo{
    public static void main(string[] args){
        Subject subject=new Subject();
        new Manager(subject);
        new GroupLeader(subject);
        subject.setState(10);
    }
}

c++的實現

//定義一個抽像觀察者類
class Observer {
   //觀察目標
protected: 
   Subject* subject;
   //更新介面
public:
  virtual void update() =0;
}
//定義一個觀察目標類
class Subject {
   //定義一個列表,儲存所有觀察者,當狀態發生改變時通知他們
private:
   std::list<Observer*> observers;
   //狀態
   int state;
 
public: 
  int getState() {
      return state;
   }
   void setState(int state) {
      this->state = state;
      notifyAllObservers();
   }
   //新增觀察者的介面
   void attach(Observer* observer){
      observers.push_back(observer);      
   }
 //狀態改變時的通知介面,遍歷所有觀察者,並呼叫更新介面
   void notifyAllObservers(){
      for (Observer *observer : observers) {
         observer->update();
      }
   }  
}

//定義具體的觀察者比如經理、主管、組長
class Manager :public Observer{
public: 
    Manager(Subject* subject){
        this->subject = subject;
        this->subject->attach(this);
    }
   void update() override {
        std::cout << "我是經理,我收到了員工的通知" << std::endl;;
    }
}
//組長
class GroupLeader :public Observer{
    public: GroupLeader(Subject* subject){
        this->subject = subject;
        this->subject->attach(this);
    }
    
     void update() override{
        std::cout << "我是組長,我收到了員工的通知" << std::endl;
    }
}
//呼叫示例
int main(){
    Subject subject;
    auto a = new Manager(&subject);
    auto b = new GroupLeader(&subject);
    subject.setState(20);
    return 0;
}

優點:
1、觀察者模式可以實現表示層和資料邏輯層的分離,定義了穩定的訊息傳遞機制,並抽象了更新介面,使得可以有各種各樣的表示層充當具體的觀察者角色。
2、觀察者模式在觀察目標和觀察者之間建立一個抽象的耦合。觀察者物件只需要維持一個抽象觀察者的集合,無需瞭解其具體觀察者。
3、觀察者模式支援廣播通訊,觀察目標會向所有已註冊的觀察者傳送通知,降低了一對多系統的設計難度。
4、觀察者模式滿足開閉原則的要求,增加新的具體觀察者無須修改原有的系統程式碼。

缺點:
1、如果一個被觀察者物件有很多的直接和間接的觀察者的話,將所有的觀察者都通知到會花費很多時間。
2、如果在觀察者和觀察目標之間有迴圈依賴的話,觀察目標會觸發它們之間進行迴圈呼叫,可能導致系統崩潰。
3、觀察者模式沒有相應的機制讓觀察者知道所觀察的目標物件是怎麼發生變化的,而僅僅只是知道觀察目標發生了變化。

使用場景:

一個抽象模型有兩個方面,其中一個方面依賴於另一個方面。將這些方面封裝在獨立的物件中使它們可以各自獨立地改變和複用。
一個物件的改變將導致其他一個或多個物件也發生改變,而不知道具體有多少物件將發生改變,可以降低物件之間的耦合度。
一個物件必須通知其他物件,而並不知道這些物件是誰。
需要在系統中建立一個觸發鏈,A物件的行為將影響B物件,B物件的行為將影響C物件……,可以使用觀察者模式建立一種鏈式觸發機制。