设计模式分为三种类型,共23种
所谓类的单例设计模式,就是采取一定的方法保证在整个系统中,对某个类 只能存在一个对象实例,并且该类值提供一个取得对象实例的方法(静态方法)
package 单例模式.饿汉式;
/**
* @author Han
* @data 2023/10/27
* @apiNode
*/
public class Test1 {
public static void main(String[] args) {
Obj obj1 = Obj.getObj();
Obj obj2 = Obj.getObj();
// 因为是单例模式所以这两个对象是同一个,所以返回true
System.out.println(obj1 == obj2);
}
}
class Obj {
// 创建一个私有的静态对象
private final static Obj obj = new Obj();
// 将构造方法私有化
private Obj() {
}
// 提供静态公共方法将这个对象返回
public static Obj getObj() {
return obj;
}
}
package 单例模式.饿汉式;
/**
* 静态代码块方式
*
* @author Han
* @data 2023/10/27
* @apiNode
*/
public class Test2 {
public static void main(String[] args) {
Obj2 obj21 = Obj2.getObj();
Obj2 obj22 = Obj2.getObj();
// 因为是单例模式所以这两个对象是同一个,所以返回true
System.out.println(obj21 == obj22);
}
}
class Obj2 {
// 声明一个私有的静态对象
private static Obj2 obj2;
static {
// 在静态代码块中创建对象
obj2 = new Obj2();
}
// 将构造方法私有化
private Obj2() {
}
// 提供静态公共方法将这个对象返回
public static Obj2 getObj() {
return obj2;
}
}
优缺点说明:
package 单例模式.懒汉式;
/**
* 这种方式是线程不安全的
* 原因在于在多线程状态下,if判断条件,
* 可以能会出现第一个对象还未创建,第二个线程就去判断
* 而发生创建多个对象的情况
* @author Han
* @data 2023/10/27
* @apiNode
*/
public class Test1 {
public static void main(String[] args) {
Obj obj1 = Obj.getObj();
Obj obj2 = Obj.getObj();
System.out.println(obj1 == obj2);
}
}
class Obj {
// 声明一个静态对象
private static Obj obj;
// 私有化构造函数
private Obj() {}
// 提供获取单例对象的方法
public static Obj getObj(){
// 如果还没有创建对象再去创建,不会发生内存的浪费
if (obj == null) {
obj = new Obj();
}
return obj;
}
}
优缺点说明
if(obi == null)判断语句块,还未来的及王往下执行,另一个线程也通过这个判断语句,这是会发生创建多个实例的错误,所以在多线程环境下不能使用优化,加同步方法,解决线程不安全问题 存在效率问题,
package 单例模式.懒汉式;
/**
* 这种方式虽然解决了线程安全问题
* 但是效率很低
* @author Han
* @data 2023/10/27
* @apiNode
*/
public class Test2 {
public static void main(String[] args) {
Obj2 obj1 = Obj2.getObj();
Obj2 obj2 = Obj2.getObj();
System.out.println(obj1 == obj2);
}
}
class Obj2 {
// 声明一个静态对象
private static Obj2 obj;
// 私有化构造函数
private Obj2() {}
// 提供获取单例对象的方法
// 加入了同步处理的代码,解决线程安全问题
public static synchronized Obj2 getObj(){
// 如果还没有创建对象再去创建,不会发生内存的浪费
if (obj == null) {
obj = new Obj2();
}
return obj;
}
}
优缺点说明
package 单例模式.双重检查;
import com.sun.org.apache.xpath.internal.operations.Variable;
/**
* 双重检查
* 解决线程安全问题,并且支持懒加载
*
* @author Han
* @data 2023/10/27
* @apiNode
*/
public class Test1 {
public static void main(String[] args) {
Obj obj1 = Obj.getObj();
Obj obj2 = Obj.getObj();
System.out.println(obj1 == obj2);
}
}
class Obj {
// 声明一个静态对象
// 并且使Obj的对象的改变立即更新到内存,在下面的双重检查中判断是否为nul
private static volatile Obj obj;
// 私有化构造函数
private Obj() {
}
// 提供获取单例对象的方法
public static Obj getObj() {
// 如果还没有创建对象再去创建,不会发生内存的浪费
if (obj == null) {
// 同步代码块
synchronized (Obj.class) {
// 再一次检查是否为null
if (obj == null) {
obj = new Obj();
}
}
}
return obj;
}
}
优缺点说明
if (obj == null )的检查,这样就可以保证线程安全package 单例模式.静态内部类;
import com.sun.org.apache.xpath.internal.operations.Variable;
/**
* 静态内部类
*
* @author Han
* @data 2023/10/27
* @apiNode
*/
public class Test1 {
public static void main(String[] args) {
Obj obj1 = Obj.getObj();
Obj obj2 = Obj.getObj();
System.out.println(obj1 == obj2);
}
}
class Obj {
// 私有化构造函数
private Obj() {
}
// 使用静态内部类
public static Obj getObj() {
// 使用静态内部类中属性
// 类加载时是线程安全的
return StaticObj.OBJ;
}
// 静态内部类在类加载时不会马上加载,解决懒加载
// 只有使用到静态内部类中的属性时,静态内部类才会加载
static class StaticObj {
private static final Obj OBJ = new Obj();
}
}
说明
package 单例模式.枚举方式;
enum Type {
INSTANCE,
USER("小韩", 12, "学生");
String name;
String job;
int i;
Type(String name, int i, String job) {
this.i = i;
this.job = job;
this.name = name;
}
Type() {
}
public void sayOk() {
System.out.println("ok");
}
@Override
public String toString() {
return "Type{" +
"name='" + name + '\'' +
", job='" + job + '\'' +
", i=" + i +
'}';
}
}
/**
* @author Han
* @data 2023/10/28
* @apiNode
*/
public class Test {
public static void main(String[] args) {
Type instance = Type.INSTANCE;
Type instance2 = Type.INSTANCE;
Type user1 = Type.USER;
Type user2 = Type.USER;
System.out.println(Type.INSTANCE);
System.out.println(Type.USER);
System.out.println(instance == instance2); // true
System.out.println(user2 == user1); // true
}
}
优点说明
