什么是单例模式?

单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例类的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。

单例模式的特点:

1、单例类有且只能有一个实例。

2、单例类需要自己创建一个自己的实例。

3、单例类需要为其他类提供这个实例。

哪些地方经常用到单例?

在计算机系统中,配置文件,线程池,缓存,日志对象,打印机等经常用到单例模式

所谓“一山不容二虎”,如果出现二虎很容易会出问题,比如配置文件,它终究只是一个文件,如果同时有好几个实例访问它并执行修改操作,那么这时候就会引发出一系列的问题

单例相对于多实例对象也更节约系统资源

单例模式常用的有几种模式?

一般来讲单例模式有三种,分别是:懒汉式,饿汉式,登记式。

下面直接上代码说明吧

①一个类之所以能够创建出实例是因为有构造方法的存在,只要我们把构造方法的访问修饰符改成私有(private),外界就不能通过new来创建该类的实例。

②在单例类中自身new出一个对象,因为要被外界访问,我们可以把它静态化(static),以便外界访问(类型.对象)。

③有时候我们需要控制这个对象,也处于安全起见,我们可以把继续私有化(private),然后提供一个getter方法以便外界访问。

SimpletonDemo1.java(单例类)

 package com.lcw.simpleton;

 public class SimpletonDemo1 {
//将构造方法私有化,阻止外界直接创建对象
private SimpletonDemo1() {
}
//提供static以便外界访问
private static SimpletonDemo1 instance = new SimpletonDemo1(); //提供getter方法以便外界访问私有化对象,static SimpleDemo1返回类型
public static SimpletonDemo1 getInstance() {
return instance;
}
}

SimpletonTest.java(测试类)

 package com.lcw.simpleton;

 public class SimpletonTest {
public static void main(String[] args) {
SimpletonDemo1 s1=SimpletonDemo1.getInstance();
SimpletonDemo1 s2=SimpletonDemo1.getInstance(); if(s1==s2){//检测对象的内存地址是否一致
System.out.println("s1和s2是同个对象");
}else{
System.out.println("s1和s2不是同个对象");
} }
}

效果如下:

上面所说的就是单例模式里饿汉模式,为什么叫饿汉模式呢?

由于这个实例是被static所修饰,被static修饰的成员属于类所有,当类加载的时候,这个成员就被加载了,也就是说不管外界是否调用这个类,它都已经被加载了。

看起来好像是饿汉,不管三七二十一,先吃了你再说。

下面再来看下单例模式中的懒汉模式

就字面上的意思,其实已经很明白了“懒汉模式”,顾名思义不同于饿汉模式,既然饿汉模式是不管三七二十一先吃了再说,那么懒汉模式当然就没那么勤快了,应该是被我们调用后的时候才去实例化对象。

它们的写法很类似,只不过是在用private static声明对象的时候不直接new对象,而是在gette方法里再去实例化对象

然后判断下这个对象是否为null,如果为null则实例化一个对象,如果不会空则直接返回对象。

下面看下具体代码

SimpletonDemo2.java(单例类)

 package com.lcw.simpleton;

 public class SimpletonDemo2 {
//将构造方法私有化,阻止外界直接创建对象
private SimpletonDemo2() {
}
//提供static以便外界访问
private static SimpletonDemo2 instance; //提供getter方法以便外界访问私有化对象,static SimpleDemo1返回类型
public static SimpletonDemo2 getInstance() {
if(instance==null){
return instance=new SimpletonDemo2();
}else{
return instance;
}
}
}

SimpletonTest.java(测试类)

 package com.lcw.simpleton;

 public class SimpletonTest {
public static void main(String[] args) {
SimpletonDemo1 s1=SimpletonDemo1.getInstance();
SimpletonDemo1 s2=SimpletonDemo1.getInstance(); if(s1==s2){//检测对象的内存地址是否一致
System.out.println("s1和s2是同个对象");
}else{
System.out.println("s1和s2不是同个对象");
} SimpletonDemo2 s3=SimpletonDemo2.getInstance();
SimpletonDemo2 s4=SimpletonDemo2.getInstance(); if(s3==s4){//检测对象的内存地址是否一致
System.out.println("s3和s4是同个对象");
}else{
System.out.println("s3和s4不是同个对象");
} }
}

效果如下:

总结下两种模式的区别:

1、饿汉式,在加载类的时候比较慢,由于它还要去实例化一个对象并造成内存资源的浪费,但在运行调用中的速度会比较快。

