使用委托的超级简单的 C # 观察者/可观察者示例

我最近开始深入研究 C # ,但是我一辈子都搞不清楚在语言中实现观察者/可观察模式时代理是如何工作的。

有人能给我举个超级简单的例子吗?我在 上谷歌了一下,但是我发现所有的例子要么是太具体的问题,要么是太“臃肿”了。

154416 次浏览

观察者模式通常是由 事件实现的。

这里有一个例子:

using System;


class Observable
{
public event EventHandler SomethingHappened;


public void DoSomething() =>
SomethingHappened?.Invoke(this, EventArgs.Empty);
}


class Observer
{
public void HandleEvent(object sender, EventArgs args)
{
Console.WriteLine("Something happened to " + sender);
}
}


class Test
{
static void Main()
{
Observable observable = new Observable();
Observer observer = new Observer();
observable.SomethingHappened += observer.HandleEvent;


observable.DoSomething();
}
}

有关更多细节,请参见链接文章。

请注意,上面的示例使用 C # 6 无条件的操作符来安全地实现 DoSomething,以处理 SomethingHappened尚未订阅的情况,因此为 null。如果你使用的是旧版本的 C # ,你需要这样的代码:

public void DoSomething()
{
var handler = SomethingHappened;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}

这里有一个简单的例子:

public class ObservableClass
{
private Int32 _Value;


public Int32 Value
{
get { return _Value; }
set
{
if (_Value != value)
{
_Value = value;
OnValueChanged();
}
}
}


public event EventHandler ValueChanged;


protected void OnValueChanged()
{
if (ValueChanged != null)
ValueChanged(this, EventArgs.Empty);
}
}


public class ObserverClass
{
public ObserverClass(ObservableClass observable)
{
observable.ValueChanged += TheValueChanged;
}


private void TheValueChanged(Object sender, EventArgs e)
{
Console.Out.WriteLine("Value changed to " +
((ObservableClass)sender).Value);
}
}


public class Program
{
public static void Main()
{
ObservableClass observable = new ObservableClass();
ObserverClass observer = new ObserverClass(observable);
observable.Value = 10;
}
}

注:

  • 这违反了一条规则,即我不会将观察者从可观察的事件中解脱出来,这对于这个简单的例子来说可能已经足够好了,但是要确保观察者不会像那样被你的事件牵着鼻子走。处理这个问题的一种方法是使 ObserverClass IDisposable,并让。方法执行与构造函数中的代码相反的操作
  • 没有执行错误检查,至少应该在 ObserverClass 的构造函数中执行空检查

我已经把上面的几个很好的例子(感谢 斯基特先生卡尔森先生)结合起来,包括了几个不同的可观测数据,并利用一个接口在《观察者》中跟踪它们,允许《观察者》通过一个内部列表“观察”任意数量的可观测数据:

