确保类只有一个唯一对象,单件模式

为什么需要单件模式

我们为什么要用到单件模式,当我们用到这些对象如:线程池,缓存,注册表和日志对象等,事实上,这些对象我们只能有一个实例,不然会导致很多问题出现,所以我们要将它弄成单件的。

分析常用单件模式

类图很简单
这里写图片描述

package headfirst.hd.singleton;

public class Singleton {

    static Singleton uniqueInstance;

    private Singleton() {}  //不允许通过new方式得到实例化对象

    //获取对象唯一方式
    static Singleton getInstance() {
        if (uniqueInstance == null) {
            uniqueInstance = new Singleton();
        }

        return uniqueInstance;
    }

}

测试类TestSingleton

package headfirst.hd.singleton;

public class TestSingleton {

    public static void main(String[] args) {
        Singleton singleton = Singleton.getInstance();
        Singleton singleton2 = Singleton.getInstance();

        System.out.println(singleton == singleton2);
        System.out.println(singleton.equals(singleton2));
    }

}

在一个单线程中运行,这样已经完美了,但如果有很多个线程并发的情况下,那单件可能就不是单件了。

具体分析如下图
这里写图片描述

多线程下几种单件模式

将方法同步,加入synchronized

将getInstance方法封装成原子性操作

package headfirst.hd.singleton;

public class SingletonSyn {

    static SingletonSyn uniqueInstance;

    private SingletonSyn() {}  

    //将getInstance方法封装成原子性操作
    static synchronized SingletonSyn getInstance() {
        if (uniqueInstance == null) {
            uniqueInstance = new SingletonSyn();
        }

        return uniqueInstance;
    }

}

虽然功能上解决了以上问题,但是每次获取单件时,都会加锁,使得其成为累赘,由于上图我们分析得知,只有第一次获取单件时候,才会造成多线程bug,所有我们改善一下哈

急切式
package headfirst.hd.singleton;

public class Singleton {

    static Singleton uniqueInstance = new Singleton();

    private Singleton() {} 

    static Singleton getInstance() {
        return uniqueInstance;
    }

}
双重检查加锁
public class Singleton {  
    private volatile static Singleton uniqueInstance;  

    private Singleton() {}  

    public static Singleton getInstance() {  
        if (uniqueInstance == null) {  
            synchronized (Singleton.class) {  
                if (uniqueInstance == null) {  
                    uniqueInstance = new Singleton();  
                }  
            }  
        }  
        return uniqueInstance;  
    }  
}  

为什么要加关键字volatile
参考:http://blog.csdn.net/dengjili/article/details/79464014

将类改造为单件模式案例

主要分以下步骤(使用急切式,毕竟简单)

  1. 【第一步】将构造方法改为私有方法
  2. 【第二步】定义静态变量,并实例化变量
  3. 【第三步】提供唯一获取单件的方法

案例
原来类ChocolateBolier

package headfirst.hd.singleton;

public class ChocolateBolier {

    private boolean empty;
    private boolean boiled;

    public ChocolateBolier() {
        this.empty = true;
        this.boiled= false;
    }

    public void fill() {
        if (isEmpty()) {
            empty = false;
            boiled = false;

            //填充巧克力和牛奶的混合物
        }
    }

    public void drain() {
        if (!isEmpty() && isBoiled()) {
            empty = true;

            //排除煮熟的巧克力和牛奶的混合物
        }
    }

    public void boil() {
        if (!isEmpty() && !isBoiled()) {
            boiled = true;
            //排除煮熟的巧克力和牛奶的混合物
        }
    }

    public boolean isEmpty() {
        return empty;
    }

    public boolean isBoiled() {
        return boiled;
    }




}

将类ChocolateBolier改造为单件

package headfirst.hd.singleton;

//使用急切式,毕竟简单
public class ChocolateBolier {

    //【第二步】定义静态变量,并实例化变量
    static ChocolateBolier instance = new ChocolateBolier();

    private boolean empty;
    private boolean boiled;

    //【第一步】将构造方法改为私有方法
    private ChocolateBolier() {
        this.empty = true;
        this.boiled= false;
    }

    //【第三步】提供唯一获取单件的方法
    static ChocolateBolier getInstance() {
        return instance;
    }

    public void fill() {
        if (isEmpty()) {
            empty = false;
            boiled = false;

            //填充巧克力和牛奶的混合物
        }
    }

    public void drain() {
        if (!isEmpty() && isBoiled()) {
            empty = true;

            //排除煮熟的巧克力和牛奶的混合物
        }
    }

    public void boil() {
        if (!isEmpty() && !isBoiled()) {
            boiled = true;
            //排除煮熟的巧克力和牛奶的混合物
        }
    }

    public boolean isEmpty() {
        return empty;
    }

    public boolean isBoiled() {
        return boiled;
    }




}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值