2、懒汉式,在加载类的时候比较快,由于在加载类的时候不需要去实例化对象,但在运行调用时的速度比较慢,由于还要去做判断。

还有一点很重要的是,饿汉模式是属于线程安全,而懒汉模式属于线程不安全,在高并发时会出现问题。

那有没有更好的方式呢?答案肯定是有的,我们可以结合了饿汉式和懒汉式各自的优点,不在加载类的时候实例化不必要的对象,又同时具备了线程安全

说直白的点就是利用内部类去静态实例化这个对象,由于内部类需要在外部类被调用的时候才会去加载,也就是说不会在没必要的时候去加载对象从而导致系统资源的浪费,同时我们在内部类中对这个对象实行静态实例化也就避免了线程安全这个问题。

 package com.lcw.simpleton;

 public class SimpletonDemo {
// 将构造方法私有化,阻止外界直接创建对象
private SimpletonDemo() {
} // 定义一个内部类用来实例化对象
private static class Inner_SimpletonDemo {
private static SimpletonDemo instance = new SimpletonDemo();
} // 提供getter方法以便外界访问私有化对象,static SimpleDemo1返回类型
public static SimpletonDemo getInstance() {
return Inner_SimpletonDemo.instance;
}
}

再来看下最后一种实现方式,登记式

由于懒汉式和饿汉式都把构造方法私有化了,所以它不能被继承,登记式可以解决这个问题

登记式单例模式  类似于Spring里面的用法,将类名注册并放到Map集合里,下次要用的时候直接取

登记式实际对一组单例模式进行的维护,主要是在数量上的扩展,通过map我们把单例存进去,这样在调用时,先判断该单例是否已经创建,是的话直接返回,不是的话创建一个登记到map中,再返回。对于数量又分为固定数量和不固定数量的。下面采用的是不固定数量的方式,在getInstance方法中加上参数(string name),然后通过子类继承,重写这个方法将name传进去。

SimpletonDemo3.java(单例类)

 package com.lcw.simpleton;

 import java.util.HashMap;
