设计模式——单例模式

类型:创建型
定义:确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
场景问题:在一个系统运行期间,某个类只需要一个类实例就可以了。
具体实现:要求该类的构造方法私有化,提供一个静态方法来获取单例。

有两种方式:

1、懒汉式

懒汉式:需要创建对象的时候才创建,以时间换空间  体现了延迟加载的思想Lazy Load,还体现了缓存的思想(if...) 

public final class SingleInstance { //使用final关键字,类不能被继承

private static SingleInstance instance;

private SingleInstance() {
	//构造函数私有化,外界无法通过new关键字创建对象
}

public static SingleInstance getInstance() {
	if (null == instance) {
		synchronized (SingleInstance.class) {//添加同步锁,避免多线程环境下创建出多个实例
			if (null == instance)
				instance = new SingleInstance();
		}
	}
	return instance;
  }
}	


2、饱汉式

饿汉式:一开始就创建好对象,直接访问即可    以空间换时间(占用内存,但是能直接返回对象,速度快).

public final class SingleInstance { //使用final关键字,类不能被继承

private static SingleInstance instance=new SingleInstance;

private SingleInstance() {
	//构造函数私有化,外界无法通过new关键字创建对象
}

public static SingleInstance getInstance() {
	return instance; 
  }
}	

二、如何创建带有构造参数的单例

如果在创建对象时,需要注入参数,那么这种单例模式如何创建呢?

public final class SingleInstance {

	private String param1; // 配置参数1
	private String param2; // 配置参数2
	
	private static SingleInstance instance;
	
	private SingleInstance(String param1,String param1) {
		this.param1 = param1;
		this.param2 = param2;
	}
	public static SingleInstance getInstance(String param1,param2) {
		if (null == instance) {
			synchronized (SingleInstance.class) {
				if (null == instance)
					instance = new SingleInstance(param1,param2);
			}
		}
		return instance;
	}
}	
由于构造函数需要带有参数,导致我们获取单例时每次都需要传入参数param1,param2, 当然这种方式是不可取的。下面给大家带来一种比较优雅的实现方式

public final class SingleInstance {

private String param1; // 配置参数1
private String param2; // 配置参数2

private static SingleInstance instance;


private SingleInstance() {
	this(new SingleInstanceBuilder());// 默认配置
}

private SingleInstance(SingleInstanceBuilder builder) {
	param1 = builder.param1;
	param2 = builder.param2;
}
public static SingleInstance getInstance() {
	if (null == instance) {
		synchronized (SingleInstance.class) {
			if (null == instance)
				instance = new SingleInstance();
		}
	}
	return instance;
}

//对外提供的业务方法
public void  fun1(){
	
}

//---------------------------对象构建器-------------------------------
/**
 * 对象构建者,设置不同的属性可构建出不同对象
 * @author 张全
 */
public static class SingleInstanceBuilder {
	private String param1;
	private String param2;

	public SingleInstanceBuilder() {
		// 初始化一些默认配置
		param1 = "";
		param2 = "";
	}

	// 配置1
	public SingleInstanceBuilder param1(String param) {
		this.param1 = param;
		return this;
	}

	// 配置2
	public SingleInstanceBuilder param2(String param) {
		this.param2 = param;
		return this;
	}

	// 构建对象
	public SingleInstance build() {
		//配置校验
		if(null==param1)throw new RuntimeException("请配置param1参数");
		return new SingleInstance(this);
	}

	// 构建对象,供SingleInstance.getInstance()获取
	public SingleInstance installDefaultInstance() {
		synchronized (SingleInstance.class) {
			if (SingleInstance.instance != null) {
				throw new RuntimeException("已存在实例");
			}
			SingleInstance.instance = build();
			return SingleInstance.instance;
		}
	}

}

}

下面来看看如何使用这种创建方式

//1、完成配置
SingleInstance instance = new SingleInstance.SingleInstanceBuilder()
.param1("配置1")
.param1("配置2")
.installDefaultInstance();

//2、任何地方调用单列
SingleInstance.getInstance().fun1();

可以看出,通过定义一个内部类来注入属性,可以完成单例对象的初始化。这种方式常见于很多开源框架设计中。


三、关于单例模式的一些注意事项

1、避免内存占用持续增大

由于单例模式保证一个类只有一个对象存在,则该对象的生命周期和系统生命周期一样长。避免持有一些大数据对象,引用的对象在不使用时应及时断开引用。

2、应注意持有对象的生命周期

对那些有固定生命周期的对象(比如Android中的Activity、Fragment等),在该对象生命周期结束时,应该将单例对象中持有的引用也断开,避免造成GC无法回收带来的内存泄漏问题。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值