设计模式:享元模式

一、定义:

使用享元对象有效地支持大量的细粒度对象。

二、角色

  • Flyweight:抽象的享元角色,是产品的抽象类,同时定义出对象的外部状态和内部状态的接口或实现。
  • ConcreteFlyweight:具体的享元角色,是具体的产品类,实现抽象角色,定义相关业务。
  • UnsharedConcreteFlyweight:不可共享的角色,一般不会出现在享元工厂。
  • FlyweightFactory:享元工厂类,用于构建一个池容器(集合),同时提供从池中获取对象的方法。

三、使用场景

  • 系统中存在大量的相似对象
  • 细粒度的对象都具备较接近的外部状态,并且内部状态和环境无关,也就是对象没有特定身份
  • 需要缓冲池的场景

四、案例代码

/**
 * 享元对象抽象基类
 */
interface Book {
    void readBook();
}

/**
 * 具体的享元对象
 */
class ConcreteBook implements Book {
    private String name;

    public ConcreteBook(String name) {
        this.name = name;
    }

    @Override
    public void readBook() {
        System.out.println("当前正在阅读:" + name);

    }
}

/**
 * 定义享元工厂 -- 图书工厂
 */
class BookFactory {
    private static Map<String, Book> bookMaps = new HashMap<>();

    public static ConcreteBook getBook(String name) {
        if (bookMaps.containsKey(name)) {
            System.out.println("有该书籍,直接找到");
            return (ConcreteBook) bookMaps.get(name);
        } else {
            System.out.println("没有该书籍,去买一本,重新创建");
            ConcreteBook book = new ConcreteBook(name);
            bookMaps.put(name, book);
            return book;
        }
    }
}

//客户端
public class Client {
    public static void main(String[] args) {
        ConcreteBook book1 = BookFactory.getBook("三国演义");
        book1.readBook();
        ConcreteBook book2 = BookFactory.getBook("三国演义");
        book2.readBook();
    }
}

五、在Android中的使用

  • Android Handler消息机制,Message

发送消息的时候最终调用sendEmptyMessageAtTime,通过Message.obtain();创建message并发送。享元模式就是从obtain这里切入。

public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
        Message msg = Message.obtain();
        msg.what = what;
        return sendMessageAtTime(msg, uptimeMillis);
    }

Message.obtain

message要么是从最后new Message返回一个新的对象,要么返回sPool。当返回sPool时就是返回已创建的重复对象

    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是一个单链表对象

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

  • JDK中的String

jdk中的String也是类似的消息池。一个String被定义过后就存在于常量池中。当其他地方使用相同的字符串时,实际使用的是缓存。

六、优缺点

优点:

  • 大幅度地降低内存中对象的数量,降低程序内存占用;

缺点:

  • 使得系统更加复杂,为了使对象可以共享,需要将一些状态外部化,使得程序的逻辑复杂化;
  • 将享元对象的状态外部化,而读取外部状态使得运行时间稍微变长;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值