namespace ObservablePattern
{
using System;
using System.Collections.Generic;


internal static class Program
{
private static void Main()
{
var observable = new Observable();
var anotherObservable = new AnotherObservable();


using (IObserver observer = new Observer(observable))
{
observable.DoSomething();
observer.Add(anotherObservable);
anotherObservable.DoSomething();
}


Console.ReadLine();
}
}


internal interface IObservable
{
event EventHandler SomethingHappened;
}


internal sealed class Observable : IObservable
{
public event EventHandler SomethingHappened;


public void DoSomething()
{
var handler = this.SomethingHappened;


Console.WriteLine("About to do something.");
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
}


internal sealed class AnotherObservable : IObservable
{
public event EventHandler SomethingHappened;


public void DoSomething()
{
var handler = this.SomethingHappened;


Console.WriteLine("About to do something different.");
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
}


internal interface IObserver : IDisposable
{
void Add(IObservable observable);


void Remove(IObservable observable);
}


internal sealed class Observer : IObserver
{
private readonly Lazy<IList<IObservable>> observables =
new Lazy<IList<IObservable>>(() => new List<IObservable>());


public Observer()
{
}


public Observer(IObservable observable) : this()
{
this.Add(observable);
}


public void Add(IObservable observable)
{
if (observable == null)
{
return;
}


lock (this.observables)
{
this.observables.Value.Add(observable);
observable.SomethingHappened += HandleEvent;
}
}


public void Remove(IObservable observable)
{
if (observable == null)
{
return;
}


lock (this.observables)
{
observable.SomethingHappened -= HandleEvent;
this.observables.Value.Remove(observable);
}
}


public void Dispose()
{
for (var i = this.observables.Value.Count - 1; i >= 0; i--)
{
this.Remove(this.observables.Value[i]);
}
}


private static void HandleEvent(object sender, EventArgs args)
{
Console.WriteLine("Something happened to " + sender);
}
}
}

我不想改变我的源代码来添加额外的观察者,所以我写了以下简单的例子:

//EVENT DRIVEN OBSERVER PATTERN
public class Publisher
{
public Publisher()
{
var observable = new Observable();
observable.PublishData("Hello World!");
}
}


//Server will send data to this class's PublishData method
public class Observable
{
public event Receive OnReceive;


public void PublishData(string data)
{
//Add all the observer below
//1st observer
IObserver iObserver = new Observer1();
this.OnReceive += iObserver.ReceiveData;
//2nd observer
IObserver iObserver2 = new Observer2();
this.OnReceive += iObserver2.ReceiveData;


//publish data
var handler = OnReceive;
if (handler != null)
{
handler(data);
}
}
}


public interface IObserver
{
void ReceiveData(string data);
}


//Observer example
public class Observer1 : IObserver
{
public void ReceiveData(string data)
{
//sample observers does nothing with data :)
}
}


public class Observer2 : IObserver
{
public void ReceiveData(string data)
{
//sample observers does nothing with data :)
}
}
    /**********************Simple Example ***********************/


class Program
{
static void Main(string[] args)
{
Parent p = new Parent();
}
}


////////////////////////////////////////////


public delegate void DelegateName(string data);


class Child
{
public event DelegateName delegateName;


public void call()
{
delegateName("Narottam");
}
}


///////////////////////////////////////////


class Parent
{
public Parent()
{
Child c = new Child();
c.delegateName += new DelegateName(print);
//or like this
//c.delegateName += print;
c.call();
}


public void print(string name)
{
Console.WriteLine("yes we got the name : " + name);
}
}

大概是这样:

// interface implementation publisher
public delegate void eiSubjectEventHandler(eiSubject subject);


public interface eiSubject
{
event eiSubjectEventHandler OnUpdate;


void GenereteEventUpdate();


}


// class implementation publisher
class ecSubject : eiSubject
{
private event eiSubjectEventHandler _OnUpdate = null;
public event eiSubjectEventHandler OnUpdate
{
add
{
lock (this)
{
_OnUpdate -= value;
_OnUpdate += value;
}
}
remove { lock (this) { _OnUpdate -= value; } }
}


public void GenereteEventUpdate()
{
eiSubjectEventHandler handler = _OnUpdate;


if (handler != null)
{
handler(this);
}
}


}


// interface implementation subscriber
public interface eiObserver
{
void DoOnUpdate(eiSubject subject);


}


// class implementation subscriber
class ecObserver : eiObserver
{
public virtual void DoOnUpdate(eiSubject subject)
{
}
}

. 事件的观察者模式 C # . 链接到存储库

观察者模式C # 中的委托和事件一起应用,根据略有变化的 MSDN命名为 “事件模式”

在本文中,您将找到一些结构良好的示例,说明如何以传统的方式以及使用委托和事件来应用 c # 中的模式。

探索观察者设计模式

public class Stock
{


//declare a delegate for the event
public delegate void AskPriceChangedHandler(object sender,
AskPriceChangedEventArgs e);
//declare the event using the delegate
public event AskPriceChangedHandler AskPriceChanged;


//instance variable for ask price
object _askPrice;


//property for ask price
public object AskPrice
{


set
{
//set the instance variable
_askPrice = value;


//fire the event
OnAskPriceChanged();
}


}//AskPrice property


//method to fire event delegate with proper name
protected void OnAskPriceChanged()
{


AskPriceChanged(this, new AskPriceChangedEventArgs(_askPrice));


}//AskPriceChanged


}//Stock class


//specialized event class for the askpricechanged event
public class AskPriceChangedEventArgs : EventArgs
{


//instance variable to store the ask price
private object _askPrice;


//constructor that sets askprice
public AskPriceChangedEventArgs(object askPrice) { _askPrice = askPrice; }


//public property for the ask price
public object AskPrice { get { return _askPrice; } }


}//AskPriceChangedEventArgs

在这个模型中,有一些发布者将执行一些逻辑并发布一个“事件”
发布服务器然后将其事件仅发送给已订阅接收特定事件的订阅服务器。

在 C # 中,任何对象都可以发布一组其他应用程序可以订阅的事件。
当发布类引发事件时,将通知所有订阅的应用程序。
下图显示了这种机制。

enter image description here

C # : 中事件和委托的最简单示例

代码是不言而喻的,而且我已经添加了注释来清除代码。

  using System;


public class Publisher //main publisher class which will invoke methods of all subscriber classes
{
public delegate void TickHandler(Publisher m, EventArgs e); //declaring a delegate
public TickHandler Tick;     //creating an object of delegate
public EventArgs e = null;   //set 2nd paramter empty
public void Start()     //starting point of thread
{
while (true)
{
System.Threading.Thread.Sleep(300);
if (Tick != null)   //check if delegate object points to any listener classes method
{
Tick(this, e);  //if it points i.e. not null then invoke that method!
}
}
}
}


public class Subscriber1                //1st subscriber class
{
public void Subscribe(Publisher m)  //get the object of pubisher class
{
m.Tick += HeardIt;              //attach listener class method to publisher class delegate object
}
private void HeardIt(Publisher m, EventArgs e)   //subscriber class method
{
System.Console.WriteLine("Heard It by Listener");
}


}
public class Subscriber2                   //2nd subscriber class
{
public void Subscribe2(Publisher m)    //get the object of pubisher class
{
m.Tick += HeardIt;               //attach listener class method to publisher class delegate object
}
private void HeardIt(Publisher m, EventArgs e)   //subscriber class method
{
System.Console.WriteLine("Heard It by Listener2");
}


}


class Test
{
static void Main()
{
Publisher m = new Publisher();      //create an object of publisher class which will later be passed on subscriber classes
Subscriber1 l = new Subscriber1();  //create object of 1st subscriber class
Subscriber2 l2 = new Subscriber2(); //create object of 2nd subscriber class
l.Subscribe(m);     //we pass object of publisher class to access delegate of publisher class
l2.Subscribe2(m);   //we pass object of publisher class to access delegate of publisher class


m.Start();          //starting point of publisher class
}
}

输出:

从听众那里听到的

由 Listener2提供

从听众那里听到的

由 Listener2提供

从听众那里听到的 . . . (无限次)