Java设计模式 - 单例模式

单例模式是一种创建模式。
顾名思义就是任何何时都只能有一个实例。且该类需自行创建这个实例,并对其他的类提供调用这一实例的方法。是java中常用的设计模式。
这种模式只涉及一个单独的类,它负责创建自己的对象。
该类确保只创建单个对象。
这个类提供了一种访问其唯一对象的方法。
而且单例模式有多种实现方式,接来我们一一来实现

实例

1. 饿汉模式

public class MainWindow {

    private static MainWindow instance = new MainWindow();

    public MainWindow() {
    }

    public static MainWindow getInstance() {
        return instance;
    }

    public void showMessage(){
        System.out.println("Hello World!");
    }
}

饿汉式,就是“比较饿”,实例在初始化的时候就要创建好,不管你有没有用到。
从代码中我们就可以看得出来,当调用getInstance这个方法的时候,返回了instance,而instance在声明时就已经创建好了。

优点:线程安全;在类加载(ClassLoader)的同时已经创建好一个静态对象,调用时反应速度快。
缺点:对象提前创建,所以会占据一定的内存,内存占用大 以空间换时间。

懒汉模式(线程不安全)

public class MainWindow {

    private static MainWindow instance;

    public MainWindow() {
    }

    public static MainWindow getInstance() {
        if (instance == null) {
            instance = new MainWindow();
        }
        return instance;
    }

    public void showMessage(){
        System.out.println("Hello World!");
    }
}

懒汉式就是“比较懒”,从上面代码我们可以看出,就是在用到的时候才去检查有没有实例,就是在调用getInstance方法的时候才会判断是否已经创建对象,如果有则直接返回,没有则新建。
优点:起到了Lazy Loading的效果,但是只能在单线程下使用。
缺点:如果在多线程下,两个线程同时进入了if (singleton == null)判断语句块,这时便会产生多个实例。所以
在多线程环境下不可使用这种方式。

3.懒汉模式(线程安全)

那么懒汉模式线程不安全,怎样才能让它线程安全呢?
对getInstance()方法添加synchronized关键字
优点:解决了线程不安全问题
缺点:每次调用都加锁同步执行,对象返回效率低,不推荐使用。

public class MainWindow {

    private static MainWindow instance;

    public MainWindow() {
    }

    public synchronized static MainWindow getInstance() {
        if (instance == null) {
            instance = new MainWindow();
        }
        return instance;
    }

    public void showMessage(){
        System.out.println("Hello World!");
    }
}

4.双重检索模式

public class MainWindow {

    private static MainWindow instance;

    public MainWindow() {
    }

    public synchronized static MainWindow getInstance() {
    //第一个 if 语句用来避免 uniqueInstance 已经被实例化之后的加锁操作
        if (instance == null) {
        // 加锁
            synchronized (MainWindow.class) {
            //第二个 if 语句进行了加锁,所以只能有一个线程进入,就不会出现 instance == null 时两个线程同时进行实例化操作。
                if (instance == null) {
                    instance = new MainWindow();
                }
            }
        }
        return instance;
    }

    public void showMessage(){
        System.out.println("Hello World!");
    }
}

这就是单例模式的几种实现方法,当然还有其他的,这里就不一一举例。