单例模式(2)

面试的时候被问到单例模式如何只创建一个实例对象?在一个类中怎么能调用构造函数呢?
没回答上来。
单例模式和工厂模式
程杰的《大话设计模式》上有,讲得很通俗易懂。
单例模式有3个要点:
(1)某个类只能有一个实例(那如何确保它只有一个实例?)在创建对象的时候,先判断对象是否存在?
(2)它必须自行创建这个实例(那它又是如何来创建这个实例呢?)通过另外一个函数调用构造函数。
(3)它必须自行向整个系统提供这个实例那如何自行提供呢?返回一个我自己。

public class GirlFriend{
	private static GirlFriend girlFriend;//在我的定义里面,有一个静态的我自己
	private String name;

	private GirlFriend(String name){
		this.name = name;
		System.out.println("制作完成");
	}
	//有一个静态的获取方法,调用我自身的私有构造
	public static GirlFriend getInstance(String name){
		if(girlFriend == null){
			girlFriend = new GirlFriend(name);//它必须自行建立这个实例
			//它必须自行向整个系统提供这个实例
		}
		return girlFriend;
	}
}

9、单例模式中有个懒汉模式和饿汉模式?
曾看过一篇比较有趣的文章:单例模式–我的机器人女友
java写的,其中volatilesynchronized不太理解。

public class GirlFriend{
	private String name;
	
	public GirlFriend(String name){
		this.name = name;
		System.out.println("制作完成");
	}
	
	public void smile(){
		System.out.println("smile");
	}
	
	public static void main(String[] args{
		GirlFriend girlFriend = new GirlFriend("小丽");
		girlFriend.smile();
	}
}

//单例模式
public class GirlFriend{
	public static GirlFriend girlFriend;
	
	private String name;
	
	public GirlFriend(String name){
		this.name = name;
		System.out.println("制作完成");
	}
	
	public static GirlFriend getInstance(String name){
		if(girlFriend == null){
			girlFriend = new GirlFriend(name);
		}
	}
	
	public void smile(){
		System.out.println("smile");
	}
	
	public static void main(String[] args{
		//GirlFriend girlFriend = new GirlFriend("小丽");
		GirlFriend girlFriend = GirlFriend.getInstance("小丽");
		girlFriend.smile();
	}
}

//通过多线程破坏单例模式
//单例模式
public class GirlFriend{
	public static GirlFriend girlFriend;
	
	private String name;
	
	public GirlFriend(String name){
		this.name = name;
		System.out.println("制作完成");
	}
	
	public static GirlFriend getInstance(String name){
		if(girlFriend == null){
			girlFriend = new GirlFriend(name);
		}
	}
	
	public void smile(){
		System.out.println("smile");
	}
	
	public static void main(String[] args){
		//GirlFriend girlFriend = new GirlFriend("小丽");
		for(int i = 0; i < 5; i++){//5个线程同时运行,顺利创建多个不同的对象。
			new thread( new Runable(){
				@Override
				public void run(){
					GirlFriend girlFriend = GirlFriend.getInstance("小丽");
					girlFriend.smile();
				}
			}).start();
			/***********************************************
				线程1                         			线程2
			T1:	if(girlFriend == null){
			T2:								  			if(girlFriend == null){
			T3:	girlFriend = new GirlFriend(name);
			T4:											girlFriend = new GirlFriend(name);
			T5: return girlFriend;
			T6: 										return girlFriend;
			线程1和线程2判断girlFriend的时候如果都为空,就会各自创建一个对象,最后就会返回两个不同的对象了。
			***********************************************/
			
			
		}
		
	}
}



//懒汉式:添加同步锁
public class GirlFriend{
	public static GirlFriend girlFriend;
	
	private String name;
	
	public GirlFriend(String name){
		this.name = name;
		System.out.println("制作完成");
	}
	
	//既然多线程会破坏单例模式,那么使用进程互斥就可以阻止多线程的不安全问题了。
	//使用互斥锁synchronized
	public synchronized static GirlFriend getInstance(String name){
		if(girlFriend == null){
			girlFriend = new GirlFriend(name);
		}
		return girlFriend;
	}
	/*
	使用互斥锁会产生一些效率问题。
	synchronized同步方法只有第一次创建对象的时候用得到,一旦创建了girlFriend对象后
	就用不到这个同步功能了,以后每次调用getInstance方法都会同步代码,严重降低了效率。
	*/
	public void smile(){
		System.out.println("smile");
	}
	
	public static void main(String[] args){		
		GirlFriend girlFriend = GirlFriend.getInstance("小丽");
		girlFriend.smile();	
	}
}

//饿汉式:在类加载的时候就创建对象。
public class GirlFriend{
	public static GirlFriend girlFriend = new GirlFriend("小丽);
	
	private String name;
	
	public GirlFriend(String name){
		this.name = name;
		System.out.println("制作完成");
	}
	
	public static GirlFriend getInstance(String name){
		return girlFriend;
	}
	/*
	存在的问题:
	(1)不支持延迟加载(在真正用到对象的时候,再创建实例);在类加载的时候,对象就创建好了。
	如果对象在整个过程中一次都用不到,提前创建就浪费了。
	(2)不能控制对象的数量,完全可以声明多个对象,比如
	GirlFriend girlFriend1;
	GirlFriend girlFriend2;
	GirlFriend girlFriend3;
	(3)可能没有足够的信息在静态初始化时,实例化每个对象,对象的构造方法参数可能要依赖程序后面的运算结果。
	*/
	public void smile(){
		System.out.println("smile");
	}
	
	public static void main(String[] args){		
		GirlFriend girlFriend = GirlFriend.getInstance("小丽");
		girlFriend.smile();	
	}
}



//双重检测
public class GirlFriend{
	//volatile关键字保证了每个线程看到的girlFriend对象都是最新的。
	public volatile static GirlFriend girlFriend;
	
	private String name;
	
	public GirlFriend(String name){
		this.name = name;
		System.out.println("制作完成");
	}
	
	public static GirlFriend getInstance(String name){
		if(girlFriend == null){//检查girlFriend对象的时候,如果为null就进入同步代码
			synchronized (GirlFriend.class){
				if(girlFriend == null){//每个线程重新判断 volatile girlFriend对象是否为空,
					girlFriend = new GirlFriend(name);
				}
			}
		}
		return girlFriend;
	}
	
	public void smile(){
		System.out.println("smile");
	}
	
	public static void main(String[] args){		
		GirlFriend girlFriend = GirlFriend.getInstance("小丽");
		girlFriend.smile();	
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值