单例模式----SingleTon

1.什么是单例模式??

单例模式是一种比较普遍和简单的模式,在我们的程序中经常会用到。简单的说就是,单例模式就是让一个类永远只对外发布唯一的实例(Instance)。

2.什么情况下使用单例模式??

比如一个连接数据库的系统,使用连接池,那么连接池管理器一定是个单例类。

取系统配置,每次只要读取一次,利用单子模式每次不用实例化对象,直接返回对象引用就可以了。

购物车,一个用户登录时就给其实例化一个购物车,它直到这个用户退出,只能用一 个,这个购物车对象就应采用单子模式设计!

 

3.为什么使用单例模式?

1.   Singleton设计模式保证一个application中就至多只有一个instance,   注意这里界定的是一个application,   而不是一个System.如果不是一个application的话,就不能够保证了。例如:在分布式环境下,虽然单服务器端实现了Singleton,但 是多服务器端(System)就有可能不能保证是Singelton。
      保证application中实现该模式的Singleton   类至多只有一个instance,   可以在一定范围内更好地确定业务逻辑,   尤其是那些保证现实生活中application中只有一个的概念。例如前面说的   数据库连接池就是一个典型;
2.   Singleton设计模式并不能保证节省资源,这是一点需要澄清的。如果要节省资源,大可不必使用Singleton设计模式,Singleton的设计目标并不是为了节省资源,而且为了保证全局性的逻辑统一;
3.   Singleton设计模式与其他设计模式(如   Factory设计模式)的联合使用基本上已经成为了一种“普遍”的技巧,对Singleton的熟悉可以帮助我们在理解他人工作上和相互交流上带来方便。

 

4.单例模式分三种:懒汉式单例、饿汉式单例、登记式单例三种。

一、懒汉式单例
在类被加载的时候,唯一实例已经被创建。这个设计模式在Java中容易实现,在别的语言中难以实现。
public class LazySingleton {
private static LazySingleton m_intance=null; //私有静态对象,加载时候不做初始化
private LazySingleton(){ //私有构造方法,避免外部创建实例
}
synchronized public static LazySingleton getInstance(){ //静态工厂方法,返回此类的唯一实例.
if(m_intance==null){
m_intance=new LazySingleton(); //当发现实例没有初始化的时候,才初始化.
}
return m_intance;
}
}
二、饿汉式单例
在类加载的时候不创建单例实例。只有在第一次请求实例的时候的时候创建,并且只在第一次创建后,以后不再创建该类的实例。
public class EagerSingleton {
private static final EagerSingleton m_instance = new EagerSingleton();//私有的(private)唯一(static final)实例成员,在类加载的时候就创建好了单例对象
private EagerSingleton() {//私有构造方法,避免外部创建实例
}
public static EagerSingleton getInstance() {//静态工厂方法,返回此类的唯一实例.
return m_instance;
}
}
三、登记式单例
这个单例实际上维护的是一组单例类的实例,将这些实例存放在一个Map(登记薄)中,对于已经登记过的实例,则从工厂直接返回,对于没有登记的,则先登记,而后返回。
public class RegSingleton {
private static Map<String, RegSingleton> m_registry = new HashMap();//登记薄,用来存放所有登记的实例
//在类加载的时候添加一个实例到登记薄
static {
RegSingleton x = new RegSingleton();
m_registry.put(x.getClass().getName(), x);
}
protected RegSingleton() {//受保护的默认构造方法
}
public static RegSingleton getInstance(String name) {//静态工厂方法,返回指定登记对象的唯一实例;
if (name == null) {
name = "RegSingleton";
}
if (m_registry.get(name) == null) {//对于已登记的直接取出返回,对于还未登记的,先登记,然后取出返回
try {
m_registry.put(name, (RegSingleton) Class.forName(name).newInstance());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return m_registry.get(name);
}
public String about() {// 一个示意性的商业方法
return "Hello,I am RegSingleton!";
}
}

5.简单且线程安全的两个单例模式

  1. public   class  Singleton2 {    
  2.     private   static   Singleton2 instance =  new  Singleton2();  
  3.     private  Singleton2(){
  4.     }  
  5.     public   static  Singleton2 getInstance(){  
  6.           return  instance;  
  7.     }  
  8.  } 
  9. public   class  Singleton {  // 单例模式创新!google的ioc作者写的。只有在调用的时候才会初始化!而且线程安全
  10.     static   class  SingletonHolder {  
  11.          static  Singleton instance =  new  Singleton();  
  12.     }  
  13.     public   static  Singleton getInstance() {  
  14.          return  SingletonHolder.instance;  
  15.     }  
  16.   } 


PS:1、实例变量应该是静态的私有的。
2、外部调用该实例时,不是通过类的构造方法,而是通过一个getInstance()这样的静态方法来创建该类的唯一实例。
3、默认的构造方法应该是私有的,没有强行规定,但觉得这样子自绝后路的办法未尝不可取 :P
4、单例模式并不是线程安全的,要实现这一点,必须在getTheSpoon()方法前面添加一个同步关键字synchronized。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值