咱們必須保持類型設計知足「高內聚,低耦合」,如此才能作到更好的代碼重用。將應用拆解成組件類型能夠實現高可維護性,並利於編碼調試。ide
按鈕點擊、鼠標移動、鍵盤按鍵一般都是觀察者模式的典型應用。封閉的類型對外發布事件,外部用用訂閱類型的事件並編碼實如今事件觸發通知到系統後的操做,想一想按鈕Button類型來源於Windows.Forms名稱空間,經過Dll提供,你沒有Button類型的源代碼不是同樣註冊Button的Click事件,從而讓Button喚起你的Method,這個Dll就是一個有效封裝。函數
委託必須實例化,或者指向一個實例化的方法才能被調用,咱們沒法直接用委託的名字加委託的參數定義一次函數Invoke,而事件充當此角色。事件的做用就是像委託的「樣式」那樣Invoke知足「樣式」的方法,將任意多個知足「樣式」的方法註冊到事件上。「樣式」本質是類型約束,因此委託就是C++的指針,但比C++多了類型檢查,因此能夠人爲是強類型的指針,是在C++指針基礎上的擴展類!this
熱水器帶加熱組件用於加熱Heat(),熱水器含有溫度報警器設置預加熱溫度和報警溫度,好的溫度傳感器甚至可以輸出控制熱水器的加熱組件從而保持恆溫。以熱水器WaterHeater和溫度傳感報警器TemperatureAlarmer爲例,下面展現其應用。能夠直接拷貝代碼到Vistual Studio,逐行調試並觀察「即時窗口」的變量的變化狀況,以深刻理解。編碼
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Demo { /// <summary> /// 報警處理器:用於熱水器及其關聯的報警器 /// </summary> /// <param name="heater">熱水器</param> /// <param name="alarmer">報警器</param> public delegate void AlarmHandler(WaterHeater heater, TemperatureAlarmer alarmer); /// <summary> /// 溫度報警器:設定當前溫度和報警溫度; /// 在超過報警溫度後會觸發事件 TemperatureOverflow,交給掛接報警器的設備處理 /// </summary> public class TemperatureAlarmer { private float temperature_current, temperature_alarm; /// <summary> /// 在超過報警溫度後會觸發事件 TemperatureOverflow,交給掛接報警器的設備處理,如熱水器 /// </summary> public event Action TemperatureOverflow; //溫度檢查:超過報警溫度後啓動報警引擎 private void TemperatureCheck() { if (temperature_current > temperature_alarm) TemperatureOverflow(); } public TemperatureAlarmer() { temperature_current = 0f; temperature_alarm = 95f; } /// <summary> /// 屬性:加熱溫度,範圍35~100 /// </summary> public float TemperaturCurrent { get { return temperature_current; } set { temperature_current = value > 100 ? 100 : value; temperature_current = value < 35 ? 35 : value; TemperatureCheck(); } } /// <summary> /// 屬性:報警溫度,範圍35~100 /// </summary> public float TemperaturAlarm { get { return temperature_alarm; } set { temperature_alarm = value > 100 ? 100 : value; temperature_alarm = value < 35 ? 35 : value; TemperatureCheck(); } } } /// <summary> /// 熱水器,屬於加熱器,須要溫度報警器 /// </summary> public class WaterHeater { public string TradeMark { get; set; } public string Company { get; set; } public TemperatureAlarmer heaterAlarmer; /// 熱水器報警事件,將處理權交給用戶處理 public event AlarmHandler TemperatureOverflow; /// 能夠綁定更換掉默認的溫度報警器 public void BindAlarmer(TemperatureAlarmer alarmer) { this.heaterAlarmer = alarmer; } public WaterHeater() { heaterAlarmer = new TemperatureAlarmer(); heaterAlarmer.TemperatureOverflow += () => { TemperatureOverflow(this, heaterAlarmer); }; } /// 對加熱器進行加熱,最高到100度,將溫度增長到指定值 public void Heat(float temperature) { heaterAlarmer.TemperaturCurrent = temperature; } public override string ToString() { return $"{this.Company},{this.TradeMark},{heaterAlarmer.TemperaturCurrent}/{heaterAlarmer.TemperaturAlarm}"; } } /* 海信,?新婚之夜,0/95 Overflow:海信,?新婚之夜,88/80 海信,?新婚之夜,88/80 海信,?新婚之夜,95/95 海信,?新婚之夜,95/95 海信,?新婚之夜,90/95 */ public class RunMyApp { static void Main(string[] args) { WaterHeater HisenseWarmer = new WaterHeater(); HisenseWarmer.Company = "海信"; HisenseWarmer.TradeMark = "©新婚之夜"; HisenseWarmer.TemperatureOverflow += (heater, e) => Console.WriteLine("Overflow:" + HisenseWarmer); Console.WriteLine(HisenseWarmer);// HisenseWarmer.Heat(88);// HisenseWarmer.heaterAlarmer.TemperaturAlarm = 80;// Console.WriteLine(HisenseWarmer); //更換第三方溫度報警器,具備更高級的自我調節溫度功能,也就是保證不超過報警溫度 TemperatureAlarmer OmronAlarmer = new TemperatureAlarmer(); OmronAlarmer.TemperatureOverflow += () => { OmronAlarmer.TemperaturCurrent = OmronAlarmer.TemperaturAlarm; }; HisenseWarmer.BindAlarmer(OmronAlarmer); HisenseWarmer.Heat(96); Console.WriteLine(HisenseWarmer); OmronAlarmer.TemperaturCurrent = 100; Console.WriteLine(HisenseWarmer); HisenseWarmer.Heat(90); Console.WriteLine(HisenseWarmer); Console.ReadKey(); } } }