C#设计模式之:观察者模式与委托

观察者模式:

定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

UML

C#设计模式之:观察者模式与委托_第1张图片

CODE

abstract class Observer
{
    public abstract void Update();
}
abstract class Subject
{
    private List observers = new List();

    public void Attach(Observer observer)
    {
        observers.Add(observer);
    }
    public void Detach(Observer observer)
    {
        observers.Remove(observer);
    }

    public void Notify()
    {
        foreach (Observer o in observers)
        {
            o.Update();
        }
    }
}
class ConcreteSubject1 : Subject
{
    private string subjectState;

    public string SubjectState { get => subjectState; set => subjectState = value; }
}
class ConcreteObserver1 : Observer
{
    private string name;
    private string observerState;
    private ConcreteSubject1 subject;

    public ConcreteObserver1(ConcreteSubject1 subject, string name)
    {
        this.Subject = subject;
        this.name = name;
    }

    public override void Update()
    {
        observerState = Subject.SubjectState;
        Console.WriteLine("观察者{0}的新状态是{1}", name, observerState);
    }

    public ConcreteSubject1 Subject
    {
        get => subject;
        set => subject = value;
    }
}
// test
ConcreteSubject1 s = new ConcreteSubject1();
s.Attach(new ConcreteObserver1(s, "X"));
s.Attach(new ConcreteObserver1(s, "Y"));
s.Attach(new ConcreteObserver1(s, "Z"));

s.SubjectState = "ABC";
s.Notify();
// result
观察者X的新状态是ABC
观察者Y的新状态是ABC
观察者Z的新状态是ABC

应该在什么时候使用观察者模式?

当一个对象的改变需要同时改变其它对象时,而且不必知道具体有多少对象要改变


本质

解除耦合,让耦合的双方都依赖于抽象,则不是依赖于具体,从而使得各自的变化都不会影响另一边的变化


缺陷

如果通知者与观察者之间互相不可以认识或无法认识


C#中使用委托来解决缺陷

interface Subject
{
   void Notify();

   string SubjectState
   {
       get;
       set;
   }
}
class StockObserver
{
    private string name;
    private Subject sub;

    public StockObserver(string name, Subject sub)
    {
        this.name = name;
        this.sub = sub;
    }

    public void CloseStockMarket()
    {
        Console.WriteLine("{0} {1}关闭股票行情,继续工作!", sub.SubjectState, name);
    }
}
class NBAObserver
{
    private string name;
    private Subject sub;

    public NBAObserver(string name, Subject sub)
    {
        this.name = name;
        this.sub = sub;
    }

    public void CloseNBADirectSeeding()
    {
        Console.WriteLine("{0} {1}关闭NBA直播,继续工作!", sub.SubjectState, name);
    }
}
delegate void EventHandler(); // 关键点1

class Boss : Subject
{
    public event EventHandler Update; // 关键点2

    private string action;
    public string SubjectState
    {
        get { return action; }
        set { action = value; }
    }

    public void Notify()
    {
        Update(); // 关键点3
    }
}
// test
Boss boss = new Boss();

StockObserver stock = new StockObserver("股民", boss);
NBAObserver nba = new NBAObserver("球迷", boss);

boss.Update += new EventHandler(stock.CloseStockMarket);
boss.Update += new EventHandler(nba.CloseNBADirectSeeding);

boss.SubjectState = "老板来了!";
boss.Notify();
// result
老板来了! 股民关闭股票行情,继续工作!
老板来了! 球迷关闭NBA直播,继续工作!

委托是什么?

委托是一种引用方法的类型。一旦为委托分配了方法,委托将与该方法具有完全相同的行为。
委托方法的使用可以像其他任何方法一样,具有参数和返回值。
委托可以看作是对函数的抽象,是函数的“类“,委托的实例将代表一个具体的函数。

delegate void EventHandler();       // 理解为声明了一个特殊的类
public event EventHandler Update;   // 解理为声明了一个类的变量
new EventHandler(stock.CloseStockMarket); // 一个委托的实例

一个委托可以搭载多个方法,所有方法被依次唤起,最重要的是,它可以便得委托对象所搭载的方法并不需要属于同一个类


委托的前提

委托对象所搭载的所有方法必须具有相同的原形和形式,也就是拥有相同的参数列表和返回值类型

你可能感兴趣的:(C#,设计模式)