Android设计模式-21-享元模式
2018-06-20 本文已影响50人
今阳说
1. 定义
- 运用共享技术有效的支持大量细粒度的对象
2. 使用场景
- 系统中存在大量的相似对象
- 细粒度的对象都具备较接近的外部状态,而内部状态与环境无关,也就是说对象没有特定身份
- 需要缓冲池的场景
3. 优缺点
- 优点:
大幅度降低内存中对象的数量,提升性能减少内存 - 缺点:
为了使对象可以共享,需要将一些状态外部化,使得程序逻辑复杂化,而且读取外部状态使得运行时间稍微变长
4. Android源码中的使用
我们平时使用的Handler中的getPostMessage所得到的message对象就是通过享元模式创建的, 可以看下如下代码:
//使用Handler
handler.post(new Runnable() {
@Override
public void run() {
mTextViewShow.append("\nThread中new Handler(Looper.getMainLooper()) 更新UI");
}
});
//源码:
public final boolean post(Runnable r) {
return sendMessageDelayed(getPostMessage(r), 0);
}
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
// 可以看到Message对象并不是通过new去大量构建的,而是通过一个默认大小为50的对象池
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();
}
5. 实例演示
以购买火车票为例
- 创建一个车票接口
public interface Ticket {
//展示车票信息的函数
void showTicketInfo(String bunk);
}
- 创建一个实现类-火车票
//火车票
public static class TrainTicket implements Ticket {
public String from;//始发地
public String to;//目的地
public String bunk;//铺位
public int price;//价格
public TrainTicket(String from, String to) {
this.from = from;
this.to = to;
}
@Override
public void showTicketInfo(String bunk) {
this.bunk = bunk;
price = new Random().nextInt(500);
LjyLogUtil.i("购买 从 " + from + " 到 " + to + " 的 " + bunk + " " +
"火车票" + ", 价格: " + price);
}
}
- 创建车票的工厂类,使用享元模式
public static class TicketFactory {
static Map<String, Ticket> sTicketMap = new HashMap<>();
public static Ticket getTicket(String from, String to) {
//1.普通写法: 每次都new会消耗资源和内存,甚至导致OOM
// return new TrainTicket(from, to);
//2.享元模式
String key = from + "-" + to;
if (sTicketMap.containsKey(key)) {
LjyLogUtil.i("使用缓存==> " + key);
return sTicketMap.get(key);
} else {
LjyLogUtil.i("创建对象==> " + key);
Ticket ticket = new TrainTicket(from, to);
sTicketMap.put(key, ticket);
return ticket;
}
}
}
- 使用享元创建实例
private void methodFlyweightPattern() {
//以购买火车票为例
Ticket ticket1 = TicketFactory.getTicket("北京", "廊坊");
ticket1.showTicketInfo("软座");
Ticket ticket2 = TicketFactory.getTicket("北京", "云南");
ticket2.showTicketInfo("上铺");
Ticket ticket3 = TicketFactory.getTicket("北京", "廊坊");
ticket3.showTicketInfo("站票");
}