Java设计模式之结构型—享元模式

Java中最常用的设计模式-CSDN博客

把“不可变且可复用”的细粒度对象缓存起来,用“共享”代替“新建”,从而节省内存。

经典场景

  • 字符串常量池、Integer.valueOf(-128~127)、Android Message.obtain()

  • 游戏粒子、编辑器字形、地图瓦片、线程池中的任务包装器

android Message

Android 里 Message 对享元模式(Flyweight)的实现就是 “对象池 + 不可变字段拆分” 的典型案例。

Android 的 Message 把享元模式做成了 “运行期对象池”
内部状态(what/arg1/arg2/obj 等字段结构)被所有消息共享;外部状态(具体数值、target、when)由调用者每次临时传入;用完调用 recycle() 把对象回收到 静态链表池(sPool),下次 obtain() 再取出来复用,从而避免大量 new Message() 造成的内存与 GC 压力

核心流程

  1. 借对象:Message.obtain() 从链表头 sPool 弹出一个空闲节点,池空才 new Message()

  2. 填充外部状态:调用者给 whatarg1obj 等赋值。

  3. 回收对象:Handler 处理完消息后自动走 recycle()recycleUnchecked(),把字段清零并插回链表,池大小上限 50

同步与性能

  • 使用 sPoolSync 对象锁 保证多线程安全;

  • 链表替代 Map,减少哈希计算,O(1) 取出/归还;

  • 只缓存“空壳”字段结构,不缓存业务数据,实现 零状态污染 的共享

Message.obtain() 就是 Android 对享元模式的落地:把不变字段当模板共享,把变化数据当参数注入,用链表池循环复用,既省内存又保线程安全

享元池核心源码

// 系统隐藏类:android.os.Message
public final class Message implements Parcelable {
    /* 享元字段:可复用的内部状态 */
    public int what;
    public int arg1;
    public int arg2;
    public Object obj;
    /* 外部状态:Handler、时间戳等由调用者每次传入 */
    /* ... */

    // ===== 享元工厂 =====
    private static final Object sPoolSync = new Object();
    private static Message sPool;       // 链表头
    private static int sPoolSize = 0;
    private static final int MAX_POOL_SIZE = 50;

    // 对外暴露的“借对象”方法
    public static Message obtain() {
        synchronized (sPoolSync) {
            if (sPool != null) {
                Message m = sPool;
                sPool  = m.next;
                m.next = null;
                sPoolSize--;
                return m;
            }
        }
        return new Message();   // 池空就新建
    }

    // 用完归还
    public void recycle() {
        // 清空可复用字段
        what = 0; arg1 = 0; arg2 = 0; obj = null;
        synchronized (sPoolSync) {
            if (sPoolSize < MAX_POOL_SIZE) {
                next = sPool;
                sPool = this;
                sPoolSize++;
            }
        }
    }
}

客户端使用示例

// 借
Message msg = Message.obtain();   // 复用池内对象
msg.what = 1;
msg.arg1 = 100;
msg.obj  = "Hello";

// 发送
handler.sendMessage(msg);

// 系统 Looper 处理完后会自动调 recycle() 归还

Message.obtain() 就是 Android 对享元模式的最佳实践:内部状态缓存复用,外部状态调用方提供,既省内存又免锁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值