我試圖獲得更好的感覺,以便如何維護可能交換的類的訂閱(更改策略)。即使這些例子是人爲設計的,我也會盡量保持這一點。如何管理對可交換類的訂閱
假設有一類皮膚
public class Skin
{
//Raised when the form needs to turn on/off a blinking light
public event BlinkEventHandler BlinkEvent;
//The back color that forms should use
public Color BackColor{ get; protected set; }
}
應用程序啓動時,它會讀取的目錄全配置文件用於不同的皮膚類。用戶可以隨時切換當前皮膚。
我目前的工作使用了一個非常奇怪的策略(IMO),看起來像這樣:
/// <summary>
/// Some class that can see when the Skin Changes
/// </summary>
public class SkinManager
{
//Raised when the Skin changes
public event SkinChangedEventHandler SkinChangedEvent;
private static Skin currentSkin;
public static Skin CurrentSkin {get;}
public SkinManager(){/* gets a skin into currentSkin */}
public void ChangeSkin()
{
//... do something to change the skin
if(SkinChangedEvent != null)
{
SkinChangedEvent(this, new SkinChangedEventArgs(/*args*/));
}
}
}
/// <summary>
/// Some form that follows the Skinning Strategy
/// </summary>
public class SkinnedForm : Form
{
private Skin skin;
public SkinnedForm()
{
skin = SkinManager.CurrentSkin;
if(skin != null)
{
skin.BlinkEvent += OnBlink;
}
SkinManager.SkinChangedEvent += OnSkinChanged;
}
private void OnSkinChanged(object sender, SkinChangedEventArgs e)
{
//unregister if we have a current skin
//the local was to ensure that the form unsubscribes
//when skin changes
if(skin != null)
{
skin.BlinkEvent -= OnBlink;
}
skin = SkinManager.CurrentSkin;
if(skin != null)
{
skin.BlinkEvent += OnBlink;
}
SkinChanged();
}
private void SkinChanged(){ Invalidate(); }
private void OnBlink(object sender, BlinkEventArgs e)
{
//... do something for blinking
}
}
我無法相信這是一個很好的實施,反而會希望看到這樣的事情:
/// <summary>
/// Some class that can see when the Skin Changes
/// </summary>
public class SkinManager
{
//Raised when the Skin changes
public event SkinChangedEventHandler SkinChangedEvent;
//Relays the event from Skin
public event BlinkEventHander BlinkEvent;
private static Skin currentSkin;
public static Skin CurrentSkin {get;}
public SkinManager()
{
//... gets a skin into currentSkin
currentSkin.BlinkEvent += OnBlink;
}
/// <summary>
/// Relays the event from Skin
/// </summary>
private void OnBlink(object sender, BlinkEventArgs e)
{
if(BlinkEvent != null)
{
BlinkEvent(this, e);
}
}
public void ChangeSkin()
{
//... do something to change the skin
if(SkinChangedEvent != null)
{
SkinChangedEvent(this, new SkinChangedEventArgs(/*args*/));
}
}
}
/// <summary>
/// Some form that follows the Skinning Strategy
/// </summary>
public class SkinnedForm : Form
{
//Do not need the local anymore
//private Skin skin;
public SkinnedForm()
{
SkinManager.CurrentSkin.BlinkEvent += OnBlink;
SkinManager.SkinChangedEvent += OnSkinChanged;
}
private void OnSkinChanged(object sender, SkinChangedEventArgs e)
{
//Only register with the manager, so no need to deal with
//subscription maintenance, could just directly to go SkinChanged();
SkinChanged();
}
private void SkinChanged() { Invalidate(); }
private void OnBlink(object sender, BlinkEventArgs e)
{
//... do something for blinking
}
}
我不確定這是否清楚,但主要是有一個局部變量,嚴格使用,以確保我們在訂閱新類上的事件之前取消訂閱事件。我認爲它是這樣的:我們實施了蒙皮策略模式(選擇您想要使用的蒙皮策略並運行它),但是每個策略實施都有我們直接訂閱的事件。當戰略發生變化時,我們希望我們的訂閱者觀看正確的發佈者,以便我們使用當地人。再次,我認爲這是一種可怕的方法。
是否有一個我爲使用管理器來監控所管理的類的所有事件並將它們傳遞的策略而改變並且訂戶繼續偵聽正確事件通知的轉換的名稱?所提供的代碼是在我形成問題時即時創建的,因此可以原諒任何錯誤。
太棒了,謝謝。這正是我所提議的,但要確保我沒有脫離基地。那麼這就是所謂的代理呢?出於某種原因,他們在這裏稱之爲提供者,但是當我查找模式時,它似乎不匹配。 – MPavlak 2011-06-08 14:51:49