你需要了解的创建型设计模式之单例模式

介绍

单例的对象必须保证只有一个实例存在,不能自由构造对象

定义

某一个类只能有一个实例,并自行实例化且向整个系统提供这个实例

使用场景

  • 产生多个对象导致资源浪费
  • 创建一个对象消耗资源过多如访问IO、数据库
  • 某种类型的对象只能有一个,如一个仓库

UML类图

UML类图

实现单例的关键

  1. 构造函数私有化不对外开放
  2. 通过静态方法或者枚举返回单例对象
  3. 确保单例对象只有一个,尤其是在多线程环境下
  4. 确保单例对象在反序列化时不会重新构建对象

问题案例

这个案例展示的是为什么要使用单例模式,或者说,我们不使用单例会有什么危害

仓库

/**
 * 仓库类
 */
public class StoreHouse {

    //仓库商品数量
    private int quantity=100;

    //货物进出
    public void setQuantity(int quantity) {
        this.quantity = quantity;
    }

    //货物数量
    public int getQuantity() {
        return quantity;
    }

}

搬货工人

/**
 * 搬货工人类
 */
public class Carrier {
        //public可以让测试的时候选择到对象
        public StoreHouse mStoreHouse;

        public Carrier(StoreHouse storeHouse){
            this.mStoreHouse = storeHouse;
        }
        //搬货进仓库
        public void MoveIn(int i){
            mStoreHouse.setQuantity(mStoreHouse.getQuantity()+i);
        }
        //搬货出仓库
        public void MoveOut(int i){
            mStoreHouse.setQuantity(mStoreHouse.getQuantity()-i);
        }
}

测试一下

public class test {

    public static void main(String[] args){
        StoreHouse mStoreHouse1 = new StoreHouse();
        StoreHouse mStoreHouse2 = new StoreHouse();
        Carrier Carrier1 = new Carrier(mStoreHouse1);
        Carrier Carrier2 = new Carrier(mStoreHouse2);

        System.out.println("两个是不是同一个?");

        //这里用equals而不是用 == 符号,因为 == 符号只是比较两个对象的地址
        if(mStoreHouse1.equals(mStoreHouse2)){
            System.out.println("是同一个");
        }else {
            System.out.println("不是同一个");
        }
        
        //搬运工搬完货物之后出来汇报仓库商品数量
        Carrier1.MoveIn(30);
        System.out.println("仓库商品余量:"+Carrier1.mStoreHouse.getQuantity());
        Carrier2.MoveOut(50);
        System.out.println("仓库商品余量:"+Carrier2.mStoreHouse.getQuantity());
    }

}

测试结果

两个是不是同一个?
不是同一个
仓库商品余量:130
仓库商品余量:50

如何更改(使用静态内部类方式实现单例)

按照实现步骤完成

仓库类

/**
 * 仓库类
 */
public class StoreHouse {

    //仓库商品数量
    private int quantity=100;

    private StoreHouse() {
    }

    private static class StoreHouseHolder{
        private static final StoreHouse storeHouse=new StoreHouse();
    }

    public static StoreHouse newInstance(){
        return StoreHouseHolder.storeHouse;
    }

    //货物进出
    public void setQuantity(int quantity) {
        this.quantity = quantity;
    }

    //货物数量
    public int getQuantity() {
        return quantity;
    }

}

搬运工人不需要改

测试一下

public class test {

    public static void main(String[] args) {
        StoreHouse mStoreHouse1 = StoreHouse.newInstance();
        StoreHouse mStoreHouse2 = StoreHouse.newInstance();
        Carrier Carrier1 = new Carrier(mStoreHouse1);
        Carrier Carrier2 = new Carrier(mStoreHouse2);

        System.out.println("两个是不是同一个?");

        //这里用equals而不是用 == 符号,因为 == 符号只是比较两个对象的地址
        if (mStoreHouse1.equals(mStoreHouse2)) {
            System.out.println("是同一个");
        } else {
            System.out.println("不是同一个");
        }

        //搬运工搬完货物之后出来汇报仓库商品数量
        Carrier1.MoveIn(30);
        System.out.println("仓库商品余量:" + Carrier1.mStoreHouse.getQuantity());
        Carrier2.MoveOut(50);
        System.out.println("仓库商品余量:" + Carrier2.mStoreHouse.getQuantity());
    }

}

测试结果

两个是不是同一个?
是同一个
仓库商品余量:70
仓库商品余量:20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值