“小李啊,你在天文史上有的新的突破啊!”BOSS的腔调不像是在夸我。

“啊?”我满脸糊涂。

“你看,我在这天上发现了两个月亮啊!这不是新突破是什么?”BOSS转过它的液晶屏,指着屏幕说道。

“啊!该死!”我暗骂道。。。原来是前几天做了一个游戏项目中,游戏背景的天空中要根据游戏里的时间的不同出现一个与时间相符(形状,大小,位置等)的月亮的情景。当时是我写的月亮这一个类,我当时也没多想,就直接写成了(代码省略了具体实现):

 

        public class Moon
        {
            
public Moon()
            { }

            
public void DisplayMoon(Time time)
            {
                
//根据时间的不同显示不同形状位置的月亮
            }
            
//其它方法
        }

 

 没想到粗心的同事小张在调用我的类时竟在天上new出了两个月亮,最要重的是由于游戏里的时间是一致的,所以这两个月亮不管是形状,大小,位置在同一视有上都重叠了,一般人还真看不出这是两个月亮。可精明的BOSS切换一下视角。。。一下子原形毕露,天空上果然挂着两个月亮!

“这。。。调用时注意点应该没问题吧。。。”这是小张粗心,怎么怪到我头上啦。。我心想。

“类是你写的,你不觉得你应该在技术层上有所防范吗?天上有两个月亮这不应该啊!你这样让客户很担心啊!”BOSS有点语重心长。我知道BOSS这里的客户指的是调用这个类的客户代码。

“这。。。啊。。对了,有个模式可以防范多实例的产生。。。单例模式!”我记得以前看过些设计模式,当时也没留下啥印象,真是灵光一闪啊!

“知道还不快去改善!”BOSS的脸色终于有所缓和。

我连忙回到办公室,把单例模式(Singleton Pattern)重温了一遍,并深入地研究一番。

   单例模式(Singleton):保证一个类仅有一个实例并提供一个访问它的全局访问点。 

 

 

实现方法一:  

   class Singleton
    
{
        
//多线程singleton代码
        private static volatile Singleton instance;  
       
//volatile关键字可防止编译器对所申请的字段优化,以保持字段的最新状态
        private  static readonly object obj = new object();

        
private Singleton()  //private 禁止外部构造
        { }

        
public static Singleton Intance
        
{
            
get
            
{
                
if (instance == null)  //如果没有实例化则实例化
                {
                    
lock (obj)  //锁定obj对象防止多线程访问
                    {
                        
if (instance == null)  //双检测
                        {
                            instance 
= new Singleton();
                        }

                    }

                }

                
return instance;
            }

        }
        
    }

 

实现方法二: 

 1 //通过静态实例实现,非惰性加载
 2 public sealed class Singleton 
 3 
 4    //静态初始化在自己被加载时将自己实例例化,也称饿汉式单例类
 5    private static readonly Singleton instance = new Singleton();
 6    private Singleton(){} 
 7    public static Singleton Instance 
 8    { 
 9       get 
10       { 
11          return instance; 
12       } 
13    } 
14 

这种实现简单,线程安全,缺陷主要是instance不是惰性加载的。准确的说是不一定是惰性加载的,因为我们无法得知instance

会在什么时候被初始化。
 
通过上面的温习,我重写了我那可怜的Moon类:
 
 1        public sealed class Moon  //sealed防止被继承子类实例化
 2        {
 3            private static volatile Moon moon;
 4            private static readonly object obj = new object();
 5
 6            private Moon()  //私有防止外部调用
 7            { }
 8
 9            public static Moon GetMoon
10            {
11                get
12                {
13                    if (moon == null)
14                    {
15                        lock (obj)
16                        {
17                            if (moon == null)
18                            {
19                                moon = new Moon();
20                            }

21                        }

22                    }

23                    return moon;
24                }

25            }

26
27            public void DisplayMoon(Time time)
28            {
29                //根据时间的不同显示不同形状位置的月亮
30            }

31            //其它方法
32        }
 
至此,那该死的小张想NEW两个月亮在天上也不可能啦!对了,过两天还有个太阳类,正好依瓢画葫芦:)
 
单例模式应用场地举例:
1,在中国,一个男人也允许娶一个老婆,哪天哪位当程序员的朋友想实现Wife类时可要小心了,最好用上单例模式,免得在公司被老板骂,回家还让老婆质问:)
2,我们在窗体应用程序中经常做一个MDI例子,如想在窗体中实现一个快捷工具箱一样的子窗体时,要防止生成多个快捷工具箱,正好也用上Singleton.
3, 在数据库接池方面可应用单例模式,确保连接的正确性并可提高效率。
 
题外话一:  
    学习设计模式,相信很多朋友都会有这种感觉:让人迷惑的不是模式的结构或实现方法,而是很难把握在什么情况下使用哪种合适的模式,为什么要用模式等一些问题。
    以我的经验来看,要学好设计模式,最重要的是理解!对OOP有深刻的理解,对一些基本原则有良好的把握,是提高程序设计水平的基础,才可能更好的把握设计模式的精髓所在。我们常说学东西要知其然,更要知其所以然,所以,本系列会以演化的眼光,希望能给读者起到引路的作用。
    情景故事纯属构,如有雷同不管我的事:)
 
题外话二:打个小广告,C#中国论坛http://www.c-sharp.cn/近日开通了,希望愿在相关方面深入学习的朋友前去交流学习。。。我们会有专门的团队为您解决力所能及的一些问题。
posted on 2008-09-25 05:19  浪尘  阅读(2528)  评论(10编辑  收藏  举报