设计模式之单例模式
来源:互联网 发布:客户关系 软件 编辑:程序博客网 时间:2024/05/16 10:24
单件模式
package designpatter.singleton;
public class Singleton {
//利用一个静态变量来记录Sinleton类的唯一实例
private static Singleton uniqueInstance;
//这里吧构造器申明为私有的,只有自Singleton类内才可以调用构造器
private Singleton(){}
//用getInstance方法实例化对象,并返回这个实例
public static Singleton getInstance(){
if(uniqueInstance ==null){
uniqueInstance=new Singleton();
}
return uniqueInstance;
}
}
单件:
独一无二,他是利用单件模式构造出来的,这个模式让让他在任何时刻都是只有一个对象,比如:如果注册表设置的对象,不想这样的对象有多个拷贝,就可以用单例模式,确保程序中使用的全局资源只有一份。
常常被用来管理共享资源,例如数据连接或者线程池
package designpatter.singleton;
/**
* 巧克力工厂
*/
public class ChoolateBoiler {
private boolean empty;
private boolean boiled;
//代码开始的时候,锅炉是空的
public ChoolateBoiler() {
empty=true;
boiled=false;
}
public void fill() {
if(isEmpty()){
empty=false;
boiled=false;
}
}
//锅炉排出时,必须是满的(不可以是空的)而且是煮过的,排出完毕后,把empty标志设为true;
public void drain(){
if(!isEmpty()&&isBoiled()){
empty=true;
}
}
public void boil(){
if(!isEmpty()&&!isBoiled()){
boiled=true;
}
}
public boolean isBoiled() {
// TODO Auto-generated method stub
return boiled;
}
public boolean isEmpty() {
// TODO Auto-generated method stub
return empty;
}
}
这里如何同事存在两个巧克力锅炉实例,可能将会发生很糟糕的事情,
单例模式:确保一个类只有一个实例,并提供一个全局访问点
package designpattern.signleton;
/**
*
* @author taojian
* @time 2017年3月5日下午6:31:48
* @ClassName ChoolateBoiler.java
* @description 现代化的巧克力工厂具备计算机控制的巧克力锅炉。锅炉要做的事情就是把巧克力和
* 牛奶融在一起,进入到下一个阶段,将普通类改写成单例模式
*/
public class ChoolateBoiler {
private boolean empty;
private boolean boiled;
private static ChoolateBoiler uniqueInstance;
private ChoolateBoiler() {
empty=true;
boiled=false;
}
/**
//代码开始的时候,锅炉是空的
public ChoolateBoiler() {
empty=true;
boiled=false;
}*/
public static ChoolateBoiler getInstance(){
if(uniqueInstance==null){
uniqueInstance=new ChoolateBoiler();
}
return uniqueInstance;
}
public void fill() {
if(isEmpty()){
empty=false;
boiled=false;
}
}
//锅炉排出时,必须是满的(不可以是空的)而且是煮过的,排出完毕后,把empty标志设为true;
public void drain(){
if(!isEmpty()&&isBoiled()){
empty=true;
}
}
public void boil(){
if(!isEmpty()&&!isBoiled()){
boiled=true;
}
}
public boolean isBoiled() {
// TODO Auto-generated method stub
return boiled;
}
public boolean isEmpty() {
// TODO Auto-generated method stub
return empty;
}
}
深入了解:
1.我们正在把某个类设计成自己管理的一个单独实例,同时也避免其他类再自行产生实例。想要取得单件实例,通过单件类是唯一的途径。
2.我们也提供对这个实例的全局访问点:当你需要实例时,向类查询,它会返回单个实例。前面的例子利用延迟实例化的方式创建单件,这种做法对资源敏感的对象特别重要。
问题继续研究:虽然将普通的巧克力锅炉改写成了单例模式,但是会出现问题,当在fill()的方法中加入原料。如何处理多线程的问题?
/**
*
* @author taojian
* @time 2017年3月5日下午6:45:22
* @methodname getInstance()
* @descripe 处理多线程的问题,只要把getInstance()改成同步的方法,多线程灾难几乎就可以轻易解决
* 通过synchronized关键字到getInstance()方法中,我们迫使每个线程在进入这个方法之前,要先等候别的线程离开该方法,也就是说不可以有两个
* 线程可以同时进入这个方法。
*/
public static synchronized ChoolateBoiler getInstance(){
if(uniqueInstance==null){
uniqueInstance=new ChoolateBoiler();
}
return uniqueInstance;
}
但是这里又会存在一个问题,只有第一次执行此方法时候,才真正需要同步。换句话说,一旦设置好uniqueInstance变量,就不再需要同步这个方法了,之后每次调用的时候,同步就是一种累赘。
为了符合大多数Java应用程序吗,很明显,我们需要确保单例模式能在多线程的状况下正常工作。但是似乎同步getIntance()的方法会影响性能。下面有几种选择:
1.如果getInstance()的性能对应用程序不是很关键,就什么都别做
2.使用急切创建实例,而不是用延迟实例化的方法。这种方式也叫做饿汉式的单例模式
public class SingletonTest2 {
//在静态初始化器中创建单例,这段代码保证了线程安全
private static SingletonTest2 uniqueInstance=new SingletonTest2();
//这里吧构造器申明为私有的,只有自Singleton类内才可以调用构造器
private SingletonTest2(){}
//用getInstance方法实例化对象,并返回这个实例
public static SingletonTest2 getInstance(){
//已经有了实例了,直接使用它。
return uniqueInstance;
}
}
3.用"双重检查加锁",首先检查是否实例已经创建,如果尚未创建,才进行同步,这里一来,只有第一次同步,这正是我们想要的。
public class SingletonTest3 {
//在静态初始化器中创建单例,这段代码保证了线程安全
private volatile static SingletonTest3 uniqueInstance;
//这里吧构造器申明为私有的,只有自Singleton类内才可以调用构造器
private SingletonTest3(){}
//用getInstance方法实例化对象,并返回这个实例
public static SingletonTest3 getInstance(){
if(uniqueInstance==null){
synchronized (SingletonTest3.class){
if(uniqueInstance ==null){
uniqueInstance=new SingletonTest3();
}}}
//已经有了实例了,直接使用它。
return uniqueInstance;
}
}
4.类加载的方式:延迟加载,线程安全,同步情况下效率高,不要进行同步控制,实现简单,不能防止反序列化
package designpattern.signleton;
/**
*
* @author taojian
* @time 2017年3月5日下午6:14:46
* @ClassName SingletonTest.java
* @description 单例模式,类加载方式
*/
public class SingletonTest4 {
//这里吧构造器申明为私有的,只有自Singleton类内才可以调用构造器
private SingletonTest4(){}
//静态内部类,用于持有唯一的SingletonClass的实例
private static class OnlyInstance{
static private SingletonTest4 ONLY=new SingletonTest4();
}
public static SingletonTest4 getInstance(){
return OnlyInstance.ONLY;
}
}
5.枚举方式:立即加载,线程安全,实现简单,防止反序列化。
public enum SingletonTest5 {
INSRANCE;
public void f(){
}
}
0 0
- 设计模式之 单例设计模式
- 设计模式之 单例设计模式
- 设计模式之单例设计模式
- 设计模式之-----------单例设计模式
- 设计模式之:单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之-单例设计模式
- 设计模式之单例设计模式 标签: 设计模式
- 设计模式之单例
- 设计模式之单例
- 设计模式之 单例
- ros 下语音调试-1
- HDU-6016
- final关键字
- 1如何将字串 String 与 int的相互转换?
- 网站地图爬虫章节遇到 TypeError: cannot use a string pattern on a bytes-like object
- 设计模式之单例模式
- Calendar的用法
- redux初体验之官方小项目详解
- 数论初步
- 2. 分组查询&&子查询
- 拓扑排序模板
- hadoop搭建三个节点(基于完全分布式)
- 第四周:84. Largest Rectangle in Histogram
- insert sql