单例设计模式与静态类,静态方法的联系



单例设计模式与静态类,静态方法的联系

最近在一次设计中,遇到单例设计模式与静态方法,何时使用的问题?同事把静态方法的调用换成单例设计模式的方式来搞,问他为什么要这样搞,却答不出原因,所以今天的讨论的主题就是,何时使用单例设计模式,何时使用静态类,何时使用静态方法,静态方法与非静态方法的区别在哪??


一.单例设计模式与静态类的区别与联系?


单例设计模式是面向对象的,即使通过new出来的实例,只不过只需要这一个实例就行了,在程序运行期间不需要创建更多的实例,通常那些没有字段属性的工具类,只是向外提供方法的类,都可用单例设计模式来搞。


而静态类,相当于seal类,是个终类,不能继承,不能用于创建对象,它不是面向对象的。


综上可以总结出一下几点:

1.静态类与单例模式在实现效果是一样的,只是单例模式中的类,更具灵活性,它是面向对象的,可继承自接口,也可被继承,去扩展这个类,类中可有非静态字段,和非静态方法。

2.静态类则更严格,具有一定的局限性,不能被继承,不能扩展,所以它不是面向对象的,并且静态类中的所有字段也必须是静态的,包括静态的属性,静态的方法,都必须是静态的。

3.所以原则是,当一个类中没有属性值,只是用来向外提供一个方法时,通常应使用单例模式,因为单例模式是面向对象的,可继承,可扩展。


二、静态方法常驻内存,非静态方法只有在实例的时候加载内存?


其实这个说法是错误的。

为什么会这样,先从内存分配开始说起:

托管堆的定义:对于32位的应用程序来说,应用程序完成进程初始化后,CLR将在进程的可用地址空间分配一块保留的地址空间,它是进程(每个进程可使用4GB)中可用地址空间上的一块内存区域,但并不对应任何物理内存,这块地址空间即是托管堆。

托管堆有分为多个区域,其中最重要的是垃圾回收堆(GC Heap)和加载堆(Loader Heap),GC Heap用于存储对象实例,受GC管理;Loader Heap又分为High-Frequency Heap、Low-Frequency Heap和Stub Heap,不同的堆上又存储不同的信息。Loader Heap最重要的信息就是元数据相关的信息,也就是Type对象,每个Type在Loader Heap上体现为一个Method Table(方法表),而Method Table中则记录了存储的元数据信息,例如基类型、静态字段、实现的接口、所有的方法等等。Loader Heap不受GC控制,其生命周期为从创建到AppDomain卸载。(摘自《你必须知道的.Net》)

由此我们就明白了,静态方法和非静态方法,在内存里其实都放在Method Table里了,在一个类第一次被加载的时候,它会在Loader Heap里把静态方法,非静态方法都写入Method Table中,而且Loader Heap不受GC控制,所以一旦加载,GC就不会回收,直到AppDomain卸载。




另外,静态方法不需要实例化对象就可调用,非静态方法是通过先实例化一个对象,然后将对象存储在GC Heap上,将methodTable中的非静态方法复制到GC Heap上那个对象当中,所以从效率的角度上来讲,静态方法确实要比非静态方法要快一些。




但不得不说的是,静态与非静态方法的设计使用规则,并不是基于效率层面的考虑。而是基于这个方法是否是与对象无关的,来考虑,通常一些工具类方法就会设计成静态的。


  • 如果某个方法是用频率较高,或者方法本身通用性较强,无需初始化类成员变量,则可以使用静态方法,那样方便,速度也快.

、 为什么使用单例模式而不用静态方法?

 从面相对象的角度讲:

虽然都能实现目的,但是他们一个是基于对象,一个是面向对象的,就像我们不面相对象也能解决问题一样,面相对象的代码提供一个更好的编程思想。

如果一个方法和他所在类的实例对象无关,那么它就应该是静态的,反之他就应该是非静态的。如果我们确实应该使用非静态的方法,但是在创建类时又确实只需要维护一份实例时,就需要用单例模式了。

比如说我们在系统运行时候,就需要加载一些配置和属性,这些配置和属性是一定存在了,又是公共的,同时需要在整个生命周期中都存在,所以只需要一份就行,这个时候如果需要我再需要的时候new一个,再给他分配值,显然是浪费内存并且再赋值没什么意义,所以这个时候我们就需要单例模式或静态方法去维持一份且仅这一份拷贝,但此时这些配置和属性又是通过面向对象的编码方式得到的,我们就应该使用单例模式,或者不是面向对象的,但他本身的属性应该是面对对象的,我们使用静态方法虽然能同样解决问题,但是最好的解决方案也应该是使用单例模式。

从功能上讲:单例模式可以控制单例数量;可以进行有意义的派生;对实例的创建有更自由的控制;








阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页