Day40面试题:单例设计模式**

单例设计模式

  • (1)什么是单例设计模式
    单:唯一
    即某个类在整个系统中只能有一个实例对象可被获取和使用的代码模式。
    在Java中即指单例设计模式,它是软件开发中最常用的设计模式之一。
  • (2)实例
    例如:代表JVM运行环境的Runtime类
public class Runtime {
    private static Runtime currentRuntime = new Runtime();

    /**
     * Returns the runtime object associated with the current Java application.
     * Most of the methods of class <code>Runtime</code> are instance
     * methods and must be invoked with respect to the current runtime object.
     *
     * @return  the <code>Runtime</code> object associated with the current
     *          Java application.
     */
    public static Runtime getRuntime() {
        return currentRuntime;
    }

    /** Don't let anyone else instantiate this class */
    private Runtime() {}

单例设计模式

  • (1)单例的要点
    》》某个类只能有一个实例 private static
    》》它必须自行创建这个实例 private 构造方法
    》》它必须自行向整个系统提供这个实例; getXxx()
  • (2)为什么?
    构造器私有化
    含有一个该类的静态变量来保存这个唯一的实例
    对外提供获取该实例对象的方式:
    (1)直接暴露(2)用静态变量的get方法获取

//1:静态的私有的成员变量
//2:私有的构造方法
//3:公有的静态的获取方法
class MyClass {
    private static MyClass obj = new MyClass();

    private MyClass() {

    }

    public static MyClass getInstance() {
        return obj;
    }
}

public class Test03单例 {
    @Test
    public void test01() {
        /* MyClass obj1 = MyClass.getInstance();
        MyClass obj2 = MyClass.getInstance();
        System.out.println(obj1);
        System.out.println(obj2);
        System.out.println(obj1==obj2);*/

        //如果构造方法不是私有的,可以创建多个对象
        //定义:项目中,该类只能有一个对象
       /*MyClass obj3 = new MyClass();
        MyClass obj4 = new MyClass();
        System.out.println(obj3);
        System.out.println(obj4);*/
        //如果没有公有的静态的获取方法,无法使用使用该单例
        //System.out.println(MyClass.obj);
        //如果静态的成员变量改成公有的,有可能被置成null
        //MyClass.obj = null;

    }
}

几种常见形式

共两类

》在使用获取方法时,是否已经初始化了实例对象
》饿汉式:已有实例对象 ,再调用
》懒汉式:调用才创建实例对象

(1)饿汉式

直接创建对象,不存在线程安全问题(加载即创建)

直接实例化饿汉式(简洁直观)

静态变量赋值

//第一种   private static MyClass obj = new MyClass();
class MyClass {
    private static MyClass obj = new MyClass();

    private MyClass() {
        System.out.println("MyClass构造方法执行了");
    }

    public static MyClass getInstance() {
        System.out.println("getInstance方法执行了");
        return obj;
    }
}

public class Test03单例 {
    @Test
    public void test01() {
        MyClass obj1 = MyClass.getInstance();
        MyClass obj2 = MyClass.getInstance();
        System.out.println(obj1);
        System.out.println(obj2);

    }
}

枚举式(最简洁)

//第二种  使用枚举 enum,枚举内只能写一个对象名
enum MyClass {
    obj1
}

public class Test03单例 {
    @Test
    public void test01() {
        // MyClass obj1 = new MyClass();
        MyClass obj1 = MyClass.obj1;
        MyClass obj2 = MyClass.obj1;
        System.out.println(obj1);
        System.out.println(obj2);

    }
}

静态代码块饿汉式(适合复杂实例化)****

静态代码块

//第三种   可以静态代码块中初始化对象
class MyClass {
    private static MyClass obj = null;

    static {
        //可以读配置文件 读properties文件,获取数据库的四大信息
        obj = new MyClass();
    }

    private MyClass() {
        System.out.println("MyClass构造方法执行了");
    }

    public static MyClass getInstance() {
        System.out.println("getInstance方法执行了");
        return obj;
    }
}

public class Test03单例 {
    @Test
    public void test01() {
        MyClass obj1 = MyClass.getInstance();
        MyClass obj2 = MyClass.getInstance();
        System.out.println(obj1);
        System.out.println(obj2);

    }
}

(2)懒汉式

lazy 延迟创建对象(在调用时才创建)
线程不安全(适用于单线程)

线程不安全

class MyClass {
    private static MyClass obj = null;

    private MyClass() {
        System.out.println("MyClass构造方法执行了");
    }

    public static MyClass getInstance() {
        System.out.println("getInstance方法执行了");
        if (obj == null) {
            //创建对象
            obj = new MyClass();
        }
        return obj;
    }
}

public class Test03单例懒汉 {
    @Test
    public void test01() {
        MyClass obj1 = MyClass.getInstance();
        MyClass obj2 = MyClass.getInstance();
        System.out.println(obj1);
        System.out.println(obj2);

    }
}

线程安全

线程安全(适用于多线程)加同步关键字+if优化判断

//懒汉:调用get时,才在get内部初始化(催作业)
class MyClass {
    private static MyClass obj = null;

    private MyClass() {
        System.out.println("MyClass构造方法执行了");
    }

    public static MyClass getInstance() {
        System.out.println("getInstance方法执行了");
        //类在内存中只有一份,所以可以拿当锁
        //有了唯一的一把锁之后,所有的线程就必须排队
        if (obj == null) {//2:因为synchronized会让线程排队,降低效率。在进入加锁代码之,满足条件的直接return
            synchronized (MyClass.class) {
                if (obj == null) {//1:判断是否有对象 ,没有才创建
                    //创建对象
                    obj = new MyClass();
                }
            }
        }
        return obj;
    }
}

public class Test03单例懒汉 {
    @Test
    public void test01() {
        MyClass obj1 = MyClass.getInstance();
        MyClass obj2 = MyClass.getInstance();
        System.out.println(obj1);
        System.out.println(obj2);

    }
}

静态内部类形式

(适用于多线程)静态内部类的静态变量

class OutMyClass {//外部类

    public class InnerClass {//内部类

    }

    public static class MyClass {//静态内部类
        //静态变量
        private static MyClass obj = new MyClass();

    }

    public static MyClass getIntance() {
        return MyClass.obj;
    }
}

public class Test03单例懒汉 {
    @Test
    public void test01() {

        OutMyClass.MyClass obj1 = OutMyClass.getIntance();
        OutMyClass.MyClass obj2 = OutMyClass.getIntance();
        System.out.println(obj1);
        System.out.println(obj2);
    }
}

内部类:在A类中,定义B类,B则是A的内部类
静态内部类:就在B类上加static

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

翁老师的教学团队

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值