参考《大话设计模式》

业务场景

人物:老板,秘书,看股票的同事A, 看股票的同事B

逻辑:老板到办公室,秘书提醒同事xxxxxxx

>>第一版(双向耦合)

秘书类:

public class Secretary
{
    private IList<StockObserver> _Observers = new List<StockObserver>();
    
    private string _Action;

    //添加需要秘书通知的对象
    public void Attach(StockObserver observer)
    {
        observers.Add(observer);
    }
    
    //秘书发出通知
    public void Notify()
    {
        foreach(var ob in _Observers)
        {
            ob.Update();
        }
    }

    //秘书的通知内容
    public string SecretaryAction
    {
       get{return _Action;}
       set{_Action = value;}
    }
}

 

看股票的同事类:

public class StockObserver
{
   private string _Name;
   private Secretary _Sub;
   
   public StockObserver(string name, Secretary sub)
   {
        _Name = name;
        _Sub = sub;
   }
   public void Update()
   {
        Console.WriteLine("{0} {1}关闭股票行情,继续工作",
                                    sub.SecretaryAction, _Name);
   }
}

客户端:

static void Main(string[] args)
{
   Secretary sec = new Secretary();
   
   StockObserver sto1 = new StockObserver("同事A", sec);
   StockObserver sto2 = new StockObserver("同事B", sec);
   //秘书登记下两位要被通知的同事
   sec.Attach(sto1);
   sec.Attach(sto2);
   
   sec.SecretaryAction = "老板来了";
   sec.Notify();
}

缺点:
1. 秘书类和看股票同事类相关耦合在一起, 秘书类需要增加看股票者, 看股票者需要访问秘书类的信息。

2. 如果要添加看NBA同事类, 秘书类也要跟着修改,不符合开闭原则。

 

> >解耦版1

抽象观察者:

public abstract class Observer
{
   private string _Name;
   private Secretary _Sub;
   
   public Observer(string name, Secretary sub)
   {
        _Name = name;
        _Sub = sub;
   }
   public abstract void Update();
}


具体观察者-看股票的同事:

public class StockObserver : Observer
{
     public StockObserver(string name, Secretary sub) : base(name, sub)
     {
     }
     
      public override void Update()
      {
          Console.WriteLine("{0} {1} 关闭股票行情, 继续工作!",
                                     sub.SecretaryAction, name);
      }
}

具体观察者-看NBA的同事:

public NBAObserver : Observer
{
    public NBAObserver(string name, Secretary sub) : base(name, sub)
    {
    }

     public override void Update()
     {
         Console.WriteLine("{0} {1} 关闭NBA直播,继续工作!",
                                    sub.SecretaryAction, name);
     }
}

秘书类:

public class Secretary
{
    private IList<Observer> _Observers = new List<Observer>();

    private string _Action;
    public string SecretaryAction
    {
        get{return _Action;}
        set{_Action = value;}
    }

    //add observer
    public void Attach(Observer observer)
    {
        _Observers.Add(observer);
    }

    //remove observer
    public void Remove(Observer observer)
    {
        _Observer.Remove(observer);
    }

    public void Notify()
    {
        foreach(var ob in obs)
        {
            ob.Update();
        }
        observers.foreach(obs => obs.update());
    }
}

缺点: 通过观察者抽象类完成了秘书类中对观察者类地解耦,但在具体观察者类中仍和秘书类存在耦合(观察者不应依赖具体的通知者)。

 

> > 解耦版二

通知者抽象类:

public abstract class Subject
{
    public abstract void Attach(Observer observer);
    public abstract void Remove(Observer observer);
    public abstract void Notify();
    public string SubjectAction{ get; set; }
}

 

秘书类:

public class  Secretary : Subject
{
     private IList<Observer> _Observers = new List<Observer>();
     
     public override void Attach(Observer observer)
     {
         _Observers .Add(observer);
     }
     
     public override void Remove(Observer observer)
     {
          _Observers .Remove(observer);
     }

      public override void Notify()
      {
           foreach(var ob in _Observers)
           {
                ob.Update();
           }
      }
}

 

观察者—看股票者:

public class StockObserver : Observer
{
     public StockObserver(string name, Subject sub) : base(name, sub)
     {
     }
     
     public override void Update()
     {
         Console.WriteLine("{0} {1} 关闭股票行情, 继续工作!",
                                     _Sub.SubjectAction, _Name);
     }
}

 

观察者—看NBA者:

public class NBAObserver : Observer
{
     public NBAObserver(string name, Subject sub) : base(name, sub)
     {
     }
     
     public override void Update()
     {
         Console.WriteLine("{0} {1} 关闭NBA, 继续工作!",
                                     _Sub.SubjectAction, _Name);
     }
}

 


客户端:

Secretary sec = new Secretary();
StockObserver sto = new StockObserver("Tom", sec);
NBAObserver no = new NBAObserver("Jack", sec);
sec.Attach(sto);
sec.Attach(no );
sec.SubjectAction = "Boss is coming";
sec.Notify();

 

类图: