享元设计模式

享元设计模式通过共享技术减少大量细粒度对象的创建,提高系统性能。例如在Android的Message.obtain方法中,利用单链表实现对象池,通过获取和回收Message对象来实现复用,避免频繁创建和销毁导致的内存开销。这种模式虽然增加了系统复杂度,但能有效降低内存消耗,提高运行效率。
摘要由CSDN通过智能技术生成

模式定义

运用共享技术有效的支持大量细粒度的对象

使用场景

  1. 系统中有大量对象, 这些对象消耗大量内存
  2. 对象的状态大部分可以外部化。
  3. 对象可以按照内蕴状态分为很多组,当把外蕴对象从对象中剔除出来时,每一组对象都可以用一个对象来代替
  4. 系统不依赖于这些对象身份,这些对象是不可分辨的

例子

  1. Message.obtain
    private static int sPoolSize = 0;
    Message next;
    private static final Object sPoolSync = new Object();
    private static Message sPool;

public static Message obtain() {
        synchronized (sPoolSync) {
            if (sPool != null) {
                Message m = sPool;
                sPool = m.next;
                m.next = null;
                m.flags = 0; // clear in-use flag
                sPoolSize--;
                return m;
            }
        }
        return new Message();
    }

我们可以看到message要么是从最后new Message返回一个新的对象,要么返回sPool。当返回sPool时就是返回已创建的重复对象。再理解为啥sPool就是重复对象时,我们先看明白Message这个单链表对象

  1. Message包含一个next的Message对象。sPoolSize表示个数,以此形成单链表结构

单链表的取出
在obtain方法中
Message m = sPool —m等于单链表
sPool = m.next —sPool单链表舍弃表头元素
m.next = null; —m舍弃除表头之外的所有元素
m.flags = 0; —flag置0标记
sPoolSize–; —单链表大小减1
这样就取出来了单链表的头元素并返回,而我们的单链表sPool舍弃表头。这样就完成了元素的复用。当然这里只是取出,接下来我们看插入

单链表的插入
插入的操作是在Message回收的时候

public void recycle() {
        if (isInUse()) {
            if (gCheckRecycle) {
                throw new IllegalStateException("This message cannot be recycled because it "
                        + "is still in use.");
            }
            return;
        }
        recycleUnchecked();
    }

void recycleUnchecked() {
        // Mark the message as in use while it remains in the recycled object pool.
        // Clear out all other details.
        flags = FLAG_IN_USE;
        what = 0;
        arg1 = 0;
        arg2 = 0;
        obj = null;
        replyTo = null;
        sendingUid = -1;
        when = 0;
        target = null;
        callback = null;
        data = null;

        synchronized (sPoolSync) {
            if (sPoolSize < MAX_POOL_SIZE) {
                next = sPool;
                sPool = this;
                sPoolSize++;
            }
        }
    }

recycle判断Message对象是否正在被使用,如果是则刨除异常,否则开始进行recycleUnchecked单链表插入操作。插入之前先清空了各个参数。

synchronized (sPoolSync) {
            if (sPoolSize < MAX_POOL_SIZE) {
                next = sPool;
                sPool = this;
                sPoolSize++;
            }
        }

总结

优点:
大大减少对象的创建,降低系统的内存,使效率提高

缺点:
提高了系统的复杂度,需要分离出外部状态和内部状态,而且外部状态具有固有化的性质,不应该随着内部状态的变化而变化,否则会造成系统的混乱

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值