设计模式之单例模式
在程序设计中,单例模式是非常常用的一个设计模式,至于有点老夫就不用多说了,肯定有一点比较省内存,但什么的类适合于设置成单例呢?一言以蔽之:
在程序设计中,无状态的类都可以设置成单例。
那么问题来了,什么样的类是无状态的,什么样的类是有状态的呢?其实很简单:
没有数据,也就是说这个类只有方法,没有成员变量。
举个例子:
User类是否可以设置成单例呢?肯定不行,因为User类每一个对应的Id肯定是不同的人,如果设置成单例,数据就乱了;但一般Service层、DAO层的方法呢?这个一般都是一些业务逻辑,只有一些方法,没有数据,所以肯定可以设置成单例,事实上我们这些类如果有Spring托管,那么自然而然这些类就是单例的。
既然单例使用这么多,有点还这么明显,那么怎么设置一个类是单例的呢?根据老夫第一个项目经理Zack的说法,设置一个类成单例的,有两种方法,首先看第一个,传统意义上的单例:
package cn.bridgeli.singleton; public class Singleton { private static volatile Singleton singleton = null; private Singleton() { } public static Singleton getInstance() { if (null == singleton) { synchronized (Singleton.class) { if(null == singleton) { singleton = new Singleton(); } } } return singleton; } }
这个最简单,构造方法设置成私有的,别人就不能new了,想获取实例必须通过getInstance()方法,而这个方法里面是static的,所以这是一个传统意义上的最简单的单例。
除此之外,我们还可以借助于静态内部类的方式实现单利:
package cn.bridgeli.demo.singleton; public class Singleton { private Singleton() { } public static Singleton getInstance() { return SingletonHolder.INSTANCE; } private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } }
第二个,管理意义上的单例
我们自己观察可以发现,这个虽然简单,但我们Spring实现的单例,肯定不是这么实现的,那么他是怎么实现的呢?Spring并没有限制我们自己写的类必须要有一个私有的构造方法,所以管理意义上的单例,并不要一个类有一个私有的构造方法,但他会通过一个BeanFactory产生我们想要的实例,参考代码如下:
package cn.bridgeli.singleton; import java.util.HashMap; import java.util.Map; import cn.bridgeli.justforfun1992.service.UserService; import cn.bridgeli.justforfun1992.service.impl.UserServiceImpl; public class BeanFactory { private static BeanFactory beanFactory = null; private static Map<String, Object> beans = new HashMap<String, Object>(); private BeanFactory() { } public static BeanFactory getInstance() { if (null == beanFactory) { beanFactory = new BeanFactory(); } return beanFactory; } public static Object getBean(String key) { if (!beans.containsKey(key)) { if (key.equals("UserService")) { UserService userService = new UserServiceImpl(); beans.put(key, userService); } } return beans.get(key); } }
UserService类
package cn.bridgeli.justforfun1992.service; public interface UserService { void add(User user); }
UserServiceImpl类
package cn.bridgeli.justforfun1992.service.impl; import cn.bridgeli.justforfun1992.service.UserService; public class UserServiceImpl implements UserService { @Override public void add(User user) { System.out.println("saved"); } }
所以当我们想获取UserService的实例时,可以通过这个BeanFactory获取,所以我们虽然没有给UserServiceImpl设置私有构造方法,同样也实现了单例,但是这么做也有一点不好,因为没有私有构造方法,所以你禁不住别人 new ,这就要求我们开发人员遵守好规则,大家只能通过getBean()去获取实例,其实我相信有些人也应该看出来了,这个BeanFactory其实是一个工厂,他负责产生我们想要的各种Bean,所以这里面也应用了工厂模式。
最后在补充一点:如果我们改造一下getBean()方法,内部实现不是直接new,而是通过读取XML文件,利用反射实例化实例,是不是我们就模拟出来了Spring的IOC?其实很简单,感兴趣的同学可以自己去实现以下,老夫就不赘述了
作 者: BridgeLi,https://www.bridgeli.cn
原文链接:http://www.bridgeli.cn/archives/113
版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。
就向你学习Java了