点击查看:设计模式系列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; } }