`
huntfor
  • 浏览: 195244 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

设计模式(1)——单例模式

 
阅读更多

先来三个问题:

1.什么是单例模式?

2.为什么要使用单例模式,优点是什么

3.什么情况下适合使用单例模式

 

先来回答第1个问题:

定义 
单例模式是一种最常用且最简单的设计模式之一,其核心是一个单例类。单例,顾名思义,须确保单例类有且只有一个实例,并自行实例化(貌似只能自己实例化,如果可以被实例化,就不再是单例了)并向系统提供该实例。

 由定义可以看到单例模式的特点:

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

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

3.单例类必须给所有其他对象提供该实例

 

 

第2个问题:为什么要使用单例模式,其优点是什么

查了一下stackOverflow上面的一些解答,无外乎几种:

1.

Instance control: Singleton prevents other objects from instantiating their own copies of the Singleton object, ensuring that all objects access the single instance.

可以有效避免其他对象访问单例对象的副本,确保了所有对象都访问这唯一的资源

 

(PS:上面那句略拗口,有人举了一个很有意思的例子,例如,地球只有一个,为了保证你不是活在你自己new出来的地球上,那么只有使用单例模式,这样大家就可以共享同一个地球了。这种单例是自然而然的,比如要访问同一个打印机,写同一个日志文件,访问同一个配置文件等等)

2.
Flexibility: Because the class controls the instantiation process, the class has the flexibility to change the instantiation process.

因为类控制了实例化过程,所以类可以灵活更改实例化过程。(这句话不是特别明白,求解惑,不过解答者后面做了一个解释:you can change your mind and manage any number of instances.我觉得所谓的灵活性只是控制数量的话,简直弱爆了

《java与模式》一书中,作者也对单例作了总结:

1.节约内存,有利于垃圾回收(GC)

2.可以通过线程同步来控制资源的并发访问

3.作为通信媒介使用,可在不建立直接关联条件下,让多个不相关的线程或进程实现通信

 

最后一个问题:

这个问题,噗~大牛们在stackOverFlow上吵得太热闹了,各说纷纭,但是人气最高的是:单例模式纯属扯淡,到现在也没有一个让人信服的理由(╯‵□′)╯︵┻━┻

大家还是看原帖吧,很有意思

http://stackoverflow.com/questions/228164/on-design-patterns-when-to-use-the-singleton

http://misko.hevery.com/2008/08/25/root-cause-of-singletons/

 

好了,虽然第三个问题有点搬石头砸自己脚的,还是硬着头皮往下讲吧

 

常用的单例模式有三种:恶汉模式,懒汉模式,登记模式

还有三种高大上的(今天先入门...):双重校验锁模式、枚举、静态内部类

1.恶汉模式

//恶汉式单例类.在类初始化时,已经自行实例化 
public class Singleton1 {
    //私有的默认构造子
    private Singleton1() {}
    //已经自行实例化 
    private static final Singleton1 single = new Singleton1();
    //静态工厂方法 
    public static Singleton1 getInstance() {
        return single;
    }
}

 2.懒汉模式

//懒汉式单例类.在第一次调用的时候实例化 
public class Singleton2 {
    //私有的默认构造子
    private Singleton2() {}
    //注意,这里没有final    
    private static Singleton2 single=null;
    //静态工厂方法 
    public synchronized  static Singleton2 getInstance() {
         if (single == null) {  
             single = new Singleton2();
         }  
        return single;
    }
}

 3.登记模式

import java.util.HashMap;
import java.util.Map;
//登记式单例类.
//类似Spring里面的方法,将类名注册,下次从里面直接获取。
public class Singleton3 {
    private static Map<String,Singleton3> map = new HashMap<String,Singleton3>();
    static{
        Singleton3 single = new Singleton3();
        map.put(single.getClass().getName(), single);
    }
    //保护的默认构造子
    protected Singleton3(){}
    //静态工厂方法,返还此类惟一的实例
    public static Singleton3 getInstance(String name) {
        if(name == null) {
            name = Singleton3.class.getName();
            System.out.println("name == null"+"--->name="+name);
        }
        if(map.get(name) == null) {
            try {
                map.put(name, (Singleton3) Class.forName(name).newInstance());
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        return map.get(name);
    }
    //一个示意性的商业方法
    public String about() {    
        return "Hello, I am RegSingleton.";    
    }    
    public static void main(String[] args) {
        Singleton3 single3 = Singleton3.getInstance(null);
        System.out.println(single3.about());
    }
}

 这里看到构造函数都被封装成 非public,原因是很容易理解的:为了阻止其他对象创建实例(说好的单例)

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics