一、单件模式
确保只有一个类只有一个实例,并提供一个全局访问点。
比如线程池,注册表等待应用
二、单件模式问题
对于多线程使用单件模式必须加上同步方法,缺点是会降低性能
public class Singleton{
private static Singleton uniqueInstance;
public static synchronized Singleton getInstance(){
if(uniqueInstance == null){
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}
建议:
1、如果getInstance()的性能对应用程序不是很关键,就什么都别做
2、使用“急切”创建实例,而不是延迟实例化的做法
public class Singleton{
private static Singleton uniqueInstance = new Singleton();
public static synchronized Singleton getInstance(){
return uniqueInstance;
}
}
3、用“双重检查加锁”,在getInstance()中减少使用同步
public class Singleton{
private volatile static Singleton uniqueInstance;
public static Singleton getInstance(){
if(uniqueInstance == null){
snchronized(Singleton.class){
uniqueInstance = new Singleton();
}
}
return uniqueInstance;
}
}
三、代码实现
package com.oyhp.singleton;
//巧克力工厂--设置为单一组件
public class ChocolateBoiler {
private boolean empty; //容器是否为空
private boolean boiled; //巧克力是否煮沸
private static ChocolateBoiler c; //静态属性
//私有构造器无法通过new创建示例
private ChocolateBoiler() {
//代码开始时,锅炉时空的
empty = true;
boiled = false;
}
//通过getInstance方法类内部创建实例
public static ChocolateBoiler getInstance(){
if(c == null)
c = new ChocolateBoiler();
return c;
}
/*
* 在锅炉内填入原料时,锅炉必须时空的。
* 一旦填入原料,就把empty和boiled标志设置好
*/
public void fill(){
if(isEmpty()){
empty = false;
boiled = false;
}
}
/*
* 锅炉排出时,必须时满的而且时煮沸过的。
* 排出完毕后把empty标志设回为true。
*/
public void drain(){
if(!isEmpty() && isBoiled()){
//排出煮沸的巧克力和牛奶
empty = true;
}
}
/*
* 煮混合物时,锅炉必须是满的,并且是没有煮过的。
* 一旦煮沸后,就把boiled标志设为true
*/
public void boil(){
if(!isEmpty() && !isBoiled()){
//将炉内物煮沸
boiled = true;
}
}
public boolean isEmpty() {
return empty;
}
public boolean isBoiled() {
return boiled;
}
}
package com.oyhp.singleton;
//单件模式使用注意,在多线程的情况下需要加同步锁
public class DoRun {
public static void main(String[] args) {
ChocolateBoiler c1 = ChocolateBoiler.getInstance();
ChocolateBoiler c2 = ChocolateBoiler.getInstance();
System.out.println("是否为同一个实例:" + (c1==c2));
}
}
四、类图
五、总结
确保一个类只有一个实例,并提供全局访问点