import java.util.Map; public class SimpletonDemo3 {
// 私有化构造器,保护钩子
private SimpletonDemo3() {
} private static Map<String, SimpletonDemo3> map = new HashMap<String, SimpletonDemo3>();
//静态代码块
static {
SimpletonDemo3 instance = new SimpletonDemo3();
map.put(instance.getClass().getName(), instance);
} // 参数name为类名
public static SimpletonDemo3 getInstance(String name) {
if (name == null) {
name = "com.lcw.simpleton.SimpletonDemo3";
}
if (!map.containsKey(name)) {
try {
map.put(name, (SimpletonDemo3) Class.forName(name)
.newInstance());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return map.get(name);
} }

SimpletonTest.java(测试类)

 package com.lcw.simpleton;

 public class SimpletonTest {
public static void main(String[] args) {
SimpletonDemo1 s1 = SimpletonDemo1.getInstance();
SimpletonDemo1 s2 = SimpletonDemo1.getInstance(); if (s1 == s2) {// 检测对象的内存地址是否一致
System.out.println("s1和s2是同个对象");
} else {
System.out.println("s1和s2不是同个对象");
} SimpletonDemo2 s3 = SimpletonDemo2.getInstance();
SimpletonDemo2 s4 = SimpletonDemo2.getInstance(); if (s3 == s4) {// 检测对象的内存地址是否一致
System.out.println("s3和s4是同个对象");
} else {
System.out.println("s3和s4不是同个对象");
} SimpletonDemo3 s5 = SimpletonDemo3.getInstance("com.lcw.simpleton.SimpletonDemo3");
SimpletonDemo3 s6 = SimpletonDemo3.getInstance("com.lcw.simpleton.SimpletonDemo3");
if (s5 == s6) {// 检测对象的内存地址是否一致
System.out.println("s5和s6是同个对象");
} else {
System.out.println("s5和s6不是同个对象");
}
}
}

效果图:

作者:Balla_兔子
出处:http://www.cnblogs.com/lichenwei/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。
正在看本人博客的这位童鞋,我看你气度不凡,谈吐间隐隐有王者之气,日后必有一番作为!旁边有“推荐”二字,你就顺手把它点了吧,相得准,我分文不收;相不准,你也好回来找我!

软件设计模式之单例模式(JAVA)的更多相关文章

  1. 软件设计模式之适配器模式(JAVA)

    什么是适配器模式? 在计算机编程中,适配器模式(有时候也称包装样式或者包装)将一个类的接口适配成用户所期待的.适配器能将因为接口不兼容而不能在一起工作的类工作在一起,做法是将类自己的接口包裹在一个已存 ...

  2. 设计模式之单例模式(JAVA实现)

    单例模式之自我介绍 我,单例模式(Singleton Pattern)是一个比较简单的模式,我的定义如下: Ensure a class has only one instance,and provi ...

  3. GOF23种设计模式之单例模式(java)

    GOF(group of four):四人帮 分类 创建者模式 单例模式 核心作用:保证一个类只有一个实例,并且提供一个访问该实例的全局访问点 优点: 由于单例模式只生成一个实例,减少了系统性能开销, ...

  4. Java中的设计模式之单例模式

    Java中的单例模式 设计模式是软件开发过程中经验的积累 一.单例模式 1.单例模式是一种常用的软件设计模式,通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控 ...

  5. Java常见设计模式之单例模式

         1.何为单例模式? 单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例类的特殊类.通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的 ...

  6. java设计模式之单例模式(几种写法及比较)

    概念: Java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍三种:懒汉式单例.饿汉式单例.登记式单例. 单例模式有以下特点: 1.单例类只能有一个实例. 2.单例类必须自己创建 ...

  7. java 23 - 2 设计模式之单例模式

    单例模式:保证类在内存中只有一个对象. 如何保证类在内存中只有一个对象呢?  A:把构造方法私有  B:在成员位置自己创建一个对象  C:通过一个公共的方法提供访问 单例模式之饿汉式: (一进来就造对 ...

  8. [转]JAVA设计模式之单例模式

    原文地址:http://blog.csdn.net/jason0539/article/details/23297037 概念: java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主 ...

  9. 设计模式 -- 单例模式(Java&&PHP)

    所谓单例模式,简单来说,就是在整个应用中保证只有一个类的实例存在.就像是Java Web中的application,也就是提供了一个全局变量,用处相当广泛,比如保存全局数据,实现全局性的操作等. 能够 ...

随机推荐

  1. 判断URL文件是不是在于在。

    判断URL文件是不是在于在. private static bool UrlIsExist(string url) { System.Uri u = null; try { u = new Uri(u ...

  2. java中常用的16个工具类

    1. org.apache.commons.io.IOUtils:处理io流的相关操作 closeQuietly ( ) toString ( ) copy ( ) toByteArray ( ) w ...

  3. iOS隐藏状态栏

    1.整个项目隐藏状态栏 在Targets->General->勾选中Hide status bar . 整个项目隐藏状态栏 2.单个界面隐藏状态栏,例如登录注册页面 1.首先在info.p ...

  4. 基于jQuery滑动分步式进度导航条代码

    分享一款基于jQuery滑动分步式进度导航条代码.这是一款基于jquery实现的网站注册动态步骤导航条代码.效果图如下: 在线预览   源码下载 实现的代码. html代码: <div id=& ...

  5. Android,我待你入初恋啊,你就别坑我了!

    最近做了好多东西,东忙忙,西茫茫,ms最后都空欢喜一场. 1.小黄图,说是小黄图,其实只是网上爬下来的写真阿自拍阿什么的,绝对没有反党反共淫秽内容.后来的后来,admob被google停用了,不开心. ...

  6. vue-router "path" is required in a route configuration

    启用了动态路由,一直提示这个错误,页面打开也是空白,后来发现原来是component参数错误. 正确的写法为: component: () => import ('@/views/own-spa ...

  7. Mongo分区后分片下count记录不准确

    问题描述 问题如图,后来上网查了一下,发现了这是正常现象: 官方文档解释了这种现象的原因以及解决方法: 不准确的原因: 操作的是分片的集合(前提): shard分片正在做块迁移,导致有重复数据出现 存 ...

  8. vnc 登录 Ubuntu gnome 桌面出现 QXcbConnection : Failed to initialize XRandr 错误,然后打不开

    现象如下: 解决方法是在 启动的时候加入 -noload Welcome 参数 也可以在 ~/.local/share/applications/DigiaQt-qtcreator-community ...

  9. java小技巧-生成重复的字符

    今天碰到个需求,根据字段个数,动态生成sql的占位符,如下: public static void main(String[] args) { System.out.println(String.jo ...

  10. 【进阶修炼】——改善C#程序质量(1)

    这是一个大纲形式的概要,以便自己可以花较少的时间反复阅读.在开发中,多加注意这些有用的建议,让自己成为一个更优秀的程序员.内容主要来自<编写高质量代码-改善C#程序的157个建议>(陆敏技 ...