设计模式(5)--单例模式
什么是单例模式
在一些场合下,我们有可能希望一个对象仅存在一个,例如线程池、缓存等,可能是因为这些对象创建一次很消耗性能,也可能是实际需要,这些都需要结合一定的实际场景。总的来说,就是无论用户怎么得到这个对象,它都是唯一一个,即为同一对象。
如何实现单例模式
首先我们先写一个平常类,如Simple
public class Simple { private String desc; public Simple(String desc) { this.desc = desc; } public String getDesc() { return desc; } }
可以很清楚看到这里包含了一个构造方法,且该方法作用域为public。
假如改成private,会怎么样呢?在其他类中肯定就无法new出这个对象了。
没有办法new出对象,那就不能随便在其他类中创建该类了,这个类的创建只有自己来负责创建,然后在通过一个静态方法来返回这个对象,感觉好像符合需求。
修改实例代码:
public class Simple { private String desc; private static Simple instance; private Simple(String desc) { this.desc = desc; } public static Simple getInstance(String desc) { if (instance == null) { instance = new Simple(desc); } else { instance.setDesc(desc); } return instance; } private void setDesc(String desc) { this.desc = desc; } public String getDesc() { return desc; } }
相信你已经迫不及待的想测试下你的代码了,可以参考下面示例:
public class Test { public static void main(String[] args) { System.out.println(Simple.getInstance("v1")); System.out.println(Simple.getInstance("v2")); } }
运行后你会发现两个输出是一致的。
但是这种单例模式是存在线程安全问题的,当多个线程调用Simple.getInstance()方法是就会出现问题。为什么呢?比如现在有两个线程,分别为线程a和线程b,线程a调用这个方法,运行到if判断语句中了,但是还没有创建这个对象,被要求沉睡10s,此时线程b也运行到if判断这里了,这时候获取到的对象肯定还是为空,那么它也会创建对象了。这时候就会创建出两个不一样的对象,自然就不符合要求呢?
既然getInstance这个方法可能会被同时调用,那么就不在这个方法内进行判断,直接在声明是就创建,然后这个方法直接返回对象就好了。
示例如下:
public class Simple { private String desc; private static Simple instance = new Simple("default"); private Simple(String desc) { this.desc = desc; } public static Simple getInstance(String desc) { instance.setDesc(desc); return instance; } private void setDesc(String desc) { this.desc = desc; } public String getDesc() { return desc; } }
红色标记表示修改处,这样就不存在线程安全了,但是有没有什么缺陷呢?
答案是有,这种方法就是无论你是否使用这个方法,这个类对象都会被创建,而第一种则是只有使用时才会进行创建,也可以被称为“延迟加载”。至于用哪一种根据实际项目需求,但是不要忘了第一种方法存在线程安全问题,当然这个是可以解决的,怎么解决可以自己去搜索下。
下一篇将介绍命令模式,如果你对这篇博客有什么见解或疑问,可以进行留言哦