戏说设计模式——单例模式

 前言

        想一想,如果公司里面有一个大牛,一个人就能把所有的事情都干了,那该多好!作为一个不喜欢卷来卷去的中国时代打工人,我喜欢这样的同事。作为吹着**春风成长起来的企业家,同样喜欢这样的员工(可以少聘用几个打工人了!!!可以裁掉几个打工人了!!!),可以省下不少成本!!!

         如你所愿,单例模式就是这么一个时代楷模,虽然不能包揽所有工作,但是分内之事,一人足矣!接下来,来看一个简单的实例吧。

实例一:

package com.elean.design.singleton;

/**
 * @auther Elean
 * @date 17/7/2024 下午4:23
 * @description
 */
public class SuperMan {
    public static SuperMan tom = new SuperMan();
    
    //拒绝招聘
    private SuperMan() {
    }

    //有事找Tom
    public static final SuperMan getInstance() {
        return tom;
    }

    public void serveTea() {
        System.out.println("端茶,我来");
    }

    public void pourWater() {
        System.out.println("倒水,我来");
    }
}

        在这个案例里面,我们可以看到单例的几个最基本特点:

                1)构造函数私有(拒绝招聘新人,Tom is super man)

                2)有一个类变量来承载单一实例

                3)给一个静态方法获取实例

        当然,如果老板突然有一天喜欢上骑马、烧柴,就需要老实肯干的Tom另外学习喂马、劈柴的技能,如果没涨工资,这就对Tom是很不公平了(也违背了开闭原则:对扩展开放,对修改关闭)。这时候,就需要老板再开放一个岗位主管所有部门的马和柴,为了进一步节约成本,老板决定,招柴买马那天再设此岗位。

实例二:

package com.elean.design.singleton;

/**
 * @auther Elean
 * @date 17/7/2024 下午4:23
 * @description
 */
public class BatMan {
    public static BatMan xiaoMing;

    private BatMan() {
    }

    public static final BatMan getInstance() {
        if (null == xiaoMing) {
            xiaoMing = new BatMan();
        }
        return xiaoMing;
    }

    public void horseFeed() {
        System.out.println("喂马,我去");
    }

    public void choppingFirewood() {
        System.out.println("劈柴,我去");
    }
}

一、单线程下的使用及存在的问题

1.1 饿汉模式和懒汉模式

        以上两个示例是单例模式中两种比较简单的写法:饿汉模式和懒汉模式

        对比两种写法来看,饿汉模式在类的初始化过程会自动调用它的实例化方法给Tom赋值,而后一直存在于内存中;懒汉模式则是在调用该类的instance()方法时才会进行实例化。从表面上看,懒汉模式对资源的占用相对更小一些。但是我们知道,用户自定义类只有在被使用,或者子类被加载的时候才会被加载,如果我们能够做到让类的加载时间跟使用实例的时间一致,那么这种消耗是可以避免的,这就要求我们熟练掌握jvm的类加载机制,小心使用饿汉模式了。

1.2 反射破坏单例

        在单线程中,一般情况下上面两个简单示例是完全可以保证内存中单例了。当然,如果我们使用反射把构造函数设置成true同样可以在内存中创建实例,这种情况,可以在构造函数中像懒汉模式一样先判断内存中是否有实例存在,如下代码。

package com.elean.design.singleton;

import java.lang.reflect.Constructor;

/**
 * @auther Elean
 * @date 18/7/2024 下午8:40
 * @description
 */
public class SingleReflect {
    public static void main(String[] args) {
        SuperMan instance = SuperMan.getInstance();
        try {
            Class<?> clazz = Class.forN
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值