java设计模式——单例模式

单例模式:

定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

优点:1.在内存中只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例。

          2.避免对资源的多重占用。

还可以使用在某些特定的场景中:这一个类只能有一个对象。


实现的基本思路:

1.不能随意的创建对象-私有化构造器。

2.唯一的对象作为类的静态属性,该对象只能初始化一次。

3.提供一个可以返回唯一对象的方法。

实现方式1-饿汉式:

public class SingleExampleHungry {

	private String name ;
	private Integer age;
	//私有化的构造器,不允许外部私自创建对象。
	private SingleExampleHungry(){
		
	}
	//私有化的类的对象。
	private static final SingleExampleHungry seh = new SingleExampleHungry();
	//提供一个可以返回对象的方法。
	public static SingleExampleHungry getInstance(){
		return seh;
	}

        //私有属性的getter和setter方法。
} 

这种方式是通过先预先创建好对象,当需要创建该类的对象时就直接提供,用时间代替空间,等待调用,线程安全。

另一种饿汉式实现方式-静态初始化块。

public class SingleExampleLasy {

	private String name;
	private Integer age;
	private Integer sex;
	
	/*私有化一个该类的对象,并且是静态的,只能创建一次。*/
	private static SingleExampleLasy se;
	
	/*私有化构造器*/
	private SingleExampleLasy() {
		super();
	}
	
	/*创建对象的方法,如果创建的对象不为null就直接返回,为null就重新创建一个。*/
	public static SingleExampleLasy getInstance(){
		
		if(se==null){
			se= new SingleExampleLasy();
		}
		
		return se;
	}
	
	public static SingleExampleLasy getInstance(String name , Integer age,Integer sex){
		if(se==null){
			se = new SingleExampleLasy();
			se.age=age;
			se.name=name;
			se.sex=sex;
		}
		return se;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
	public Integer getSex() {
		return sex;
	}
	public void setSex(Integer sex) {
		this.sex = sex;
	}
	
}

public class SingleExampleHungryChange {

	private String name;
	private Integer age;
	
	private static SingleExampleHungryChange sehc;
	
	private SingleExampleHungryChange(){}
	
	static{
		sehc = new SingleExampleHungryChange();
	}
	
	public SingleExampleHungryChange getInstance(){
		return sehc;
	}

        //私有属性的getter和setter方法。
	
} 

以上两种处理方式都是在类加载时就将对象创建完毕,等待调用。

存在的缺点:浪费内存资源,不管这个类是否需要被实例化,都会创建对象,而且当这个类被多次加载时,也会创建多个对象。

实现方式2-懒汉式:

与饿汉式不同,懒汉式采取的方式是与正常创建对象类似,需要该类创建对象时才创建,但是只能只创建一次。用空间代替时间,但是会存在线程安全问题。

public class SingleExampleLasy {

	private String name;
	private Integer age;
	private Integer sex;
	
	/*私有化一个该类的对象,并且是静态的,只能创建一次。*/
	private static SingleExampleLasy se;
	
	/*私有化构造器*/
	private SingleExampleLasy() {
		super();
	}
	
	/*创建对象的方法,如果创建的对象不为null就直接返回,为null就重新创建一个。*/
	public static SingleExampleLasy getInstance(){
		
		if(se==null){
			se= new SingleExampleLasy();
		}
		
		return se;
	}
	
	public static SingleExampleLasy getInstance(String name , Integer age,Integer sex){
		if(se==null){
			se = new SingleExampleLasy();
			se.age=age;
			se.name=name;
			se.sex=sex;
		}
		return se;
	}
	//私有属性的getter和setter方法。
}

这种处理方式存在线程安全问题:

当第一个线程创建该类对象时,因为未知原因阻塞。第二个线程开始创建对象,就会导致创建多个对象,不符合单例模式的基本  目的。

通过增加同步锁的方式来提高线程安全。

public class SingleExampleChange {

	private String name ;
	private Integer height;
	
	private static SingleExampleChange sec;
	
	private SingleExampleChange(){
		
	}
	
	/*修饰符synchronized 实现同步锁的需求*/
	private static synchronized void createObject(){
		if(sec == null){
			sec = new SingleExampleChange();
		}
	}
	
	public static SingleExampleChange getInstance(){
		createObject();
		return sec;
	}
	
	public static SingleExampleChange getInstance(String name , Integer height){
		createObject();
		sec.name=name;
		sec.height=height;
		return sec;
	}
        //私有属性的getter和setter方法。
}

以上方式通过加同步锁的方式可以实现线程安全,但是还是存在效率低的问题,可以通过加双层同步锁的方式来解决,这里我还没有理解透彻,先待定。

实现方式3-枚举法:

public enum SingleExample {

	INSTANCE;
	public void SingleExample(){
		
	}
}
枚举法防止了反序列化等问题。这个实现方法还没有理解,先待定。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值