设计模式学习笔记之单例模式

Posted birdlove1987

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式学习笔记之单例模式相关的知识,希望对你有一定的参考价值。

设计模式中最简单的模式就要数单例模式了。

那么什么是单例模式呢? 保证一个类仅有一个实例,并提供一个访问它的全局访问点。



上图为单例模式的结构示意图。


那么为什么要使用单例模式呢?

简单来说:单例模式的存在,一则,解决多线程并发访问的问题二则,节约系统内存,提交系统运行的效率,提高系统性能


下面我们就来看看程序中是怎么实现单例模式的:


一般我们设计一个类都是这样的:


public class Abc

	private Abc()
	
			
	;	


然后在其他部分调用:


public class Cbd

	public Cbd()
	
		Abc n1,n2;
		n1=new Abc();
		n2=new Abc();
	


但这样Abc这个类就会出现好多实体并不好控制,下面我们来改变一下啊Abc这个类的结构从而实现单例模式:


public class Abc
	
	private static Abc uniqeInstance_Abc = null; //通过内置私有静态参数实现单例状态
	
	private Abc()
		
	;
	
	//外部只能调用单例,单例实体有类内部控制
	public static Abc getInstance_Abc()
	
		if(uniqeInstance_Abc==null)
		
			uniqeInstance_Abc=new Abc();
		
		return uniqeInstance_Abc;
		
	


这样我们变实现了单例模式


public class Cbd

	public Cbd()
	
		Abc n1,n2;
		n1=Abc.getInstance_Abc();
	


可以看到Abc这个类的构造函数变成了private修饰,所以并不能在其他类中new出来只能通过调用getxxx函数来使用,这就保证了单例性。


写一个小例子,模拟一下我们计算机中的CPU处理程序:




package com.java.jikexueyuan.singleton;

public class Cpu 
	private boolean idle;
	private boolean compute;
	public volatile static Cpu uniqueInstance_cpu = null;
	int num;

	private Cpu() 
		idle = true;
		compute = false;
		num = 101;
	

	public static Cpu getInstance() 

		if (uniqueInstance_cpu == null) 
			synchronized (Cpu.class) 
				if (uniqueInstance_cpu == null) 
					uniqueInstance_cpu = new Cpu();
				
			
		
		return uniqueInstance_cpu;
	

	//判断cpu是否为空闲状态
	public boolean isIdle() 
		if (idle) 
			idle = false;
			compute = false;
			System.out.println("cpu空闲");
			return true;
		
		else
		
			System.out.println("cpu繁忙");
			return true;
		
	
	
	//cpu计算结束
	public void compute_over() 
		if ((!idle) && compute) 
			idle = true;
			compute = false;
			System.out.println("cpu计算完成");
		
	
	
	//启动cpu计算过程
	public void computing() 
		if ((!idle) && (!compute)) 
			compute = true;
			System.out.println("cpu正在计算,计算cpu编号为" + num);
		
	


我们来调用一下:


public class test 
	public static void main(String[] args) 
	
		for(int i = 0; i < 5 ; i++)
		
			Cpu c1 = Cpu.getInstance();
			if(c1.isIdle())
			
				c1.computing();
				c1.compute_over();
			
		
	



其实这样设计的单例模式有一个重大隐患,就是当两个线程同时创建一个Abc类的时候,可以会new出来两个实体而导致严重的错误。。。


解决传统的解决方式呢,有三种:

第一种:添加同步锁:


public class Abc
	
	private static Abc uniqeInstance_Abc = null; //通过内置私有静态参数实现单例状态
	
	private Abc()
		
	;
	
	//外部只能调用单例,单例实体有类内部控制
	//添加了同步所,保证不会有两个线程同是进入该方法
	public static synchronized Abc getInstance_Abc()
	
		if(uniqeInstance_Abc==null)
		
			uniqeInstance_Abc=new Abc();
		
		return uniqeInstance_Abc;
		
	


第二种:急切创建法:

public class Abc
	
	//通过内置私有静态参数实现单例状态
	//直接创建实例
	private static Abc uniqeInstance_Abc = new Abc();
	
	private Abc()
		
	;
	
	//外部只能调用单例,单例实体有类内部控制
	public static Abc getInstance_Abc()
	
		if(uniqeInstance_Abc==null)
		
			uniqeInstance_Abc=new Abc();
		
		return uniqeInstance_Abc;
		
	


第三种:双重检查加锁法


public class Abc
	
	//通过内置私有静态参数实现单例状态
	//volatile关键字确保多线程在处理时的正确性
	private volatile static Abc uniqeInstance_Abc = new Abc();
	
	private Abc()
		
	;
	
	//外部只能调用单例,单例实体有类内部控制
	public static Abc getInstance_Abc()
	
		//多重加锁
		if (uniqeInstance_Abc == null) 
			synchronized (Abc.class) 
				if (uniqeInstance_Abc == null) 
					uniqeInstance_Abc = new Abc();
				
			
		
		return uniqeInstance_Abc;
	


单例模式的使用场景:

1.资源共享的情况下,避免由于资源操作时导致的性能或损耗等。如上述中的日志文件,应用配置。 
2.控制资源的情况下,方便资源之间的互相通信。如线程池等。 


以上是关于设计模式学习笔记之单例模式的主要内容,如果未能解决你的问题,请参考以下文章

《从零开始学Swift》学习笔记(Day 63)——Cocoa Touch设计模式及应用之单例模式

Java设计模式之单例模式

单例模式的学习笔记

effective java笔记之单例模式与序列化

设计模式:学习笔记——单例模式

设计模式之单例模式学习(C#)