點擊查看:設計模式系列html
咳咳,今天起,我要把對設計模式的理解心得,用全新的案例去分析,分享給你們。但願你們可以喜歡。c#
舉例闡述:遊戲情節,一顆小男孩,丟到衆多鬼子附近,爆炸啦,根據炸彈的威力計算爆炸後鬼子的血量,假定有些鬼子有防具,有些鬼子沒有防具。設計模式
分析:這種狀況,使用觀察者模式是比較理想的,由於觀察者模式的就是是處理對象間一對多的依賴關係的,當一個對象發生變化,其它依賴他的對象都要獲得通知並更新。ide
定義:在觀察者模式中,上述小男孩被稱爲主題,而小鬼子們就被稱爲觀察者。this
下面我用代碼,把舉例給演示出來。spa
定義觀察者模式中的主題。線程
//炸彈 public class bomb { //炸彈名稱 public string Name; //炸彈攻擊距離 public int Length; //炸彈攻擊力 public int ATK; //簡單期間,這裏炸彈我只有一顆啦。 public bomb() { Name = "小男孩"; Length = 100; ATK = 1000; } public DeBeng debeng; //爆炸 public void beng() { if (debeng != null) { debeng(this); } } } //定義委託,爲啦添加爆炸影響的路人 public delegate void DeBeng(bomb bomb);
定義觀察者模式中的觀察者設計
//觀察者,路人 public class roadPeople { //離炸彈距離 public int Length; //路人名稱 public string Name; //血量 public int LifeLength; //盾抵抗力 public int ShieldLth; /// <summary> /// 初始化路人 /// </summary> /// <param name="name">名稱</param> /// <param name="lgth">炸彈距離</param> /// <param name="llth">生命值</param> /// <param name="sth">抵抗能力</param> public roadPeople(string name, int lgth,int llth,int sth) { Length = lgth; Name = name; LifeLength = llth; ShieldLth = sth; } //被炸,這裏的處理方法我寫一致啦,其實能夠是根據不一樣的櫃子有不同的處理方式,這樣就展現啦觀察者模式的強大,我這裏爲啦簡便起見,就沒有定義那麼多類 public void Beated(bomb bom) { //盾削去攻擊 int th=this.ShieldLth-bom.ATK; //被炸後,血量狀況 string info=""; if (th > 0) { //盾牛逼,不掉血 info = "我是:" + this.Name + "。個人盾更牛逼不掉血" ; } else { //掉血 int h=th+this.LifeLength; //判斷死亡 if (h>0) { //未死 info = "我是:" + this.Name + "。掉血:" + (-th)+"點。"; } else { //已死 info = "我是:" + this.Name + "。最後一句話,希望蒼老師隨我而去!"; } } Console.WriteLine("啊,哦,額,噗,我靠,牛逼。"+ info); } }
使用主題與觀察者code
static void Main() { //路人集合 List<roadPeople> list = new List<roadPeople>() { //路人甲,距離炸彈10米,血量100,帶1級盾 new roadPeople("路人甲",40,100,1), //路人乙,距離炸彈20米,血量1000,帶10級盾 new roadPeople("路人乙",40,100,4000), new roadPeople("路人丙",50,2000,50), new roadPeople("路人丁",1000,30,1) }; //實例化炸彈 bomb bom = new bomb(); //添加能炸到的路人 foreach(roadPeople rp in list) { if ((bom.Length - rp.Length) > 0) { bom.debeng += new DeBeng(rp.Beated); } } //炸彈爆炸 bom.beng(); Console.ReadLine(); }
運行結果htm
簡單闡述構建使用觀察者模式過程:主題可變動作爲參數,觀察者擁有本身的屬性與一樣簽名的響應方法,把各個觀察者對象的被炸方法添加到事件中,而後把主題對象做爲參數傳遞給事件中,這樣就能根據觀察者各自的屬性,與計算方法來獲取通知更新。
觀察者模式的效果:觀察者促進啦主體的抽象耦合。主體不知道觀察者的細節,觀察者可根據自身的屬性功能來對主題的通知作變動。然而觀察者也有本身的缺點,就是當主題發生一系列的變化事,觀察者都要作批量的更新,若是這樣的更新成本很高,那麼解決方法就是根據種類需求通知,而不能盲目的通知全部的觀察者。
案例:你只有一個老爸,你媽只有一個老公,然而他是同一我的,晚上大家吃過飯,你就讓你爸給你講你小時候的事,你媽讓你爸講她們談戀愛時候的事,老爸說除啦大家兩個其它人是沒有這待遇的。
分析:這種狀況下,老爸只有一個,不能屢次建立,就很適合使用單例模式。
單例模式:首先要肯定老爸不能被屢次建立,由於老爸只有一個,使咱們的惟一。
單例模式中的單件確保類有且僅有一個
//單例中的Dad有且僅有一個 public class Dad { //老爸 static Dad dad = null; static readonly object padlock = new object(); Dad() { //吃飽,先休息2秒 Thread.Sleep(2000); } ///故事內容 private string content = ""; ///講故事 public void tell() { lock (padlock) { if (Thread.CurrentThread.Name == "mama") { content = "老婆那畫面太美,我不敢想!"; } else if (Thread.CurrentThread.Name == "me") { content = "兒子,你小時候最乖啦,咱們都很愛你。"; } else { content = "除來老婆和孩子,別人休想讓我講故事!"; } } } ///得到故事內容 public string GetCounter() { return content; } //老爸只有一個,不能被屢次建立,叫一下老爸,老爸就會出現 public static Dad sayDad { get { if (dad == null) { lock (padlock) { if (dad == null) { dad = new Dad(); } } } return dad; } } }
使用單件對象
/// <summary> /// 線程工做 /// </summary> public static void DoSomeWork() { ///構造顯示字符串 string results = ""; ///叫一下老爸,惟一的老爸閃亮登場 Dad dad = Dad.sayDad; ///開始講故事 dad.tell(); results += "講給"; results += Thread.CurrentThread.Name.ToString() + "——〉"; results += "我想對你說:"; results += dad.GetCounter().ToString(); results += "\n"; Console.WriteLine(results); ///清空顯示字符串 results = ""; } //爸爸的世界裏,永遠有媽媽跟我2個線程 public void StartMain() { Thread thread0 = Thread.CurrentThread; thread0.Name = "me"; Thread thread1 = new Thread(new ThreadStart(DoSomeWork)); thread1.Name = "mama"; Thread thread2 = new Thread(new ThreadStart(DoSomeWork)); thread2.Name = "badegg"; Thread.Sleep(1000); thread1.Start(); Thread.Sleep(1000); thread2.Start(); Thread.Sleep(1000); ///線程0也只執行和其餘線程相同的工做 DoSomeWork(); }
運行
public static void Main(string[] args) { CountMutilThread cmt = new CountMutilThread(); cmt.StartMain(); Console.ReadLine(); }
結果:
單例模式:確保單件有且僅有一個實例(不讓繼承,不讓構造等手段),而且提供一個對實例的訪問點。
單例的另外好辦法
public class Dad { ///存儲惟一的實例 static Dad dad = new Dad(); //爲啦不讓實例化 private Dad() { } //老爸只有一個,不能被屢次建立,叫一下老爸,老爸就會出現 public static Dad sayDad() { return dad; } object ss = new object(); ///故事內容 private string content = ""; ///講故事 public void tell() { lock (ss) { if (Thread.CurrentThread.Name == "mama") { content = "老婆那畫面太美,我不敢想!"; } else if (Thread.CurrentThread.Name == "me") { content = "兒子,你小時候最乖啦,咱們都很愛你。"; } else { content = "除來老婆和孩子,別人休想讓我講故事!"; } } } ///得到故事內容 public string GetCounter() { return content; } }