JAVA 单例模式(一)

本文介绍单例模式的应用场景和实现方式,通过一个具体的例子——配置文件读取类MyConfig,展示了如何利用单例模式减少资源消耗,提高系统效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

设想一个场景,我们的应用,需要读取配置文件的内容。然而会存在有很多应用都需要有相应的配置文件,比如说xml格式,比如说properties格式等等。假设我们创建了一个专门用来读取配置文件的一个类,名为MyConfig。
我们的客户端可以通过MyConfig提供的构造方法 new 出一个实例对象来,用这个实例操作配置文件。可是,在项目中,会有很多地方都需要使用这个MyConfig的实例对象,也就意味着我们会 new 出来很多个实例,无疑这样会造成资源的浪费,而且当配置文件内容越来越多,我们的内存中存放着很多个“同样”功能的一个类,而这个类还封装了配置文件的内容,还特别消耗资源。所以,对于MyConfig这样的类,我们在运行期间只要一个实例对象就足够。

这个时候就需要单例模式了,从字面上来看,“单例”就是一个实例。单例模式是一中对象创建模式,它用于产生一个对象的具体实例,并且可以确保整个应用程序的生命周期中一个类只产生这么一个实例。
这样可以带来两大好处:
1、对于频繁使用的对象,可以省略创建对象所花费的时间;
2、降低系统内存的使用频率,节省资源,并且也可以减轻GC(垃圾回收机制)的压力。

* 编写Singleton类 *

package signal.Singleton;

public class Singleton {
    //定义一个私有静态全局变量来保存该类的唯一实例
    private static Singleton singleton;

    /**
     * 构造方法必须是私有的,这样在外部便无法使用new来创建该类的实例
     */
    private Singleton(){

    }

    /**
     * 定义一个全局访问点,即通过该方法可以获取一个Singleton的实例对象
     * 设置为静态方法,则在类的外部便不需要实例化就可以调用该方法
     * @return  Singleton实例对象
     */
    public static Singleton getSingletonInstance(){
        /**
         * 为了保证只实例化一次,先判断该对象是否为 null
         * 当然第一次调用时会实例化出一个singleton对象,但是以后的调用便不会再实例化
         */
        if(singleton == null){
            singleton = new Singleton();
        }
        return singleton;
    }
}

对于单例模式,需要有一个私有的构造方法,这样在外部便无法new出该类的实例,同时要有一个共有的实例化方法,用于在类的外部在没有实例化的时候可以调用该方法。

这里就牵扯到两个比较基础的概念,对于public、private…等修饰符的认识,还有关于static关键字的认识。
我们先说public、private…,Java中有四种访问控制权限,即“public/protected/default/private”。通过以下这张图来描述他们的区别就非常明显了,具体什么时候用什么修饰符,要看具体需求,一般情况下是属性用private,方法用public,但是这只是一般情况。而我们的单例模式不属于这个一般情况^&^
这里写图片描述
前面也已经说过了,单例模式就希望在整个应用的生命周期中只创建一个实例,要是在外部能够随意访问,随意创建的话就不是单例模式了,所以我们使用private来修饰我们的构造方法。

接下来就是static关键字,它翻译过来是
这里写图片描述
在Java中,static表示“全局”、“静态”的意思。因为我们这篇的主角是单例模式,这里就不过多介绍了,稍后我会写一篇关于这个关键字的文章,举几个例子帮助理解。总之这会儿就记住,如果需要描述共享信息时使用static关键字,一是方便修改,再就是不会重复开辟内存空间。

好了,回到主题,我们的单例写好了,当然得测试一下吧^&^

package signal.Singleton;

public class TestSingleton {
    public static void main(String[] args) {
        Singleton singleton1 = Singleton.getSingletonInstance();
        Singleton singleton2 = Singleton.getSingletonInstance();

        if(singleton1.equals(singleton2)){
            System.out.println("singleton1 和 singleton2 是同一个实例");
        }else{
            System.out.println("singleton1 和 singleton2 不是同一个实例");
        }
    }
}

测试程序运行结果如下:
这里写图片描述
从这里我们可以看出来,虽然调用了两次 getSingletonInstance() 方法,但是这个实例对象是同一个。由于构造方法是用private修饰的,快返回去看那张图,是不是一目了然,我们无法在这个类的外部通过 new 的方式来创建一个Singleton类的实例,我们只能通过Singleton类中定义的静态方法来访问。
这个 getSingletonInstance() 方法第一步是先判断实例对象 singleton 是否为空,为空则可以创建一个实例,但是如果不是空,就将这个实例返回给调用处。所以我们的 singleton1 和 singleton2 是同一个实例。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值