标签:
一个类只有一个实例,并提供一个全局访问点。
上回说到,屌丝小明同学跟女神完成了第一次的约会。女神很高兴,小明正准备下一次约会的时候。女神另一个追求者小刚也打算约女神出去。
但是女神就一个人,面对两个人的追求,只能是选择一个。另一个人只能说,抱歉了。
我们就以上剧情,使用单例模式,来进行演示。
我们用单例的方法创建女神类,并让他第一次约有空,剩下均没有空。
public class Goddess { private Goddess() { Console.WriteLine("我有空,走吧"); } private static Goddess _Goddess; //创建全局访问点 public static Goddess HelloGoddess() { if (_Goddess == null) { _Goddess = new Goddess(); } else { Console.WriteLine("很抱歉,我没有时间"); } return _Goddess; } }
首先,我们让他的实例变成私有。这样外部就无法调用了。
然后我们创建一个静态的变量,用来返回实例。
最后,我们创建全局访问点。来进行操作。
小明先邀请女神,然后小刚在邀请女神。
static void Main(string[] args) { Console.Write("小明邀请女神:"); Goddess xiaoming = Goddess.HelloGoddess(); Console.Write("小刚邀请女神:"); Goddess xiaogang = Goddess.HelloGoddess(); Console.ReadLine(); }
我们看看,运行结果
小明捷足先登的约到了女神。小刚失利了。
这就是单例模式,如果你打算一直使用单线程并且不异步操作。那么这个完全是可以得。
但如果我们使用异步操作来调用的话,这个就不起作用了。我们下面来修改成异步操作。
女神类不进行修改。我们来修改小明和小刚,进行异步调用操作。
使用await异步请求,进行调用操作。因为我懒得修改女神这个类了,所以我就加了一个等待时间。
public class Suitors { public async void Go() { Task xm = xiaoMing(); Task xg = xiaoGang(); await xm; await xg; } public async Task xiaoMing() { await Task.Delay(1000); Goddess girl = Goddess.HelloGoddess(); } public async Task xiaoGang() { await Task.Delay(1000); Goddess girl = Goddess.HelloGoddess(); } }
当我执行Go这个方法的时候,就会同时进行两个追求者的操作。那么就会产生下面这种情况。
女神来者不拒啊~~~但我们知道,女神只能同意一个人的约会。所以我们再修改一下女神这个类。
public class Goddess { private Goddess() { Console.WriteLine("我有空,走吧"); } private static Goddess _Goddess; private static object obj = new object(); //创建全局访问点 public static Goddess HelloGoddess() { if (_Goddess == null) { lock(obj) { if(_Goddess == null) _Goddess = new Goddess(); else { Console.WriteLine("很抱歉,我没有时间"); } } } else { Console.WriteLine("很抱歉,我没有时间"); } return _Goddess; } }
两个if中间一个lock,双重加锁。lock会锁定线程,一直到执行完毕。相关lock知识可以查看。点我
那么,我们的女神执行结果就变成了。
小明同学,顺利约到女神。并且让情敌小刚碰了一鼻子灰。
主要还是lock锁和全局访问点,这个模式还是好用的。
常用场景:要使用单例模式的对象,必须是全局且唯一。
选择关键点:一个对象如果出现多个实例,会不会引起逻辑上或程序上的错误。
标签:
原文地址:http://www.cnblogs.com/chenxygx/p/4984322.html