设计模式-单例模式

常用的单例模式有:懒汉式和饿汉式

单例模式的特点:

1. 单例类只有一个实例

2. 单例类必须自己创建自己的唯一实例

3. 单例类必须给其他多有对象提供这一实例

一、懒汉式

[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. //懒汉式单例类.在第一次调用的时候实例化自己   
  2. public class Singleton {  
  3.     //私有的默认构造方法  
  4.     private Singleton() {}  
  5.     private static Singleton single=null;  
  6.     //静态工厂方法   
  7.     public static Singleton getInstance() {  
  8.          if (single == null) {    
  9.              single = new Singleton();  
  10.          }    
  11.         return single;  
  12.     }  
  13. }  
懒汉式单例的实现没有考虑线程安全问题,它是线程不安全的,并发环境下很可能出现多个Singleton实例,下面介绍的饿汉式单例是线程安全的。

二、饿汉式单例模式

[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. //饿汉式单例类.在类初始化时,已经自行实例化   
  2. public class Singleton1 {  
  3.     //私有的默认构造方法 
  4.     private Singleton1() {}  
  5.     //自行实例化   
  6.     private static final Singleton1 single = new Singleton1();  
  7.     //静态工厂方法   
  8.     public static Singleton1 getInstance() {  
  9.         return single;  
  10.     }  
  11. }  
饿汉式在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以是线程安全的。

饿汉式和懒汉式区别

这两种设计模式乍看上去非常相似,其实是有区别的,主要有两点

1、线程安全:

饿汉式是线程安全的,可以直接用于多线程而不会出现问题,懒汉式就不行,它是线程不安全的,如果用于多线程可能会被实例化多次,失去单例的作用。

如果要把懒汉式用于多线程,有两种方式保证安全性,一种是在getInstance方法上加同步,另一种是在使用该单例方法前后加双锁。

2、资源加载:

饿汉式在类创建的同时就实例化一个静态对象出来,不管之后会不会使用这个单例,会占据一定的内存,相应的在调用时速度也会更快,

而懒汉式顾名思义,会延迟加载,在第一次使用该单例的时候才会实例化对象出来,第一次调用时要初始化,如果要做的工作比较多,性能上会有些延迟,之后就和饿汉式一样了。


什么是线程安全?

如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。

或者说:一个类或者程序所提供的接口对于线程来说是原子操作,或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题,那就是线程安全的。

应用

以下是一个单例类使用的例子,以懒汉式为例:

[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. public class TestSingleton {  
  2.     String name = null;  
  3.   
  4.         private TestSingleton() {  
  5.     }  
  6.   
  7.     private static TestSingleton ts = null;  
  8.   
  9.     public static TestSingleton getInstance() {  
  10.         if (ts == null) {  
  11.             ts = new TestSingleton();  
  12.         }  
  13.         return ts;  
  14.     }  
  15.   
  16.     public String getName() {  
  17.         return name;  
  18.     }  
  19.   
  20.     public void setName(String name) {  
  21.         this.name = name;  
  22.     }  
  23.   
  24.     public void printInfo() {  
  25.         System.out.println("the name is " + name);  
  26.     }  
  27.   
  28. }  
[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. public class TMain {  
  2.     public static void main(String[] args){  
  3.         TestStream ts1 = TestSingleton.getInstance();  
  4.         ts1.setName("jason");  
  5.         TestStream ts2 = TestSingleton.getInstance();  
  6.         ts2.setName("0539");  
  7.           
  8.         ts1.printInfo();  
  9.         ts2.printInfo();  
  10.           
  11.         if(ts1 == ts2){  
  12.             System.out.println("创建的是同一个实例");  
  13.         }else{  
  14.             System.out.println("创建的不是同一个实例");  
  15.         }  
  16.     }  
  17. }  

 运行结果:

the name is 0539

the name is 0539

创建的是同一个实例


结论:由结果可以得知单例模式为一个面向对象的应用程序提供了对象惟一的访问点,不管它实现何种功能,整个应用程序都会同享一个实例对象。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值