您的位置:首页 > 其它

设计模式-让我们从从最简单的Singleton开始设计模式

2007-09-17 23:04 337 查看
本人同意他人对我的文章引用,但请在引用时注明出处,谢谢.作者:蒋志强

我第一次接触到设计模式就是从Singleton开始的,在此之前,我根本不知道什么是设计模式。当时带我写程序的老师,把程序框架做完后,把程序给我,给我讲了一下程序的大体结构,然后让我接着写。那个时候,他给我说工程的那个类是个单粒类,当时我一头雾水,但还是点头说晓得了。后来发现这个类的设计非常巧妙,最后发现原来就是使用的Singleton设计模式,之后我对设计模式就迸发了巨大的兴趣。

设计模式(Design Pattern),不是教授如何具体编程,而是从软件的构建的角度来设计软件的结构。设计模式可以是很高层的抽象,也可以相对中层一些。Erich Gamma的那本《设计模式》是一个里程碑式的巨作,奠定了设计模式在软件设计中举足轻重的地位,也规范了以往不同的混乱的设计模式术语。

究竟什么是设计模式?设计模式是无数优秀程序员的经验结晶,是他们在实际构建软件过程中,发现的对于特定问题的优秀解决方案。Erich Gamma的那本《设计模式》的全名为Design Pattern--Elements of Reusable Object-Oriented software,也就是说这本书中讲的是针对面向对象的程序设计中的优秀解决方案。但是设计模式并不仅仅限于面向对象程序语言,面向过程的程序设计当然也有设计模式,只是在当今程序设计领域,面向对象程序设计占据了很大的份额,并非面向过程就没有设计模式。在该书中详细的分析了经典的23种被广泛应用的设计模式,这23种设计模式被广大优秀软件工程师在实践中证明是非常的实用的。当然设计模式远不只限于书中提到的23种,而且设计模式也在不断的发展,不断有优秀的软件工程师在实践中思考出新的优秀的设计模式。当一个经验丰富的程序员在不断的实践编程过程中,自然会思考出解决出某类问题的优秀解决方案。新的设计模式就诞生了。

我们先看看最简单的设计模式--Singleton,它非常有用,但却非常简单。Singleton中文常被称作单粒类,它可以保证那些需要创建对象,但只需要创建一个对象,绝对不允许被创建多个该类的对象的情况。同时,这个对象又要保证可以在任意地方地方被方便的访问。

这样的情况很常见,比如编写一个图像处理软件,该图像处理软件保存为一个工程(或者工作区),该图像软件一次显然是只打开一个工程(工作区)进行处理,在程序的各个逻辑处需要进行处理都需要要求可以方便的访问该工程。如果将工程抽象为一个类,那这个类最好就被设计为Singleton的。

要保证一个类只被用来创建一个对象,我们很自然的想到创建一个static的字段来记录,所创建的对象的个数,如果发现该字段为0,则创建该类的一个对象,如果为1,则不去创建该对象。用C#来描述这样的思想,如下面的代码:


class Singleton




......{


public Singleton() //构造函数




...{


count++;


}


~Singleton()//析构函数




...{


count--;


}


public static int count = 0;//记录创建的对象个数的字段


//其它非静态的成员...


}

OK,这样看上去可以解决问题,但实际上并没有,反而让事情变得更糟糕。因为在创建该类的对象的时候,我们还需要去判断静态变量的值:


Singleton single;//创建Singleton类的引用,这和C++中的指针意思类似,并没有创建实际的对象


if(Singleton.count == 0)


single = new Singleton();



这样做让我们创建对象的时候很麻烦,更讨厌的是,如果发现count字段已经为1的时候,我们该怎么办?!有人会想到也做一个静态字段,像这样:


class Singleton




...{


public Singleton() //构造函数




....{


count++;


instance = this;


}


~Singleton()//析构函数




...{


count--;


}


public static int count = 0;//记录创建的对象个数的字段


public static Singleton instance;


//其它非静态的成员...


}

这样做,就好多了。我们可以保证在发现count字段为1的时候,直接去从instance字段去获取这个唯一的对象,但是还是不是很好。我们使用对象获取对象,而不是使用在全局范围都可以访问的类来获取对象,因为对象在函数周期结束的时候,会被收回(C++)或者可能被CLR或JVM垃圾回收(C#或JAVA),而且我们在创建对象时,还需要使用下面讨厌的代码:


Singleton single;//创建Singleton类的引用,这和C++中的指针意思类似,并没有创建实际的对象


if(Singleton.count == 0)


single = new Singleton();


els


single = Singleton.instance;

现在我们使用Singleton设计模式来做这个类,情况会是怎样呢?其相应的C#代码如下:


public class Singleton




...{


private static Singleton instance;


protected Singleton Instance




...{


get




...{


if(instance == null)


instance = new Singleton;


return instance;


}


}


public Singleton()//构造函数




...{}


}

相应的C++代码:


class Singleton




...{


private: static Singleton* instance;


public: static Singleton* Instance




...{


if(instance == null)


instance = new Singleton;


return instance;


}


}


protected: Singleton()//构造函数




...{}


}

哈哈,现在的感觉怎么样。将C#的类设置为public,或把C++的类的定义文件包含进入工程,则该类可以在程序的任何地方访问,避免了在方法中定义对象导致对象生命周期限制于函数返回前,同时想访问就访问。另外,直接通过C#的public的属性或者通过C++静态的public方法可以任意访问,通过C++函数中的判断语句,或者通过C#属性中的判断语句,判断类是否已经创建对象。同时构造函数被设置为了protected,从而在根本上杜绝了使用类似Singleton single;这样的代码来错误的使用Singleton模式的类。当需要使用该类的对象时,可以很放心的使用下面的代码:

//C#代码
Singleton.Instance.X;//X代表你想使用的字段或者方法
//C++代码
Singleton.Instance().X;//X代表你想使用的字段或者方法

其实在很多其它地方也都可以使用Singleton,又如图像处理软件中常见的工具箱中的各个功能按钮,很好的抽象就是做成Singleton,因为这些类代表一个功能,只需要创建一个对象,而且也需要保证在程序逻辑的其它地方可以方便访问,一般这部分的结构是结合Singleton和State设计模式来构建,甚至是还应该结合Command设计模式才算比较完满。这些都是后话了,我会在后面介绍它们以及综合的使用这些设计模式。

是不是,很爽啊!当然Singleton模式可谓是简单得不能再简单了,但这短短的几句代码凝结的前人的智慧。以后,我们看到的其它设计模式肯定都比Singleton要复杂,设置是几种设计模式综合使用来设计程序。但是Singleton是一个完整的设计模式,我们都已经学会了吧。赶紧在我们当前编写的具体工程中使用吧,具体在工程实践中使用,才算真正的学习了一种设计模式。以后的复杂的设计模式会更加精彩得多,真是令人兴奋。当我们熟练使用这23种设计模式的时候,也就离我们自己改进原有的或设计新的设计模式不远了。

下次内容将更加精彩。

To be continued...
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