单例模式与反射模式

一.单例模式

        单例模式是一种常见的设计模式,用于确保一个类只有一个实例,并提供全局访问点来获取该实例。在单例模式中,通过限制类的实例化过程,可以防止多个实例的创建,从而保证所有代码都使用同一个实例。

注意

  • 1、单例类只能有一个实例。
  • 2、单例类必须自己创建自己的唯一实例。
  • 3、单例类必须给所有其他对象提供这一实例。

单例模式的几种实现方式

1、懒汉式,线程不安全

        这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。因为没有加锁 synchronized,所以严格意义上它并不算单例模式。

//懒汉式,线程不安全
public class Singleton_Demo01 {
    private static Singleton_Demo01 instance;

    // 私有化构造方法,防止外部创建实例
    private Singleton_Demo01() {
    }

    // 私有化构造方法,防止外部创建实例
    public static Singleton_Demo01 getInstance() {
        if (instance == null) {
            instance = new Singleton_Demo01();
        }
        return instance;
    }
}

2、懒汉式,线程安全

        这种方式具备很好的 lazy loading,能够在多线程中很好的工作,但是,效率很低,99% 情况下不需要同步。
优点:第一次调用才初始化,避免内存浪费。
缺点:必须加锁 synchronized 才能保证单例,但加锁会影响效率。        

//懒汉式,线程安全
public class Singleton_Demo02 {
    private static Singleton_Demo02 instance;

    // 私有化构造方法,防止外部创建实例
    private Singleton_Demo02() {}

    // 只有在首次调用时才创建实例
    public static synchronized Singleton_Demo02 getInstance() {
        if (instance == null) {
            instance = new Singleton_Demo02(); 
        }
        return instance;
    }
}

3、饿汉式(Eager initialization)

这种方式比较常用,但容易产生垃圾对象。
优点:没有加锁,执行效率会提高。
缺点:类加载时就初始化,浪费内存。

//饿汉式(Eager initialization)
public class Singleton_Demo03 {
    // 在类加载时就创建实例
    private static Singleton_Demo03 instance = new Singleton_Demo03();

    // 私有化构造方法,防止外部创建实例
    private Singleton_Demo03() {}

    // 提供公共的访问方法
    public static Singleton_Demo03 getInstance() {
         return instance;
    }
}

4、双重检查锁定(Double-checked locking)

这种方式采用双锁机制,安全且在多线程情况下能保持高性能。

//双重检查锁定(Double-checked locking)
public class Singleton_Demo04 {
    private volatile static Singleton_Demo04 instance;

    // 私有化构造方法,防止外部创建实例
    private Singleton_Demo04() {
    }

    public static Singleton_Demo04 getInstance() {
        if (instance == null) {
            synchronized (Singleton_Demo04.class) {
                if (instance == null) {
                    instance = new Singleton_Demo04();
                }
            }
        }
        return instance;
    }
}

5、静态内部类(Static inner class)

        这种方式能达到双检锁方式一样的功效,但实现更简单。对静态域使用延迟初始化,应使用这种方式而不是双检锁方式。这种方式只适用于静态域的情况,双检锁方式可在实例域需要延迟初始化时使用。

//静态内部类(Static inner class)
public class Singleton_Demo05 {
    private static class SingletonHolder {
        private static final Singleton_Demo05 INSTANCE = new Singleton_Demo05();
    }

    // 私有化构造方法,防止外部创建实例
    private Singleton_Demo05() {
    }

    public static Singleton_Demo05 getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

        以上是几种常见的单例模式的实现方式,每种方式都有其适用的场景和特点。在选择使用哪种实现方式时,需要根据具体需求和线程安全性要求进行选择

二.反射模式

        反射模式是一种软件设计模式,它允许程序在运行时动态地调查、获取和使用类或对象的信息。它提供了一种机制来检查和操作代码中的类型、属性、方法等元素,而无需显式编写这些元素的名称。

反射模式实现方法

1.首先要有一个类(用来验证反射)

package com.cskt.pojo;

import lombok.Data;

@Data
public class User_SupCc {
    //私有属性字段
    private Integer id;
    private String name;

    //公有属性字段
    public String password;
    public String address;

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", password='" + password + '\'' +
                ", address='" + address + '\'' +
                '}';
    }

    //私有方法 无参
    private void PrivatelyShowWu(){
        System.out.println("私有方法-无参!");
    }
    //私有方法 有参
    private void PrivatelyShowYou(String name){
        System.out.println("私有方法-有参! "+name);
    }

    //公共方法 无参
    public void commonalityShowWu(){
        System.out.println("公共方法-无参!");
    }
    //公共方法 有参
    public void commonalityShowYou(String name){
        System.out.println("公共方法-有参! "+name);
    }
}

2.我们使用反射得到类、通过得到类获取字段

   @Test //测试注解
    @SneakyThrows   //抛出异常注解
    public void TestPojoUser(){
        //放射模式 全路径 获取类
        Class c1 = Class.forName("com.cskt.pojo.User_SupCc");
        Constructor<User_SupCc> constructor = c1.getConstructor();
        User_SupCc user_supCc = constructor.newInstance();
        //公有属性调用
        user_supCc.address="赛博坦";
        user_supCc.password="123456";

        //私有属性调用
        //id
        Field id = c1.getDeclaredField("id");
        id.setAccessible(true);//设置true 才能这设置值
        id.set(user_supCc,1);
        //name
        Field name = c1.getDeclaredField("name");
        name.setAccessible(true);//设置true 才能这设置值
        name.set(user_supCc,"SupCc");

        System.out.println(user_supCc.toString());
    }

测试结果

 

3.我们使用反射得到类、通过得到类获取、公共方法、私有方法

   @Test //测试注解
    @SneakyThrows   //抛出异常注解
    public void TestUserMethod(){
        //放射模式 全路径 获取类
        Class c2 = Class.forName("com.cskt.pojo.User_SupCc");
        //公共方法获取 获取所有的public的方法
        Constructor<User_SupCc> constructor = c2.getConstructor();
        User_SupCc user_supCc = constructor.newInstance();
        //公共无参方法
        user_supCc.commonalityShowWu();
        //公共有参方法
        user_supCc.commonalityShowYou("SupCc");

        //私有方法获取 获取指定的的private的方法
        Method privatelyShowWu = c2.getDeclaredMethod("PrivatelyShowWu");
        privatelyShowWu.setAccessible(true);//私有需要强制才能执行
        privatelyShowWu.invoke(user_supCc);//执行方法

        //私有方法调用 调用私有方法无参
        Method privatelyShowYou = c2.getDeclaredMethod("PrivatelyShowYou",String.class);
        privatelyShowYou.setAccessible(true);//私有需要强制才能执行
        privatelyShowYou.invoke(user_supCc,"SupCc");//执行方法
    }

测试结果

 

        反射模式在某些情况下非常有用,例如在框架开发、插件系统、动态代理等场景中。它使得程序可以在运行时根据需要动态地加载和使用类,从而增加了程序的灵活性和可扩展性。

        需要注意的是,由于反射模式具有较高的复杂性和性能开销,所以在普通的业务逻辑中并不需要频繁地使用反射。只有在确实需要动态处理类和对象时才应考虑使用反射模式。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值