在此应用程序中,观察者处理对象网络中的状态更改。所有对象都是基于相同BaseObject类的派生类。 BaseObject提供重要的识别和导航功能。C#类型特定观察者
从BaseObject派生的类由代码生成器创建。这些类应具有最小的占用空间,并专注于特定的状态和行为。
在应用程序级别,观察者处理BaseObject派生类中的状态更改,通常对于多个类而言,并且通常对于大量BaseObject派生实例。
在当前的解决方案中,BaseObject管理观察者并以BaseObject实例作为发件人通知观察者。
using System;
using System.Collections.Generic;
namespace Observer {
#region underlying framework foundation
interface IObserver {
void ObjectChanged (BaseObject obj);
}
abstract class BaseObject {
HashSet<IObserver> observers = new HashSet<IObserver>();
public void RegisterObserver (IObserver observer) {
observers.Add (observer);
}
public void FireObjectChanged() {
foreach (var obs in observers)
obs.ObjectChanged (this);
}
}
#endregion underlying framework foundation
#region code generator
class DerivedObject1 : BaseObject {
}
class DerivedObject2 : BaseObject {
}
#endregion code generator
#region application code
class Observer : IObserver {
public void ObjectChanged (BaseObject obj) {
Console.WriteLine (obj.GetType().Name);
if (obj is DerivedObject1) {
} else if (obj is DerivedObject2) {
}
}
}
#endregion application code
#region sample
class Program {
static void Main (string[] args) {
Observer observer = new Observer();
List<BaseObject> objects = new List<BaseObject>();
DerivedObject1 obj1 = new DerivedObject1();
objects.Add (obj1);
obj1.RegisterObserver (observer);
DerivedObject2 obj2 = new DerivedObject2();
objects.Add (obj2);
obj2.RegisterObserver (observer);
foreach (var bo in objects)
bo.FireObjectChanged();
}
}
#endregion sample
}
我不喜欢那种方法是观察者必须在运行时识别发送者类型。相反,我想在编译时保证安全。
所以我提出了一种新的方法,它引入了泛型和第二个BaseObject层,它包含类型安全的观察者。
using System;
using System.Collections.Generic;
namespace Observer {
#region underlying framework foundation
interface IObserver<T> where T : BaseObjectT<T> {
void ObjectChanged (T obj);
}
abstract class BaseObject {
public abstract void FireObjectChanged();
}
abstract class BaseObjectT<T> : BaseObject where T : BaseObjectT<T> {
HashSet<IObserver<T>> observers = new HashSet<IObserver<T>>();
public void RegisterObserver (IObserver<T> observer) {
observers.Add (observer);
}
public override void FireObjectChanged() {
foreach (var obs in observers)
obs.ObjectChanged ((T)this);
}
}
#endregion underlying framework foundation
#region code generator
class DerivedObject1 : BaseObjectT<DerivedObject1> {
}
class DerivedObject2 : BaseObjectT<DerivedObject2> {
}
#endregion code generator
#region application code
class Observer :
IObserver<DerivedObject1>,
IObserver<DerivedObject2> {
public void ObjectChanged (DerivedObject1 obj) {
Console.WriteLine (obj.GetType().Name);
}
public void ObjectChanged (DerivedObject2 obj) {
Console.WriteLine (obj.GetType().Name);
}
}
#endregion application code
#region sample
class Program {
static void Main (string[] args) {
Observer observer = new Observer();
List<BaseObject> objects = new List<BaseObject>();
DerivedObject1 obj1 = new DerivedObject1();
objects.Add (obj1);
obj1.RegisterObserver (observer);
DerivedObject2 obj2 = new DerivedObject2();
objects.Add (obj2);
obj2.RegisterObserver (observer);
foreach (var bo in objects)
bo.FireObjectChanged();
}
}
#endregion sample
}
虽然这种方法,准确地我想要做什么在应用层面 - 通过派生类的实例,以观察者无需类型强制转换那里,不同IObserver方法实现的,允许超载 - 在底层我看起来有点难看。
我现在的问题,是有没有更好的,来完成这个更优雅的方式,特别是有没有办法避免FireObjectChanged)演员(
obs.ObjectChanged ((T)this);
,或者BaseObject和BaseObjectT结合成单个基类?
你不应该命名的东西'IObserver'除非,以及['IObserver '](https://msdn.microsoft.com/en-us/library/dd783449(V = VS。 110).aspx) –
Falanwe
2015-04-03 10:31:55