C#設計模式(一)訂閱-釋出模式
本來是在持續開發Besige,但考慮到以後遲早會在設計模式這塊繼續擴充,就新開了一個標題,算是個開個頭。
模式這東西原本可以獨立於語言之外來說,但考慮到不同語言的實現畢竟有些差異,我本人搜尋文章時,也不喜歡搜出一堆其他語言的參考資料來,為了少製造些垃圾資訊積點德,就在標題前加了個C#。
訂閱-釋出模式又稱觀察者模式,很多資料只是介紹了個大致思想,很難找到把訂閱者和釋出者最大化解耦的參考程式碼。
我這裡貼個在我比較欣賞的一個設計上作了些許修改的版本:
using UnityEngine;
using System;
using System.Collections.Generic;
public class SubPubSystem
{
public Dictionary<string, Delegate> records = new Dictionary<string, Delegate>();
public void Subscribe(string name, Action method) { _Subscribe(name, method); }
public void Subscribe<T0>(string name, Action<T0> method) { _Subscribe(name, method); }
public void Subscribe<T0, T1>(string name, Action<T0, T1> method) { _Subscribe(name, method); }
public void Subscribe<T0, T1, T2>(string name, Action<T0, T1, T2> method) { _Subscribe(name, method); }
public void Subscribe<T0, T1, T2, T3>(string name, Action<T0, T1, T2, T3> method) { _Subscribe(name, method); }
public void UnSubscribe(string name, Action method) { _UnSubscribe(name, method); }
public void UnSubscribe<T0>(string name, Action<T0> method) { _UnSubscribe(name, method); }
public void UnSubscribe<T0, T1>(string name, Action<T0, T1> method) { _UnSubscribe(name, method); }
public void UnSubscribe<T0, T1, T2>(string name, Action<T0, T1, T2> method) { _UnSubscribe(name, method); }
public void UnSubscribe<T0, T1, T2, T3>(string name, Action<T0, T1, T2, T3> method) { _UnSubscribe(name, method); }
public void _Subscribe(string name, Delegate method)
{
Delegate d;
if (records.TryGetValue(name, out d))
{
d = Delegate.Combine(d, method);
records[name] = d;
}
else
{
records.Add(name, method);
}
}
public void _UnSubscribe(string name, Delegate method)
{
Delegate d;
if (records.TryGetValue(name, out d))
{
d = Delegate.Remove(d, method);
records[name] = d;
}
}
public void Publish(string name, params object[] args)
{
try
{
Delegate d;
if (records.TryGetValue(name, out d))
{
if (d != null)
{
d.DynamicInvoke(args);
}
}
else
{
records.Remove(name);
}
}
catch(Exception ex)
{
Debug.LogError(ex.Message);
}
}
}
使用也很簡單,在某個大系統模組裡new一個例項,在需要的地方呼叫其Subscribe、Publish方法就是了,假如遊戲規模小,甚至可以直接改成靜態類來用。
需要注意的點:
1.訂閱者方法若意外丟失了,比如Unity裡綁在某個物體上的指令碼隨著物體的銷燬也不見了,那釋出訊息呼叫時會引發異常。關於如何更好的探知呼叫的方法是否還存在的問題,幾個群問了下,沒得到很好的答覆,最好還是手工在OnDestroy裡UnSubscribe罷。若誰知道更好的方案,請賜教。
2.為簡單起見這裡最多隻支援四個引數,若需要更多引數,多複製貼上幾行就是了。
我個人還是很喜歡這個系統的簡單、靈活的。像.net framwork給出的EventHandler規範那種,還要自己繼承EventArgs寫許多訊息類,感覺略微有些麻煩。
暫時就在Besige中用這套系統來處理訊息事件了,以後遇到問題再完善。
最後說下下階段的計劃:
上文說到Besige還是留下大把的功能模組需要做,但我現在急切的想劍指另一塊垂涎已久的地盤——指令碼系統。
暫時把那些輕車熟路只是需要時間完成的工作放一放,先進入下一個相對陌生更有挑戰性的領域。
公司專案用的指令碼系統是自定義的一套DSL,虛擬機器也是自己寫的,感覺這樣完全沒必要,其技能指令碼甚至弱到連變數都沒法用。借用通用的指令碼語言和第三方庫明顯更實惠些,功能也更強大。
這樣具體來說無非就是Lua或Python了,Unity裡相對用Lua的明顯多一些,所以目標就鎖定在ulua_tolua上了,tolua的開發者同時提供了一個LuaFramework_NGUI/UGUI的框架,用來學習其架構也是不錯的。
我希望在消化其思想後,將ulua虛擬機器剝離出來,最小化的放進自己的專案,在此基礎上作一些指令碼程式設計的實踐,至少要做到用指令碼定義UI,然後視情況看能不能做點別的比如AI之類,甚至整個邏輯都拿lua來實現。
最後,搞定了這塊,很多小公司的面試者特別喜歡問的熱更新,自然也就搞定了。
最近工作也忙,整個週期可能會比較長,定在兩個月左右吧。
相關文章
- C#設計模式之訂閱釋出模式C#設計模式
- 設計模式之釋出訂閱模式(2) Redis 釋出/訂閱模式設計模式Redis
- 設計模式之釋出訂閱模式(1) 一文搞懂釋出訂閱模式設計模式
- js設計模式--釋出訂閱模式JS設計模式
- JS設計模式七:釋出-訂閱模式JS設計模式
- JavaScript設計模式系列--釋出訂閱模式JavaScript設計模式
- 每天一個設計模式之訂閱-釋出模式設計模式
- js進階-設計模式: 釋出訂閱模式JS設計模式
- javascript設計模式 之 5 釋出-訂閱模式JavaScript設計模式
- javascript中的設計模式之釋出-訂閱模式JavaScript設計模式
- 設計模式之單例、工廠、釋出訂閱者模式設計模式設計模式單例
- 釋出訂閱模式模式
- JavaScript 設計模式之觀察者模式與釋出訂閱模式JavaScript設計模式
- 設計模式學習之觀察者模式和釋出訂閱模式設計模式
- 設計模式讀書筆記之原型模式、釋出訂閱模式設計模式筆記原型
- JS訂閱釋出模式JS模式
- JavaScript設計模式之釋出-訂閱模式(觀察者模式)-Part2JavaScript設計模式
- 設計模式之釋出訂閱模式(5) Spring Events原始碼解析設計模式Spring原始碼
- 設計模式之釋出訂閱模式(4) Guava Eventbus 事件處理設計模式Guava事件
- 觀察者模式-訂閱釋出模式模式
- Javascript(七)釋出-訂閱模式JavaScript模式
- 釋出訂閱模式學習模式
- 觀察者模式 vs 釋出訂閱模式模式
- js 觀察者模式 訂閱釋出模式JS模式
- 設計模式之釋出訂閱模式(3) 深入Spring Events事件驅動模型設計模式Spring事件模型
- Spring 中的釋出-訂閱模式Spring模式
- 行為型:釋出訂閱模式模式
- MQTT 釋出/訂閱模式介紹MQQT模式
- 觀察者模式和釋出訂閱模式(上)模式
- 一分鐘理解 JavaScript 釋出訂閱模式JavaScript模式
- 每日一學:Publish/Subscribe釋出與訂閱模式模式
- 談談觀察者模式和釋出訂閱模式模式
- javascript(js) 觀察者模式和釋出訂閱模式JavaScriptJS模式
- 釋出訂閱 VS 觀察者模式模式
- 奇技淫巧之釋出訂閱模式模式
- JavaScript中釋出/訂閱模式的理解JavaScript模式
- 對釋出-訂閱者模式的解析模式
- SpringBoot Redis 釋出訂閱模式 Pub/SubSpring BootRedis模式
- 觀察者模式與釋出訂閱模式區別 - JS模式JS