乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      設計模式(20) 觀察者模式

       丹楓無跡 2021-07-12

      觀察者模式是一種平時接觸較多的模式。它主要用于一對多的通知發(fā)布機制,當一個對象發(fā)生改變時自動通知其他對象,其他對象便做出相應的反應,同時保證了被觀察對象與觀察對象之間沒有直接的依賴。

      GOF對觀察者模式的描述為:
      Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically..
      — Design Patterns : Elements of Reusable Object-Oriented Software

      觀察者模式的適用場景

      • 當存在一類對象通知關系上依賴于另一類對象的時候,把它們進行抽象,確保兩類對象的具體實現(xiàn)都可以相對獨立的變化,但它們交互的接口保持穩(wěn)定。
      • 一個類型狀態(tài)變化時,需要通知的對象的數(shù)量不固定,會有增加或刪除若干被通知對象的情況。
      • 需要讓目標對象與被通知對象之間保持松散耦合的時間。

      UML類圖如下:

      代碼實例

      public interface IObserver<T>
      {
          void Update(SubjectBase<T> subject);
      }
      
      public abstract class SubjectBase<T>
      {
          protected IList<IObserver<T>> observers = new List<IObserver<T>>();
      
          protected T state;
          public virtual T State
          {
              get { return state; }
          }
      
          //Attach
          public static SubjectBase<T> operator +(SubjectBase<T> subject, IObserver<T> observer)
          {
              subject.observers.Add(observer);
              return subject;
          }
      
          //Detach
          public static SubjectBase<T> operator -(SubjectBase<T> subject, IObserver<T> observer)
          {
              subject.observers.Remove(observer);
              return subject;
          }
      
          //更新各觀察者
          public virtual void Notify()
          {
              foreach (var observer in observers)
              {
                  observer.Update(this);
              }
          }
      
          public virtual void Update(T state)
          {
              this.state = state;
              Notify();//觸發(fā)對外通知
          }
      }
      
      public class Subject<T> : SubjectBase<T> { }
      
      public class Observer<T> : IObserver<T>
      {
          public T State;
          public void Update(SubjectBase<T> subject)
          {
              this.State = subject.State;
          }
      }
      

      調(diào)用端

      static void Main(string[] args)
      {
          SubjectBase<int> subject = new Subject<int>();
          Observer<int> observer1 = new Observer<int>();
          observer1.State = 10;
          Observer<int> observer2 = new Observer<int>();
          observer2.State = 20;
          subject += observer1;
          subject += observer2;
          subject.Update(30);
          Console.WriteLine($"ob1:{observer1.State}  ob2:{observer2.State}");
          //ob1:30 ob2:30 兩個觀察者都發(fā)生了變化
          subject -= observer2;
          subject.Update(40);
          Console.WriteLine($"ob1:{observer1.State}  ob2:{observer2.State}");
          //ob1:40 ob2:30 observer2被移除,不會跟隨變化
      }
      

      這里的被觀察者繼承基類SubjectBase,觀察者實現(xiàn)接口IObserver。SubjectBase和IObserver相互依賴,SubjectBase本身不知道會有哪些具體IObserver類型希望獲得它的更新通知,具體的Observer類型也并不需要關心目標類型,只需要依賴SubjectcBase,所以實際上一個觀察者可以跟蹤多個被觀察者。

      推模式和拉模式

      根據(jù)當目標對象狀態(tài)更新的時候,觀察者更新自己數(shù)據(jù)的方式,可以將觀察者模式分為推模式和拉模式。

      • 推模式:目標對象在通知里把需要更新的信息作為參數(shù)提供給IObserver的Update()方法。采用這種方式,觀察者只能只能被動接受,如果推送的內(nèi)容比較多,那么對網(wǎng)絡、內(nèi)存或者I/O的開銷就會很大。

      • 拉模式:目標對象僅僅告訴觀察者有新的狀態(tài),至于該狀態(tài)是什么,則需要觀察者主動訪問目標對象來獲取。這種方式下,觀察者獲取信息的時機和內(nèi)容都可以自主決定,但如果觀察者沒有及時獲取信息,就會漏掉之前通知的內(nèi)容。

      前面的代碼示例是兩種方式的結(jié)合,看起來像是推模式,但他推送的是一個SubjectBase的引用,觀察者可以根據(jù)需要通過這個引用訪問到具體的狀態(tài),從這個角度看又是拉模式。

      事件

      .NET中的事件機制也可以看作觀察者模式,事件所定義的委托類型本身就是個抽象的觀察者,而且相對經(jīng)典的觀察者模式,事件更加簡單、靈活,耦合也更加松散。
      代碼示例

      public class UserEventArgs : EventArgs
      {
          public string Name { get; }
          public UserEventArgs(string name)
          {
              this.Name = name;
          }
      }
      
      public class User
      {
          public event EventHandler<UserEventArgs> NameChanged;
          private string name;
          public string Name
          {
              get { return name; }
              set
              {
                  name = value;
                  NameChanged(this, new UserEventArgs(value));
              }
          }
      }
      
      

      觀察者,注冊事件

      public class Test
      {
          public static void Entry()
          {
              User user = new User();
              user.NameChanged += (sender, args) =>
              {
                  Console.WriteLine(args.Name);
              };
              user.Name = "Andy";
          }
      }
      

      觀察者模式的缺點

      • 如果觀察者比較多,逐個通知會相對耗時。
      • 測試和調(diào)試相比直接依賴更加困難。
      • 可能導致內(nèi)存泄漏,即使所有觀察者都已經(jīng)失效了,但如果它們沒有注銷對主題對象的觀察,那么觀察者和主題對象間的這種相互的引用關系,會使雙方無法被GC回收。

      參考書籍:
      王翔著 《設計模式——基于C#的工程化實現(xiàn)及擴展》

        本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多