关于与单例与采用静态变量引用一个对象的区别
2013-10-21 10:37
337 查看
这里要说明的是,即将讨论的是单例模式获取一个对象与定义一个静态变量而创建一个对象,这两种方式的区别。
看如下代码
有朋友跟我交流,问这两种写法到底有什么区别。看起来实现的效果都一样。这两种方式的区别到底是什么,有时新手面试时可能会被问到,这里做个总结。
要分辨两者之间的区别,要来看看两者的一些基本特点。
单例的特点:
1. 保证某类只存在唯一实例。
2. 该类本身完成自身的初始化。
3. 获取该唯一实例的方式非常明确,可以通过该类本身定义的静态方法getInstance()获取该类的唯一实例引用。
静态变量定义某类的实例引用特点:
1. 该类的实例引用的静态变量可定义在任何文档类当中。
2. 获取该类的实例引用的静态变量,可以通过定义该静态变量的类名通过点语法进行访问该引用。
3. 任何位置可以对该静态变量进行重新赋值。
通过这两者方式的特点,我们可以很明显的看出两者之间的区别。(这一切都是基于某类只需要存在一个实例对象的前提来讨论)
首先静态变量方式不能确保某类的实例的唯一性,这样在项目中,可能因为在某个文档类中对该静态变量进行再次赋值,存不可意料的风险(这种风险可以规避)。同样的,因为静态变量的定义的位置不确定,所以需要协议商定,这些静态变量分类别进行定义在一个固定的位置(比如说某个专门存放静态变量方式的某类的对象的引用的文档类当中)。
而单例模式也就是静态变量方式创建一个类的实例引用所带来的缺陷的改善。首先解决引用的唯一实例可能被重新赋值的问题,单例模式中的getInstance()静态方法实现时,采用懒汉式创建一个对象(当然这只是创建方式的一种),规避了这一风险,无则创建,有则跳过创建。其次,getInstance()静态方法定义在该类的内部,获取该类对象的引用位置非常明确,无需额外的沟通商定,团队成员拿起即用。最后一个区别并不是很明显,声明一个静态变量,实际上,我们会直接对其进行初始化赋值,这样,在内存占用上,所占用的内存为该初始化赋值对象实际的内存。而单例模式可以通过懒汉创建法延迟该内存的占用,要知道,当一个静态变量只进行声明,而不进行初始化时,实际的内存占用只有4个字节(笔者个人推测,这四个字节只是一个指针地址所占用的内存空间)。
看如下代码
//方式一:单例模式 package { public class Singleton { private static var instance:Singleton; public function Singleton(pClass:PClass) { if(pClass == null) throw new Error("单例,禁用构造函数创建对象."); } public static function getInstance():Singleton { if(instance == null) instance = new Singleton(new PClass()); return instance; } /*<------------------------------------------->*/ public var num:int = 0; public function traceNum():void { trace(num); } } } class PClass{} //方式二:定义普通类的静态变量: package { public class Sample { public var num:int = 0; public function Sample() { } public function traceNum():void { trace(num); } } } //然后定义一个该类的静态变量 public static varmeSample:Sample = new Sample();
有朋友跟我交流,问这两种写法到底有什么区别。看起来实现的效果都一样。这两种方式的区别到底是什么,有时新手面试时可能会被问到,这里做个总结。
要分辨两者之间的区别,要来看看两者的一些基本特点。
单例的特点:
1. 保证某类只存在唯一实例。
2. 该类本身完成自身的初始化。
3. 获取该唯一实例的方式非常明确,可以通过该类本身定义的静态方法getInstance()获取该类的唯一实例引用。
静态变量定义某类的实例引用特点:
1. 该类的实例引用的静态变量可定义在任何文档类当中。
2. 获取该类的实例引用的静态变量,可以通过定义该静态变量的类名通过点语法进行访问该引用。
3. 任何位置可以对该静态变量进行重新赋值。
通过这两者方式的特点,我们可以很明显的看出两者之间的区别。(这一切都是基于某类只需要存在一个实例对象的前提来讨论)
首先静态变量方式不能确保某类的实例的唯一性,这样在项目中,可能因为在某个文档类中对该静态变量进行再次赋值,存不可意料的风险(这种风险可以规避)。同样的,因为静态变量的定义的位置不确定,所以需要协议商定,这些静态变量分类别进行定义在一个固定的位置(比如说某个专门存放静态变量方式的某类的对象的引用的文档类当中)。
而单例模式也就是静态变量方式创建一个类的实例引用所带来的缺陷的改善。首先解决引用的唯一实例可能被重新赋值的问题,单例模式中的getInstance()静态方法实现时,采用懒汉式创建一个对象(当然这只是创建方式的一种),规避了这一风险,无则创建,有则跳过创建。其次,getInstance()静态方法定义在该类的内部,获取该类对象的引用位置非常明确,无需额外的沟通商定,团队成员拿起即用。最后一个区别并不是很明显,声明一个静态变量,实际上,我们会直接对其进行初始化赋值,这样,在内存占用上,所占用的内存为该初始化赋值对象实际的内存。而单例模式可以通过懒汉创建法延迟该内存的占用,要知道,当一个静态变量只进行声明,而不进行初始化时,实际的内存占用只有4个字节(笔者个人推测,这四个字节只是一个指针地址所占用的内存空间)。
相关文章推荐
- 关于对象引用的一个例子
- static 静态变量和静态函数的使用探究 类::functionname 与 初始化一个对象的区别
- Java中int和Integer的区别:int 是基本类型,直接存数值 ;integer是对象,用一个引用指向这个对象
- Java 匿名对象和对象就是一个能否不断得到实例化对象内存引用的区别
- 今天碰到的一个问题,关于通过基类对象的引用给子类赋值
- 关于直接打印一个对象的引用
- 关于Fragment.onCreate()中引用Activity.onCreate()创建的对象时的一个异常
- 关于js中一个对象当做参数传递是按值传递还是按引用传递的个人看法
- 关于游戏对象是继承自CCSprite还是引用CCSprite的思考,想来想去,还是面向对象的思想的区别。
- 关于一个实体对象不能由多个 IEntityChangeTracker 实例引用。
- 关于js中一个对象当做参数传递是按值传递还是按引用传递的个人看法
- 关于类的静态变量和非静态变量区别的一个研究例子
- Java中关于静态变量的一个问题
- JavaSE8基础 instanceof 判断引用变量指向的是一个类的具体对象吗
- Java 把对象作为参数传到一个方法里,这个是值传递还是引用传递, 为什么结果这么怪?
- 读书笔记 effective c++ Item 21 当你必须返回一个对象的时候,不要尝试返回引用
- 关于一个类中使用自己(类对象或类指针)
- Java 关于提高效率的小原则---多层对象引用会浪费时间!
- 对象引用与对象的区别
- 关于模板编程的一个例子 来自深度探索c++对象模型