享元模式是对象池的一种实现,用来尽可能减少内存使用量,适合用于可能存在大量重复对象的场景,来缓存可共享的对象;
定义:
使用共享对象可有效地支持大量的细粒度的对象;
使用场景:
UML类图:
Flyweight:
享元对象抽象基类或者接口;
ConcreteFlyweight:
具体的享元对象;
FlyweightFactory:
享元工厂,负责管理享元对象池和创建享元对象;
这里以读书
进行举例,现在想阅读三国演义
,但家里没有那就需要去买一本(享元工厂生产一本三国),读完了又想看水浒传
,家里也没有那也需要去买一本(享元工厂生产一本水浒),回过头,又想要在读一遍三国,那就不再在去买了,直接找到原来的一本读就好了;
下面用享元模式实现:
Book
/*** 享元对象抽象基类*/
interface Book {/*** readBook*/fun readBook()
}
ConcreteBook
/*** 具体的书籍,具体的享元对象* @param name 图书名称*/
class ConcreteBook(private val name: String) : Book {override fun readBook() {println("当前正在阅读:$name")}
}
BookFactory
/*** 图书工厂*/
object BookFactory {private val bookMaps = hashMapOf()fun getBook(name: String): ConcreteBook {return if (bookMaps.containsKey(name)) {println("家里有该书籍,直接找到")bookMaps[name] as ConcreteBook} else {println("家里没有该书籍,去买一本")val book = ConcreteBook(name)bookMaps[name] = bookbook}}
}
object Test {@JvmStaticfun main(args: Array) {//阅读三国演义val book1 = BookFactory.getBook("三国演义")book1.readBook()println("============================")//阅读水浒传val book2 = BookFactory.getBook("水浒传")book2.readBook()println("============================")//再读一遍三国演义val book3 = BookFactory.getBook("三国演义")book3.readBook()}
}
输出结果如下:
家里没有该书籍,去买一本
当前正在阅读:三国演义
============================
家里没有该书籍,去买一本
当前正在阅读:水浒传
============================
家里有该书籍,直接找到
当前正在阅读:三国演义
Message
,熟悉Android消息机制的同学,对于Message
肯定不陌生,我们废话不多说,直接看源码:public final class Message implements Parcelable {//message相关信息public int what;public int arg1;public int arg2;public Object obj;public Messenger replyTo;//可以看出message是一个链表结构Message next;public static final Object sPoolSync = new Object();private static Message sPool;//当前消息池的大小private static int sPoolSize = 0;//消息池中最多缓存50个messageprivate static final int MAX_POOL_SIZE = 50;private static boolean gCheckRecycle = true;//如果sPool不为null,则从消息池中取消息,否则直接new Message()对象;public static Message obtain() {synchronized (sPoolSync) {if (sPool != null) {//从链表头取出MessageMessage m = sPool;sPool = m.next;m.next = null;m.flags = 0; // clear in-use flagsPoolSize--;return m;}}return new Message();}//进行回收public void recycle() {//如果当前正在使用,则调用recycle方法抛异常if (isInUse()) {if (gCheckRecycle) {throw new IllegalStateException("This message cannot be recycled because it "+ "is still in use.");}return;}recycleUnchecked();}//回收处理,清除相关信息,并将message插入到消息池中void recycleUnchecked() {flags = FLAG_IN_USE;what = 0;arg1 = 0;arg2 = 0;obj = null;replyTo = null;sendingUid = UID_NONE;workSourceUid = UID_NONE;when = 0;target = null;callback = null;data = null;synchronized (sPoolSync) {//判断消息池不满50时,将消息插入到链表头部if (sPoolSize < MAX_POOL_SIZE) {next = sPool;sPool = this;sPoolSize++;}}}}
从上面我们可以看出,调用Message.obtain()
方法会从消息缓存池中取消息,这也是为什么推荐大家使用Message.obtain()
方法而不是直接new Message()
的原因,当Message
被回收的时候,会清除相关信息,将消息存放到消息池中,从而实现消息的重复利用,典型的享元模式
!!!
优点:
缺点:
如果以上文章对您有一点点帮助,希望您不要吝啬的点个赞加个关注,您每一次小小的举动都是我坚持写作的不懈动力!ღ( ´・ᴗ・` )
上一篇:网络编程套接字----UDP协议