JAVA设计模式--单例模式
JAVA设计模式--单例模式
- 经典单例模式的原理
1.1 意义:有些类,实际应用中往往只能有一个对象。可能用可能不用,用也只能用这一个对象,比如打印机,显卡日志对象等,这样不会导致冲突,使结果一致。
1.2 问题解决:是否可以考虑静态变量方式来实现(构造方法私有化)?或者程序员之间协商全局变量。
1.3 单例模式:确保一个类最多只有一个实例,并提供一个全局访问点。
1.4 实际操作:使用private自己内部调用
单例模式类图:
案例:巧克力工厂
普通类中,因为工厂只有一个,但是实例有多个,这时会导致状态不一致,可以考虑用单例模式。
public class ChoclateFactory { private boolean empty; private boolean boiled; private static ChoclateFactory uniqeInstance=null ; private ChoclateFactory(){ empty=true; boiled=false; } //构造类对象 public static ChoclateFactory getInstance() { //是否为空,同事调用时保持状态不变 if(uniqeInstance==null){ uniqeInstance=new ChoclateFactory(); } return uniqeInstance; } public void Fill() { if(empty){ //添加 empty=false; boiled=false; } } public void Boil() { if((!empty)&&(!boiled)){ boiled=true; } } public void Drain() { if(!empty&&boiled){ empty=true; } } }
使用过程中,会出现一些问题,例如多线程(两个线程获取两个对象,无法保证唯一性)。
解决方法:①在getInstance添加一个同步锁(保证一个线程结束后,在执行下一个线程)
public static synchronized ChoclateFactory getInstance()
但是同步锁比较消耗资源,能解决问题,但不建议使用。
②“急切”创建实例
private static ChoclateFactory uniqeInstance=new ChoclateFactory() ;
调用运行时,直接创建对象,getInstance()直接返回,弥补了同步锁的资源消耗,但是如果不用工厂时,也会创建对象占用资源。
③双重检查加锁方法:
//volatile编译器使用处理多线程安全 private volatile static ChocolateFactory uniqeInstance=null ; //构造类对象 public static ChocolateFactory getInstance() { //是否为空,同事调用时保持状态不变 if(uniqeInstance==null){
//第一个线程执行到这里,为空.若第二个线程也到这里,也要为空,new对象,返回.二者只能一个进入
//获取到一个对象,返回;另一个线程重新进入时,判断不为空,跳出(只要进入一次,就不会为空了). synchronized (ChocolateFactory.class){ if(uniqeInstance==null){ uniqeInstance=new ChocolateFactory(); } } } return uniqeInstance; }
实际使用过程中建议使用②③这两种方法
2.单例模式的分类
单例模式有很多表现形式,常见的有懒汉式,饥汉式,登记式
懒汉式:是指类保留的对象的创建时间是在需要时进行(用到时才创建);
饥汉式:和懒汉式相反,类保留的对象在第一次访问时就创建了(和上面的"急切"创建法一致);