TOP

设计模式-单例(一)
2017-10-10 12:35:06 】 浏览:9938
Tags:设计模式 单例

 一、概念

  保证一个类仅有一个实例,并提供一个访问他的全局访问点。

二、模式动机

  对一些全局性资原或者配置进行统一管理,以提供一个唯一的访问点,并减少内存的使用。

 三、模式的结构

   

  单例模式有如下特点:

  1.单例类只能有一个实例

  2.单例类必须自已创建自已的实例

  3.单例类必须提一个访问点,以便向外部提供自已唯一的实例

模式示意代码

  1.懒汉式

 1 public class LazySingleton {
 2     
 3     //定义一个变量用来存储创建好的唯一实例
 4     private static LazySingleton instance = null;
 5 
 6     //私有化构造函数,避免外面用new 直接创建任意多的实例
 7     private LazySingleton() {
 8 
 9     }
10 
11     //定义一个静态方法,提供全局访问点
12     public synchronized static LazySingleton getInstance() {
13         //判断唯一实例是否已创建
14         if (instance == null) {
15             //如果没创建,则创建实例
16             instance = new LazySingleton();
17         }
18         //返回创建好的唯一实例
19         return instance;
20     }
21 }

分析:

  a.private构造子,保证了外部不能用new直接创建该类的实例

  b.getInstance用synchronized,解决了当多线程同步时,同时只能有一个线程进入该方法,从而避免了两个线程同时进入if块内部创建不同的instance实例

  c.由于getInstance是静态方法(属于类的静态方法只能调用属于类的静态成员),所以那个private的instance成员必须是static

  d.由于getInstance进行了synchronized,所以当多线程时会出现性能问题,且获取实例前,每次都要判断实例是否存在。

  2.饿汉式

  

 1 public class EagerSingleton {
 2     
 3     //定义一个变量用来存储创建好的唯一实例 ,类加载时直接创建,且只创建一次
 4     private static EagerSingleton instance = new EagerSingleton();
 5 
 6     //私有化构造函数,避免外面用new 直接创建任意多的实例
 7     private EagerSingleton() {
 8 
 9     }
10 
11     //定义一个静态工厂方法,提供全局访问点
12     public static EagerSingleton getInstance() {
13         //直接返回类加载时已创建好的实例
14         return instance;
15     }
16 
17 }

  分析:

  a.private构造子,保证了外部不能用new直接创建该类的实例

  b.静态成员  instance在类加载时直接实例化,因为虚拟机保证只会装载一次,在装载类的时候是不会发生并发的,所以饿汉式是线程安全的。试想一下,如果饿汉式的instance如果不是static会出现什么情况,会出现死循环。

  c.由于静态成员并非是在使用实例时实例化,而是在类加载时就实例化,所以饿汉式是空间换时间的一种模式。

 

四、模式样例

  系统中属性文件的读取

  

 1 import java.io.File;
 2 import java.io.FileInputStream;
 3 import java.io.IOException;
 4 import java.io.InputStream;
 5 import java.util.Properties;
 6 
 7 public class PropertiesManager {
 8     private static String fileName="D:\\workspace\\exec\\bin\\singleton\\app_base.properties";    
 9     private  Properties props=new Properties();    
10     private static PropertiesManager instance=new PropertiesManager();
11     
12     private  PropertiesManager() {
13         readFile();
14     }
15     
16     private void readFile() {
17          InputStream in=null ;
18          try {
19             in=new FileInputStream(new File(fileName));
20             props.load(in);
21         } catch (IOException e) {
22             e.printStackTrace();
23         }finally{
24             try {
25                 in.close();
26             } catch (IOException e1) {
27                 // TODO Auto-generated catch block
28                 e1.printStackTrace();
29             }
30         }
31     }
32     
33     public static PropertiesManager getInstance() {
34         return instance;
35     }
36     public String  getItem(String key) {
37         return props.getProperty(key);
38     }
39         
40 }

使用方法如:

import singleton.PropertiesManager;

public class TestC {

    public static void main(String[] args) {
        PropertiesManager obj=PropertiesManager.getInstance();
        System.out.println(obj.getItem("name"));
    }
}

 

五、模式的约束

  同一个JVM中会多个类加载器,当两个类加载器同时加载同一个类时,会出现两个实例,这样也意味着单例类也有可能有多个实例,这样就有可能会违背了单例类的初衷,更何况随着系统的变大,还会用到集群,所以单例类现在使用的场景可能越来越少,或者我们使用单例类的目的已发生了变化,常常是为了减少内存的使用而使用单例类。

六、模式的变体与扩展

  多例模式(暂略)

七、与其它模式的关系

  单例类的全局访问点用的就是静态工厂模式模式

八、模式优缺点

  1.懒汉模式:在类加载时并不会创建唯一实例,只有在调用getInstance时才会创建唯一实例,但时在每次获取实例时又会涉及多线程同步的问题,且每次都要判断实例是否已创建,所以懒汉模式是典型的以时间换空间(只有获取实例时才创建对像)。

  2.饿汉模式:在类加载时就实例化,在调用全局方问点时,直接返回已创建好的实例,所以速度要比懒汉模式快一些,是空间换时间的一种模式

  下面的例子弥补了以上两种模式的不足

  样例:

   

public class Singleton {
    private static class SingletonHolder{
        private static Singleton instance=new Singleton();
    }
    p  
		
设计模式-单例(一) https://www.cppentry.com/bencandy.php?fid=97&id=131030

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇设计模式之建造者模式 下一篇UML学习——状态图(四)