黑马程序员_JAVA设计模式之单例模式

------- android培训java培训、期待与您交流! ----------

 

JAVA标准的设计模式里面包含了23个,单例模式是最经典的设计模式了,每个人学习JAVA设计模式,都以这个模式作为入门。JAVA是一门优雅的语言,其中设计模式是最能说明这个的了,JAVA设计模式不仅仅是模式了,更是一种思想,不多说废话。

       单例模式的本质是:控制实例的个数。

       单例模式分饿汉式和懒汉式两种。

       饿汉式示例代码如下:

public class SingleCloud{        
	private int a ;        
	private String str;        
	private SingleCloud(){}   //似有化构造方法,不能让外界new出实例       
	private static  SingleCloud  instance = new SingleCloud();    //一定要静态的,这样类在加载的时候就创造实例       
	public static SingleCloud getInstance(){//当然获得实例的方法也是静态的,因为外界要访问非静态方法                
		return instance ;//构造方法我们使其私有,不能外界new的,因此这个方法必须静态,外界用类名就可访问,当然实例是类加载的时候就new出来了	       
	}        
	public void f1(){        
		//TODO      
	}        
	public String f2(){        
		//TODO      
	}     
}

 

懒汉式示例代码如下:

public class SingleCloud{ 
	private int a ;        
	private String str;        
	private SingleCloud(){}        
	private static SingleCloud instance = null;   //在类加载的时候先不要创建实例         
	public SingleCloud getInstance(){  //用到实例的时候再来创建实例               
		if (null == instance){    //先判断是不是已经创建过了                        
			instance = new SingleCloud();  //如果没有创建,那就进来创建实例                
		}                
		return instance ;        
	}        
	public void f1(){ 
		//TODO     
	}        
	public String f2(){        
		//TODO
	}     
}

饿汉式和懒汉式都有其好处和缺点,饿汉式是不管你用不用我都在类加载的时候创建实例,可能程序运行很久才用得到,当用到的时候直接获取就行了,这样就浪费了空间。而懒汉式,用到的时候才去创建实例,典型的以时间换空间。两者还有区别就是,饿汉式是线程安全的,而懒汉式是线程不安全的,解决方式如下:

public class SingleCloud{    
	private int a ;        
	private String str;        
	private SingleCloud(){}        
	private static SingleCloud instance = null;   //在类加载的时候先不要创建实例*/  
      
	public SingleCloud getInstance(){                
		if (null == instance){                        
			synchronized(SingleCloud.class){//进行同步,拿到的是类的同步监视器                                
				if (null == instance){                                        
					instance = new SinlgeCloud();                                
				}                        
			}                
		}	
		return instance;        
	} 
       
	public void f1(){        
		//TODO       
	}        

	public String f2(){        
		//TODO       
	}     
} 

还有一种方案可以延迟加载而又保证线程安全,就是采用类级内部类,其实就是静态的内部类,这种类是不与外部类的实例绑定的,所以外部类在加载的时候并不会去初始化这种内部类,而在使用到的时候才进行初始化,示例代码如下:

public class SingleCloud{        
	private SingleCloud(){}        
	public SingleCloud getInstance(){                
 		return SingleTonHolder.instance;        
	}        
	private static class SingleTonHolder{                
 		public static  SingleCloud  instance = new SingleCloud();        
	}    
}

其实最完美的单例是枚举类型,其实枚举的一个元素就是一个对象实例,枚举是一种特殊的类,首先它是类,也有属性也有方法,第二它是不能new出来的,它隐含的构造方法是私有的。

enum Grade{
	A(345,23,"xiaoming);//这里只能有一个元素
	
	
	
	private int score;
	
	private int age;
	private String name;
	
	private Grade(int score,int age,String name){//
		this.score = score;
		this.name = name;
		this.age = age;
	}
	public String toString(){
		return "score=="+score+",name=="+name+",age=="+age;
	}
}

后要说明的是,单例是在多大的范围内呢。很多人认为一台机器范围内,这是不正确的,应该是JVM范围内的单例,一个JVM可以运行多线程,一个JVM中的各个线程拿到的单例是同一个,如果一台机器上起了2个JVM,那么这个单例在同一个机器上就有两个实例了。




 


------- android培训java培训、期待与您交流! ----------
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值