0
点赞
收藏
分享

微信扫一扫

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


举报

相关推荐

0 条评论