设计模式之单例模式(singleton)

一、引言:
单例设计模式是非常常见的一种设计模式,在java中,单例设计模式确保了每个类只有一个实例,其实现的原理是将构造方法声明为private

二、示例代码:
下面这段代码是最佳的单例模式代码:

public class singleton{
	
	public static void main(String[] args){
	/* 调用三次,看是否只有一个对象生成 */
	for(int i = 0; i < 3; i++){
		Emperor emperor = Emperor.getInstance();
		emperor.say();  
		}		
	}
}

class Emperor{
	
	/* 内部构造唯一的对象 */
	private static final Emperor emperor = new Emperor();
	
	/* 构造函数private化 */
	private Emperor(){
		System.out.println("Constructor Emperor!");
	}
	/* 返回唯一对象 */
	public static Emperor getInstance(){
		return emperor;
	}
	/* 测试对象 */
	public static void say(){
		System.out.println("The only one Emperor is me!");
	}
}

这段代码的好处在于不会在并发环境下产生多个对象,因为唯一对象是在类内部通过类加载的时候构造的,但是有时候的一些单例模式代码就会出现多个对象的情况:

public class Singleton {
     private static Singleton singleton = null; 
     //限制产生多个对象
     private Singleton(){
     }  
     //通过该方法获得实例对象
     public static Singleton getSingleton(){
             if(singleton == null){
                    singleton = new Singleton();
             }
             return singleton;
     }
}

这个实例中,假如线程A正在执行singleton = new Singleton();而线程B此时正好在执行
if(singleton == null)这个语句,因为对象初始化需要时间,而正好此时的对象还没有创建起来,那么线程B会继续往下执行,就会出现两个线程拥有两个对象的情况,解决的办法就是在getSingleton方法之前加上synchronized关键字,不过,对于高并发模式,显然不是最优的方式。
所以,对于java中单例模式的最佳设计如下:

public class Singleton {
     private static final Singleton singleton = new Singleton();        
     //限制产生多个对象
     private Singleton(){
     }
	//通过该方法获得实例对象
     public static Singleton getSingleton(){
             return singleton;
     }  
     //类中其他方法,尽量是static
     public static void doSomething(){
     }
}

三、拓展:
1.单例模式的拓展是多例模式,就是限定产生的对象数,这里顺便说一下C/C++中的单例模式,C++也是面向对象的语言,所以,从原理上来讲,面向对象部分的单例模式和java示例如出一辙,但是C++和C中面向过程时,单例模式怎么实现的呢?答案是通过全局变量的方式,我们看一下binder中,单例模式在面向过程中的的应用:

sp<ProcessState> ProcessState::self()
{
    Mutex::Autolock _l(gProcessMutex);
    if (gProcess != NULL) {
        return gProcess;
    }
    gProcess = new ProcessState;
    return gProcess;
}

这段代码摘自Android的binder机制,每个binder服务中,有且只有一个ProcessState用于记录当前服务的状态,上面的代码中,将描述状态的类ProcessState设为全局变量,保证了整个进程中,凡是使用到了gProcess 的地方都只有唯一的一个状态来维护。

2.java中构造方法声明为private的使用:
java中,类外部不能直接以实例化private关键字声明的构造方法的方式构造对象。

public class hello{
	
	public static void main(String[] args){
		System.out.println("hello world!");
		/* 实例化对象成功,因为对应的构造是default的访问权限 */
		Emperor ep = new Emperor("张三");
		/* 编译报错,因为对应的构造为private权限,不能在类外调用 */
		Emperor ep1 = new Emperor();
	}
}

class Emperor{
	/* private构造 */
	private Emperor(){
		System.out.println("create a Emperor class!");
	}
	/* default构造 */
	Emperor(String name)
	{
		System.out.println("create a Emperor class:" + name);
	}
}

博客参考书籍:秦小波 《设计模式之禅(第2版)》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值