Back

Java单例模式

单例设计模式

什么是设计模式

  • 静态方法和属性的经典实用
  • 设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式。设计模式就像是经典的棋谱,不同的棋局,我们用不同的棋谱,免去我们自己再思考和摸索

什么是单例模式

  • 单例:就是单个的实例

  • 所谓的类的单例设计模式,就是采用一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法

  • 单例模式有两种方式:

    • 饿汉式(只有类被加载了,该对象就会被创建)

      1. 将构造器私有化
      2. 在类的内部之间创建(该对象是static)
      3. 提供一个公共的static方法,返回对象

      例如,我们规定一个人必须专一,只能有一个女朋友!

      package com.singleton;
      
      public class SingleTon {
          public static void main(String[] args) {
              GirlFriend instance = GirlFriend.getInstance();
              System.out.println(instance);
              //无论你怎么创建,该对象都是同一个
              GirlFriend instance1 = GirlFriend.getInstance();
              System.out.println(instance1);
              //返回结果为True
              System.out.println(instance==instance1);
          }
      }
      class GirlFriend{
          private String name ;
          //在类内部创建了对象,加static是为了可以在静态方法中返回girlFriend对象
          private static GirlFriend girlFriend = new GirlFriend("小红");
          //构造器私有化
          private GirlFriend(String name){
              this.name = name;
          }
          public static GirlFriend getInstance(){
              return girlFriend;
          }
      
          @Override
          public String toString() {
              return "GirlFriend{" +
                      "name='" + name + '\'' +
                      '}';
          }
      }
      
      

      image1

      由于类被加载之后,对象无论如何都会被创建,会造成资源的浪费。

      package com.singleton;
      
      public class SingleTon {
          public static void main(String[] args) {
              System.out.println(GirlFriend.n);
          }
      }
      class GirlFriend{
          private String name ;
          public static int n = 100;
          //对象,通常是重量级的对象,饿汉模式可能造成创建了对象,但没有使用
          private static GirlFriend girlFriend = new GirlFriend("小红");
          //构造器私有化
          private GirlFriend(String name){
              System.out.println("构造器被调用了");
              this.name = name;
          }
          public static GirlFriend getInstance(){
              return girlFriend;
          }
      
          @Override
          public String toString() {
              return "GirlFriend{" +
                      "name='" + name + '\'' +
                      '}';
          }
      }
      
      

      image2

      使用懒汉式可以很好的解决这个问题

    • 懒汉式(不调用就不会创建对象)

      1. 将构造器私有化
      2. 定义一个static静态属性对象
      3. 提供一个public的static方法,可以返回一个对象

      懒汉式:只有当用户使用getInstance时才会返回一个对象。后面再调用时,会返回上次创建的对象

      package com.singleton;
      
      public class SingleTon01 {
          public static void main(String[] args) {
              System.out.println(Cat.n);
              System.out.println("================");
              Cat cat = Cat.getInstance();
              System.out.println(cat);
          }
      }
      class Cat{
          private String name;
          public static int n = 100;
          private static Cat cat;
          private Cat(String name){
              System.out.println("构造器被调用");
              this.name = name;
          }
          public static Cat getInstance(){
              //判断有没有创建Cat对象
              if(cat == null){
                  cat = new Cat("miao");
              }
              return cat;
          }
      
          @Override
          public String toString() {
              return "Cat{" +
                      "name='" + name + '\'' +
                      '}';
          }
      }
      

      image3

  • 饿汉式VS懒汉式

    • 二者最主要的区别在于创建对象的时机不同:饿汉式是在类加载就创建了对象实例而懒汉式是在使用时才创建
    • 饿汉式不存在线程安全问题,懒汉式存在线程安全问题
    • 饿汉式存在浪费资源的可能。因为如果程序员一个对象实例都没有使用,那么饿汉式创建的对象就浪费了,懒汉式是使用时才创建,就不存在这个问题。
    • 在我们的JavaSE标准类中,java.lang.Runtime就是经典的单例模式
Built with Hugo
Theme Stack designed by Jimmy