定义
享元模式(FlyWeight),运用共享技术有效的支持大量细粒度的对象。
与单例模式有些类似,都是生成一个对象以便共享使用,其目的是减少大量不必要的内存消耗。
实现
享元模式实现起来也相对简单,先来看代码:
public class Key {
// no-op
}
public class Book {
public String name;
public String author;
public String id;
public Book() {
this.name = name;
this.author = author;
this.id = id;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", author='" + author + '\'' +
", id='" + id + '\'' +
'}';
}
}
public class BookFactory {
private static final HashMap<Key, Book> bookPool = new HashMap<>();
public static Book obtainBook(Key key) {
Book book = null;
if (bookPool.containsKey(key)) {
book = bookPool.get(key);
} else {
book = new Book();
bookPool.put(key, book);
}
return book;
}
}
public class Client {
public static void main(String[] args) {
Key k1 = new Key();
Key k2 = new Key();
Book b1 = BookFactory.obtainBook(k1);
b1.author = "ME";
b1.id = "123456";
b1.name = "JAVA XXX";
Book b2 = BookFactory.obtainBook(k2);
b2.id = "654321";
b2.name = "Linux XXX";
b1.author = "YOU";
Book b3 = BookFactory.obtainBook(k1);
b1.author = "ME2";
b1.id = "1234567";
b1.name = "JAVA XXX2";
System.out.println(b1);
System.out.println(b2);
System.out.println(b3);
// print
/*
Book{name='JAVA XXX2', author='ME2', id='1234567'}
Book{name='Linux XXX', author='null', id='654321'}
Book{name='JAVA XXX2', author='ME2', id='1234567'}
*/
}
}
以上代码实现了简单享元模式,实际项目中可以灵活变通,根据业务需求设计合理的代码结构。
模式的使用场景
面向对象编程在某些情况下会创建大量的细粒度对象,它们的产生,存储,销毁都会造成资源和性能上的损耗,
可能会在程序运行时形成效率瓶颈,在遇到以下情况时,即可考虑使用享元模式:
(1)一个应用程序使用了大量的对象,耗费大量的内存,降低了系统的效率。
(2)这些对象的状态可以分离出内外两部分。
(3)这些对象按照状态分成很多的组,当把删除对象的外部状态时,可以用相对较少的共享对象取代很多组对象。
(4)应用程序不依赖这些对象的身份,即这些对象是不可分辨的。
在一般的开发中享元模式并不常用,其常常应用于系统底层的开发,以便解决系统的性能问题。
优点与缺点
-
优点——大幅度地降低内存中对象的数量,节省系统资源的开销
-
缺点
1、为了使对象可以共享,享元模式需要将部分状态外部化,使得系统的逻辑变得复杂。
2、读取状态外部化的享元对象,影响了系统速度,使运行时间有所加长。
Android 源码中的享元模式
最熟悉的莫过于 Android 中的 Message 了:
public static Message obtain(Message orig) {
Message m = obtain();
m.what = orig.what;
m.arg1 = orig.arg1;
m.arg2 = orig.arg2;
m.obj = orig.obj;
m.replyTo = orig.replyTo;
m.sendingUid = orig.sendingUid;
if (orig.data != null) {
m.data = new Bundle(orig.data);
}
m.target = orig.target;
m.callback = orig.callback;
return m;
}
网友评论