主管约谈
主管叫我过去,说到:“小陈,春节快要到了,为了方便我们同事查询火车票的情况,你开发一个火车票查询系统吧”。我心想,这个系统对于我来说,那简直是太简单了。
我是我着手这个需求的开发了。
需求开发
需求开发完以后,有彩蛋,一定要坚持看下去。
这就是一个简单的查询系统,实例代码如下:
第一步:定义一个票接口。
package com.example.createproject;
/**
* 票接口
*/
public interface Ticket {
/**
* 获取票信息接口
*/
void showTicketInfo();
}
复制代码
第二步:定义火者票的实现类。
package com.example.createproject;
import android.util.Log;
import java.util.Random;
public class TrainTicket implements Ticket {
private static final String TAG = TrainTicket.class.getSimpleName();
private String from;
private String to;
private String price;
private String puwei;//铺位
public TrainTicket(String from, String to, String puwei) {
this.from = from;
this.to = to;
this.puwei = puwei;
}
@Override
public void showTicketInfo() {
price = new Random().nextInt() + "";
Log.e(TAG, "购买了从 " + from + "到" + to + " 的火车票,票价:" + price);
}
}
复制代码
第三步:定义火车票的管理类。
package com.example.createproject;
public class TrainTicketManager {
public static TrainTicket getTicketInfo(String from, String to, String puwei) {
return new TrainTicket(from, to, puwei);
}
}
复制代码
第四步:用户去查询火车票信息。
TrainTicket ticketInfo = TrainTicketManager.getTicketInfo("深圳", "西安", "上铺");
复制代码
写实现了上面的功能以后,我交给了主管,希望得到主管的夸奖:效率高,查询快….
主管再次约谈
主管叫我过去,说到:“小陈,这样的系统你也敢给我看,getTicketInfo方法每次都返回一个TrainTicket对象 ,假设我们的系统有1000万的人同时查询,那岂不是要创建1000万个对象,那公司的服务器岂不是要爆炸了?”,我听到以后,觉得不是服务器要爆炸了,而是我的头要爆炸了。主管看我一脸困惑,说到:“你可以采用享元设计模式重构优化一下”。
我很敏锐的捕捉到了关键字:享元设计模式。
主管告诉我说:在下面的情况下,你可以考虑享元设计模式。
享元设计模式的场景
1、当一个系统中存在大量相似的对象。
2、如果系统中需要设计缓冲池。
比如在车票查询系统中,会爆发大量的车票信息对象,而对于一辆车K5038来说,它的作座位是固定的个数,比如有500个,如果我们有500万次查询,如果有500万个车票对象产生,显然是不合理的,那么我们可以进行如下优化。
思考:Android系统中哪些地方会使用池的设计思想、也可以认为是缓存的设计思想?
1、图片框架中的三级缓存思想。将图片缓存在内存和本地中。
2、网络框架中使用的线程池思想。
3、自定义控件属性集合TypeArray底层也是用了池的思想,我们可以通过typeArray.recycle();来看到。
4、消息机制中Message的创建,查看源码,我们发现Message是通过Message.obtain()来获取的,但是Message消息池并没有使用Map,而是使用的是链表,当我们获取Message的时候,首先是从缓冲池中获取,如果缓存池中没有,则重新创建一个。
优化流程
针对上面的流程,我们可以进行简单优化。
package com.example.createproject;
import java.util.HashMap;
import java.util.Map;
public class TrainTicketManager {
// 缓冲池的思想
static Map<String, TrainTicket> map = new HashMap<>();
public static TrainTicket getTicketInfo(String from, String to, String puwei) {
// key值
String key = from + "-" + to + "-" + puwei;
// 如果缓存中有,那么就从缓存中去取
// 如果缓存中没有,那么构造之后,放入缓存中
if (map.containsKey(key)) {
return map.get(key);
} else {
TrainTicket trainTicket = new TrainTicket(from, to, puwei);
map.put(key, trainTicket);
return trainTicket;
}
}
}
复制代码
享元模式是什么
通过上面的例子,我们可以看到享元模式有下面的特点:
1、享元模式内部维护着一个缓冲池,这个缓冲池可以使Map,可以使链表,可以使其他的数据接口,选择最合适的就好。
2、它的核心思想其实就是缓存思想。
3、利用享元模式创建的系统,可以避免创建过多的对象。
主管继续给我讲到,我们将上面的流程图示化
享元模式的UML类图
总结
1、享元模式是比较简单的,主要是利用缓存数据结构的使用,比如Map等。
2、可以大大减少创建对象的个数,降低程序内存的使用,增强程序的性能。