设计模式-陈词滥调的单例

一万个人眼中有一万个哈姆雷特,一万个程序猿中有一万种对单例模式的理解,以下絮叨絮叨我对单例模式的理解。

引言

民间神抵中,财神是一位掌管财运的神仙,百姓渴望富足的心情在财神信仰中被表现的淋漓尽致。同一朝代只有一位财神,这种情况下百姓们也好信仰,大家烧香,膜拜的时候只要提及财神,每个人都知道指的是哪位神仙。不用在财神前面加上特定的称呼,如文财神比干、武财神赵公明,武财神关公,增幅财神沈万三。这一过程反应到软件设计领域就是一个类只能生成一个对象(财神),所有对象对他的依赖都是相同的(拜财神求富贵),因为只有一对象,大家对它的生平和喜好都非常了解,建立稳固的关系,我们将财神这种神仙职位通过代码方式实现出来。

财神每天都要接受百姓香火、分发财运,百姓每天都要给财神上香,财神只能有一个,也就是一个类只能创建一个对象,大家也都知道对象是通过关键字new完成的(当然也有反射等方式可以实现),但是要怎么控制呢?可以通过构造函数完成,肯定有人会说为什么呢?因为使用new关键字创建对象时都会根据传入的参数调用相应的构造函数,我们将构造函数设置为private私有权限不就可以防止外部创建对象了吗?

Mammon代表财神类,People代表百姓类,下面我们来实现这个逻辑,代码如下。

财神类


public class Mammon {
	private static final Mammon mammon = new Mammon();// 初始化一个财神

	private Mammon() {
//		道德的底线束缚着你,目的就是不希望出现第二个财神抢香火
	}

	public static Mammon getMammon() {
		return mammon;
	}

//	财神显灵了
	public static void apparition() {
		System.out.println("我就是财神,快来膜拜我吧!");
  }
}

通过定义一个私有构造器, 避免别的类new出一个对象,而Mammon自己则可以new出一个对象,其他只能通过getMammon获取这个对象。

百姓类


public class People {
	public static void main(String[] args) {
		for (int i = 0; i < 5; i++) {
			Mammon mammon = Mammon.getMammon();
			mammon.apparition();
		}
//		看看这五天显灵的是不是同一个财神
	}
}

运行结果

运行结果

百姓天天都要给财神上香求富贵,今天膜拜的财神应该和前几天的一样,嗨,还是昨天显灵的财神,仙风道骨、英姿飒飒,这就是我理解的单例模式。

单例模式的定义

单例模式(Singleton Pattern)定义如下:

确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。Singleton类简称单例类,通过使用private的构造函数确保了在一个项目中只产生一个实例对象,并且是自行实例化的(在Singleton中使用自己的new Singleton())。

##单例模式的几种实现方式

饿汉式


public class Singleton {
	private static final Singleton singleton = new Singleton();
//	限制产生多个实例
	private Singleton() {}
//	通过该方法获取实例
	public static Singleton getSingleton() {
		return singleton;
	}
//	类中的其他方法,尽量是static
	public static void demo() {
		System.out.println("hello world! my name is Singleton");
	}

优点:没有加锁,执行效率会提高。

缺点:类加载时就初始化,浪费内存。

懒汉式

public class Singleton {  
   private static Singleton singleton ;  
	    // 限制产生多个实例
	    private Singleton (){}  
        // 通过该方法获取实例
	    public static synchronized Singleton getInstance() {  
	    if (singleton == null) {  
	        singleton = new Singleton();  
	    }  
	    return singleton;  
	    }  
}

优点:第一次调用才初始化,避免内存浪费。

缺点:必须加锁 synchronized 才能保证单例,但加锁会影响效率。

双检锁/双重校验锁(DCL,即 double-checked locking)


public class Singleton {  
    private volatile static Singleton singleton;  
    private Singleton (){}  
    public static Singleton getSingleton() {  
    if (singleton == null) {  
        synchronized (Singleton.class) {  
        if (singleton == null) {  
            singleton = new Singleton();  
        }  
        }  
    }  
    return singleton;  
    }  
}

这种方式采用双锁机制,安全且在多线程情况下能保持高性能。

getSingleton() 的性能对应用程序很关键。

单例的应用场景

Spring 在Spring中,每个Bean的默认就是单例的,这样做的优点是Spring容器可以管理这些Bean的声明周期,决定什么时候创建出来,什么时候销毁,销毁时要如何处理等等。

代码地址

https://github.com/dxf1998/MyDesignPattern

文章转自公众号左羊公社

https://mp.weixin.qq.com/s/skI3BSBMaHcRWfHijF0QOg
左羊公社

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值