设计模式之01单例模式(笔记)
来源:互联网 发布:帝国cms定时审核 编辑:程序博客网 时间:2024/06/08 09:28
1 定义:
1.1文字定义:Ensure a classhas only one instance, and provide a global point of access to it.(确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。)
1.2通用类图:
图1 单例模式通用类图
1.3通用代码:
public class Singleton { privatestatic final Singleton singleton = new Singleton(); //限制产生多个对象 privateSingleton(){ } //通过该方法获得实例对象 publicstatic Singleton getSingleton(){ returnsingleton; } //类中其他方法,尽量是static publicstatic void doSomething(){ }}
2优点:
- 内存仅有一个实例,减少内存开支;特别是一个对象需要频繁地创建、销毁时,而且创建或销毁时性能又无法优化,单例模式的优势就非常明显。
- 当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后用永驻留内存的方式来解决(在Java EE中注意JVM垃圾回收机制)。
- 单例模式可以在系统设置全局的访问点,优化和共享资源访问,例如可以设计一个单例类,负责所有数据表的映射处理。
3缺点:
3.1 单例模式一般没有接口,扩展很困难,若要扩展,除了修改代码基本上没有别的途径。单例模式为什么不能增加接口呢?因为接口对单例模式是没有任何意义的,它要求“自行实例化”,并且提供单一实例。接口、抽象类是不可能被实例化的。当然特殊情况下,单例模式可以实现接口、被继承等,需要在系统开中根据环境判断。
3.2 单例模式对测试不利。在并行开发环境中,如果单例没有完成,是不能进行测试的。
3.3 单例模式与单一职责原则有冲突。一个类应该只实现一个逻辑,而不关心它是否是单例的,是不是要取决于环境,单例模式把“要单例”和业务逻辑融合在一个类中。
4使用场景:
在一个系统中,要求一个类有且仅有一个对象,如果出现多个对象就会出现“不良反应”,可以采用单例模式,具体场景如下:
- 要求生成唯一序列号的环境;
- 在整个项目中需要一个共享访问点或共享数据,如计数器;
- 创建一个对象需要消耗资源过多,如要访问IO和数据库等资源;
- 需要定义大量的静态常量和静态方法(如工具类)的环境,可以采用单例模式。
5注意事项:
5.1 高并发时注意单例模式的线程同步问题。
在单例的实例化时,有“饿汉式”如1.3中实例化方法;也有使用同步方法,仅在需要时创建的方式,这种方式称为“懒汉式”单例;后者不是优秀的方式,前者为推荐方式。
若后者未添加同步关键字,则可能导致“创建 赋值”过程中,被另一调用再次创建。
5.2 考虑对象复制情况。
在Java中,对象默认是不可以被复制的,若实现了Cloneable接口,并实现了clone方法,则可以直接通过对象复制方式创建一个新对象,对象复制不调用类的构造函数,因此即使是私有的构造函数,对象仍然可以被复制。即,单例类不要实现Cloneable接口。
6扩展:
如果一个类只要一个对象,使用单例模式即可;如果一个类可以只要两个、三个对象呢?亦可参照单例模式,静态初始若干实例,然后使用时或随机或按某种规则取出即可。
7范例:
单例用法(计数器类,部分工具类)
package _01_Singleton;public class Counter {private static final Counter counter = new Counter();//创建实例 private static int total = 0;private Counter(){}public static Counter getInstance(){//获取实例return counter;}//做点事。public synchronized void Increase(){total++;}//做点事。public synchronized int getTotal(){return total;}//工具类可参考public static void whatAmI(){System.out.println("我是计数器工具方法");}}测试:
package _01_Singleton;public class TestCounter {public static void main(String[] args) {Counter.whatAmI();Counter c = Counter.getInstance();for(int i=0; i<10; i++){c.Increase();System.out.println("The current total is : " + c.getTotal());}}}结果:
我是计数器工具方法
The current total is : 1
The current total is : 2
The current total is : 3
The current total is : 4
The current total is : 5
The current total is : 6
The current total is : 7
The current total is : 8
The current total is : 9
The current total is : 10
注意:
使用单例模式需要注意的一点就是JVM的垃圾回收机制,如果我们的一个单例对象在内存中长久不使用,JVM就认为这个对象是一个垃圾,在CPU资源空闲的情况下,该对象会被清理掉,下次再调用时就需要重新产生一个对象。如果我们在应用中使用单例类作为有状态值(如计数器)的管理,则会出现恢复原状的情况,应用就会出现故障。如果确实需要采用单例模式来记录有状态的值,有两种方法可以解决该问题:(下述为转述,未尝试)
由容器管理单例的生命周期
JavaEE容器或者框架级容器(如Spring)可以让对象长久驻留内存。当然,自行通过管理对象的生命期也是一个可行的办法,既然有那么多的工具提供我们,为什么不用呢?
状态随时记录
可以使用异步记录的方式,或者使用观察者模式,记录状态的变化,写入文件或写入数据库中,确保即使单例对象重新初始化也可以从资源环境获得销毁前的数据,避免应用数据丢失。
- 设计模式之01单例模式(笔记)
- 设计模式笔记之---单例模式
- 设计模式笔记之单例模式
- 设计模式笔记之----单例模式
- 设计模式笔记之单例模式
- 01 设计模式之单例模式
- 设计模式01之单例模式
- 学习笔记07-设计模式之单例设计模式
- 设计模式笔记之——单例设计模式
- 设计模式之(单例模式)
- 设计模式之(单例模式)
- 设计模式之单例学习笔记
- 菜鸟学设计模式系列笔记之单例设计模式(Singleton模式)
- 黑马程序员-Java学习笔记之设计模式(单例设计模式,装饰设计模式,模板设计模式)
- 设计模式之单例设计模式(饿汉单例设计模式&懒汉单例设计模式)
- 设计模式笔记之单例模式(Singleton Pattern)
- 设计模式学习笔记(一)之单例模式(Singleton)
- 深入浅出设计模式笔记之二:单例模式
- [转MSDN]虚拟列表(MFC)
- 【java】java二进制,字节数组,字符,十六进制,BCD编码转换收藏
- linphone源码分析----初始化部分
- 在VC++6.0下构建可直接编辑的列表控件类
- C语言系统资源控制(getrlimit && setrlimit)
- 设计模式之01单例模式(笔记)
- CTreeView说明
- Sphere/sector 深度剖析之一
- 使用java vuser来实现mysql的执行过程
- 孵化器给创业者的5个忠告:怎样融资并开始上路
- CTreeView 类的使用
- js实现父页面接收子页面传的值
- 查看长时间运行的session
- jsp学习1-----乱码