介绍
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。
每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。
总之,选择单例模式就是为了避免不一致状态,避免政出多头。
特性:
- 单例类只能有一个实例。
- 单例类必须自己创建自己的唯一实例。
- 单例类必须给所有其他对象提供这一实例。
单例模式保证了全局对象的唯一性,比如系统启动读取配置文件就需要单例保证配置的一致性。
单例模式之自我分析
缺点:
- 一般没有接口,扩展很困难,如果想扩展的话,除了修改代码基本上没有第二种方式
- 使用的场景比较单调,如果是在多场景不断变化的实例对象最好不要使用单例,数据容易出问题
优点:
- 由于只有一个实例对象,所以占用内存很少
- 对象不用重复new了,当然于解放了对资源的重复占用,提升了性能
- 比类操作更灵活
单例模式之实现
俗话说,说的比唱的好听。为了证明我唱的也很好听,接下来我就以人类的一夫一妻制来具体讲解一下如何实现我的模式~一夫一妻制又称作”单偶婚“,“个体婚”,据说一夫一妻制起源于秦始皇统一天下之后
自大秦一统天下,中国酒实行了一夫一妻制,尤其是在汉朝“罢黜百家,独尊儒术”开始,古人严格执行了这一制度blablabla...(此处省略n字)。咳咳,跑题了,我们接着谈一夫一妻制,哦不,单例模式,首先得有个妻子类:
public class Wife{
private static final Wife wife = new Wife();
private Wife(){
}
public static Wife getInstance(){
return wife;
}
public static void say(){
System.out.println("I am Y's wife!");
}
}
通过定义一个私有访问权限的构造函数,可以避免被其他类new出来一个对象,而Wife自己可以new一个对象出来,其他的类对该类的访问可以通过getInstance获得一个对象。妻子有了,老公Y自然要出场了,其类代码如下:
public class Y{
public static void main(String[] args) {
for (int day=0; day<3;day++ ) {
Wife wife = Wife.getInstance();
wife.say();
}
}
}
运行结果如下:
I am Y's wife!
I am Y's wife!
I am Y's wife!
Y每天回家见到的妻子,都是同一个妻子,不会出现开门后,一看,呦呵,老婆怎么变了?
如有此情况,请速与我联系!
单例模式之优化/问题
有人嫌这样麻烦,因为无论是都使用这个类,都会创建一个instance对象,如果创建这个很耗时,比如需要连接10**9(python的10的9次方写法)次数据库,并且还不一定使用,那该这么办?于是乎有“聪明人”想到如下的方法:
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
是不是感觉很不错,很好?这个是传说中的懒汉模式其实这个有个很大的问题,如果是高并发情况下,可能A线程在创建实例,但是还没获取对象,B此时也在执行,判断也为真,所以又获得一个对象,如此下去,你的妻子会越来越多!没办法了么?不,当然有,且往下看:
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
这种写法确实解决了问题,但是效率么,啧啧,99%情况下不需要同步我会告诉你么?
奇淫技巧:单例模式之反射实现
public class Singleton{
private static Singleton singleton;
static{
try{
class cl = class.forName(Singleton.class.getName());
//获得无参构造
Constructor con = cl.getDeclaredConstructor();
//设置无参构造是可访问的
con.setAccessible(true);
//产生一个实例对象
singleton = (Singleton)con.newInstance();
}
catch(Exception e)
{
}
}
public static Singleton getSingleton(){
return singleton;
}
}
实现原理是:通过获得类构造,然后设置访问权限,生成一个对象,然后提供外部访问,保证内存对象单一。
一个挺有意思的角度,枯燥的理论换个表达方式理解起来有不一样的效果
参考文章:
设计模式之单例模式(JAVA实现)