在此應用程序中,觀察者處理對象網絡中的狀態更改。所有對象都是基於相同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