你的位置:首页 > Java教程

[Java教程]Java设计模式——单例模式


很多人都疑惑,单例模式是什么?为什么要用单例模式?在这里,笔者记录的仅仅只是自己对于知识点的理解,如果有错误的,请下方评论指教,共同进步,谢谢。

单例模式是什么?

简单理解: 单例就是一个实例被多个用户共享,好比宿舍共用同一个垃圾桶,这个垃圾桶就是单个实例,现实生活中不可能每个人都配一个垃圾桶什么的,那样太浪费资源了吧。

官方理解:对象的创建模式,确保某一个类只有一个实例,并且能够自动实例化且向整个应用程序提供这个实例。

单例模式的特点:

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

2、单例类必须自己创建自己的实例(无法从外部创建,创建的时候将构造函数设置为私有的)

3、单例类必须向所有对象提供自己的实例

单例模式的优点:

1、在内存中只有一个对象,节省内存空间

2、避免频繁的创建销毁对象,提高性能

3、避免对共享资源的占用,可以全局访问

单例模式的类型:

1、饿汉单例(自动创建实例)

2、懒汉单例(调用的时候才创建实例)

3、登记式单例(这个我还没理解)

一、饿汉单例

//饿汉式单例,在类初始化的时候,已经自己实例化了public class mvc {
private static mvc instance = new mvc(); private mvc() { } public static mvc getInstance(){ return instance; }}

饿汉在类创建的同时就已经创建好一个静态的对象供使用了,线程是安全的

二、懒汉单例

//懒汉单例,在第一次调用的时候实例化自己public class mvc1 {  private static mvc1 instance = null;  private String name;  private mvc1(){}  //静态工厂方法  synchronized public static mvc1 getInstance(){    if(instance==null){      instance = new mvc1();    }    return instance;  }  public String getName() {    return name;  }  public void setName(String name) {    this.name = name;  }  public void printinfo(){    System.out.println("this name is "+name);  }}


测试代码
//定义测试类public class testmvc1 {  public static void main(String[] args) {    mvc1 m2 = mvc1.getInstance();    m2.setName("0539");    mvc1 m1 = mvc1.getInstance();    m1.setName("json");    m1.printinfo();    m2.printinfo();    System.out.println(m1==m2?"创建的是同一个实例":"创建的不是同一个实例");  }}

结果

this name is jsonthis name is json创建的是同一个实例


测试结果说明:实例化,结果往往是最后一个的实例。也就是说,单例模式,不管是饿汉还是懒汉,创建的都是同一个实例。
mvc1通过构造方法private将自己限制为内部使用的,避免外部被实例化,同时,在外部的话只能通过getInstance()方法去调用;
懒汉单例下是没有考虑线程安全问题的,所以要用synchronized加同步

饿汉和懒汉的区别:
1、饿汉自动实例化,懒汉要调用它才实例化
2、饿汉不用考虑线程安全问题,懒汉需要考虑线程安全问题

什么是线程安全?

如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。

或者说:一个类或者程序所提供的接口对于线程来说是原子操作,或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题,那就是线程安全的。

 

总结:

1、单例模式的作用是用来创建单个实例,并且这个实例这整个应用程序共享

2、单例模式的类型有三种:饿汉单例,懒汉单例,登记式单例

    其中饿汉自动创建实例,并保证线程安全;懒汉被动创建实例,不能保证线程安全的问题。

3、单例模式的优点:但同一个对象被多次实例,会占用大量资源,减少性能;通过采用单例,那么每次都是调用同一个实例,会提高性能。好比喝水,不可能每次都用一次性杯子。