Java设计模式-创建者模式-单例模式-饿汉式

岳庆锦

发布于 2022.03.12 20:29 阅读 1561 评论 0

创建者模式

 主要关注点:怎样创建对象?

 主要特点:将对象的创建与使用分离。

 好处:降低系统的耦合度,使用者不需关注对象的创建细节,对象的创建由相关的工厂来完成。

 就像我们买东西,不需要知道商品是怎么生产的,因为它们有专门的厂商生产。

 分类1.单例模式 2.工厂方法模式 3.抽象工厂模式 4.原型模式 5.建造者模式

单例模式(Singleton Pattern)

 定义 指一个类只有一个实例对象),且该类能自行创建这个实例(对象的创建在此类中就完成了,而且创建的是自己的对象)的一种模式 。

 单例模式提供了一种创建对象的最佳方式,单例模式可以理解为单个对象的设计模式。

 特点

①单例类只有一个实例对象。(自己的对象)

②该单例对象必须由单例类自行创建。(对象的创建在类内部就已完成)

③单例类对外提供一个访问该单例的全局访问点。(在单例类中,提供了一种访问其唯一对象的方法,外界不可以实例化该对象,仅能通过此方法(全局访问点)获取到该类的对象)

 结构

①单例类:只能创建一个实例(对象)的类。

②访问类:其实就是测试类,使用单例类的。

 实现方式

单例设计模式分为两类:

饿汉式:类加载就会导致该单实例对象被创建。

懒汉式:类加载的时候该类的对象并不会被创建,而是在首次使用该对象的时候(外界调用获取该单实例对象的getInstance()方法时)被创建。

 区分懒汉式和饿汉式的方法:看对象是否是在类加载的时候被创建的。如果是,就是饿汉式;如果不是,就是懒汉式。

 下面来介绍饿汉式的三种实现方式(静态成员变量方式静态代码块方式枚举方式

 

 1.饿汉式-方式1(静态成员变量方式)

1.单例类(Singleton)

public class Singleton {

    //1,私有构造方法(让外界访问不到)
    private Singleton(){}

    //2,在本类中创建本类对象(方法返回值类型是静态的,静态的不能访问非静态的,所以这个对象也用static修饰)
    private static Singleton instance = new Singleton();

    //3,对象虽然创建了但是用private修饰,所以需要提供一个公共的访问方式,让外界获取该对象
    //用static修饰方法是因为外界不能创建此类对象,不能创建就不能访问非静态的方法,所以定义的是静态的方法
    public static Singleton getInstance(){
        return instance;
    }

}

2.测试类(Client)

public class Client {
    public static void main(String[] args) {
        //创建singleton对象,通过类名获取
        Singleton instance = Singleton.getInstance();

        //判断获取到的两个对象是否是同一个对象(在内存中是否是同一个地址)
        Singleton instance1 = Singleton.getInstance();

        System.out.println(instance == instance1);//true
    }
}

3.运行结果(运行结果是true,说明两次创建的是同一个对象,实现了单例)

 

 2.饿汉式-方式2(静态代码块方式)

1.单例类(Singleton)

public class Singleton {

    //私有构造方法
    private Singleton(){};

    //声明Singleton类型的变量(只是声明,没有进行赋值,不是创建!)
    private static Singleton instance;//null

    //在静态代码块中进行赋值
    static {
        instance = new Singleton();
    }

    //对外提供获取该类对象的方法
    public static Singleton getInstance(){
        return instance;
    }
}

2.测试类(Client)

public class Client {
    public static void main(String[] args) {
        Singleton instance = Singleton.getInstance();

        Singleton instance1 = Singleton.getInstance();

        //判断是否为同一对象
        System.out.println(instance == instance1);
    }
}

3.运行结果(结果为true,说明实现了单例)

 方式1和方式2唯一的区别是:方式1是在声明该类的成员变量的同时进行赋值;方式2是先声明了该类的成员变量,然后在代码块里面进行赋值。

 

 3.饿汉式-方式3(枚举方式)

1.单例类(Singleton,枚举类型)

public enum Singleton {
    INSTANCE;
}

2.测试类(Client)

public class Client {
    public static void main(String[] args) {

        Singleton instance = Singleton.INSTANCE;

        Singleton instance1 = Singleton.INSTANCE;

        //判断获取的对象是否是同一个
        System.out.println(instance == instance1);//true
    }
}

3.运行结果(运行结果为true,说明实现了单例)

 枚举方式的优点:线程安全,只会加载一次,是所有单例实现中唯一一种不会被破坏的单例实现模式。

 枚举方式的缺点:会造成内存空间的浪费。

 单例模式-饿汉式的缺点:(会造成内存空间的浪费)

  饿汉式缺点解释:饿汉式都是在类加载时创建了对象,但如果只是进行了类加载,并没有获取该类的对象,此时对象也已经存在了内存中。如果该对象足够大的话,一直没有使用就会造成内存的浪费。

  不考虑内存空间浪费的话,首选枚举方式。