小胖这几天由于把时间花在了公司的任务上,所以就没有写关于设计模式的文章,现在系统的流程熟悉了很多,不需要把大部分的时间花在任务上,也有一些时间来学习设计模式了,今天把之前学习的单例模式补上!
他学习新的内容喜欢使用百度百科将名词的意思看一遍,如果看的不明白再找其他大牛的博客看,这次也不例外,打开百度百科敲上单例模式,搜索!页面立刻弹了出来!
定义:
这一模式的目的是使得类的一个对象成为系统中的唯一实例。要实现这一点,可以从客户端对其进行实例化开始。因此需要用一种只允许生成对象类的唯一实例的机制,“阻止”所有想要生成对象的访问。使用工厂方法来限制实例化过程。这个方法应该是静态方法(类方法),因为让类的实例去生成另一个唯一实例毫无意义。关键词---“唯一”、“静态”、“工厂”
“看来每个设计模式之间有那么一丝关系啊!”,小胖自言自语道,边看边唱到“你和他还在藕断丝连。。。”,对于系统中的某些类来说,只有一个实例很重要,例如,一个系统中可以存在多个打印任务,但是只能有一个正在工作的任务;一个系统只能有一个窗口管理器或文件系统;一个系统只能有一个计时工具或ID(序号)生成器。如在Windows中就只能打开一个任务管理器。如果不使用机制对窗口对象进行唯一化,将弹出多个窗口,如果这些窗口显示的内容完全一致,则是重复对象,浪费内存资源;如果这些窗口显示的内容不一致,则意味着在某一瞬间系统有多个状态,与实际不符,也会给用户带来误解,不知道哪一个才是真实的状态。因此有时确保系统中某个对象的唯一性即一个类只能有一个实例非常重要。
看到这小胖不服了,因为他想起大一和室友玩CF的时候,有时候切出游戏,就按“ctrl+alt+delete”然后“召唤出”任务管理器,当时可是出了不止一个窗口啊,出了十几个呢!他赶紧的在自己新的笔记本上测试了一下,嘿,这次只能弹出一个窗口,真是奇怪了,他就这个问题百度了一番,大概知道了原因,因为大一用的电脑有点旧,运行稍大的游戏就有点吃力,然后你又要召唤出任务管理器,电脑一时吃不消,于是你按了几下,就弹出了多少个窗口!说白了就是因为电脑频临死机的边缘,就会出现一些不正常的现象!
”原来是这样“,小胖继续看下去
单例模式要点有三个:
- 某个类只能有一个实例
- 它必须自行创建这个实例
- 它必须自行的向整个系统提供这个实例
从具体实现的角度来看:
- 只提供私有的构造函数
- 类定义中含有一个该类的静态私有对象
- 该类提供一个静态的共有函数用于创建或获取它本身的静态私有对象
小胖看了看一些博主写的单例模式见解,总结出了一些
单例模式分为最常见的三种:饿汉模式、懒汉模式、双重锁模式,小胖对饿汉与懒汉比较感兴趣,急忙的将这两个代码实现出来,代码如下:
饿汉模式
/**
* 饿汉
* @author Administrator
*
*/
public class Singleton {
String str=null;
private static Singleton instance = new Singleton();
private Singleton(){
}
public static Singleton getInstance(){
return instance;
}
public void print(){
System.out.println(str);
}
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
}
懒汉模式:
/**
* 懒汉模式
* @author Administrator
*/
public class LazySingleton {
String str = null;
private static LazySingleton instance=null ;
public static LazySingleton getInstnce(){
if(instance==null){
instance = new LazySingleton();
}
return instance;
}
public void print(){
System.out.println(str);
}
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
private LazySingleton(){
}
}
小胖仔细的分析了这两段代码,饿汉模式在测试代码还没有调用该类的时候,已经new出实例了,”真是饥饿难耐啊!“
懒汉模式没有new实例,只是当测试代码在调用该类的时候,首先对instance进行了一个判断,如果存在直接返回,如果不存在,此时,才new一个实例返回,”呵呵,也够懒的,但是比饿汉好一点“
饿汉和懒汉搞懂了,这个双重锁是怎么回事呢?
这里引入了线程的问题,以上对单线程是没有错的,假如是多个线程同时使用懒汉模式下的单例呢?现有A,B两个线程,同时去调用这个单例类,同时判断instance,当然为空了,于是A和B就同时得到了实例,针对这个问题,双重锁就出现了,也就是对instance进行两次判断,代码如下:
/**
* 双重锁模式
* @author Administrator
*
*/
public class SingletonObject {
private static SingletonObject obj;
private static Object lock = new Object();
private SingletonObject(){}
public static SingletonObject getInstance(){
if(obj == null){
synchronized (lock) {
if(obj ==null){
obj = new SingletonObject();
}
}
}
return obj;
}
这次对instance进行了两次判断,再多的进程也不怕了!
单例模式的类图如下: