享元模式的定义
Use sharing to support large numbers of fine-grained objects efficiently. (使用共享对象可有效地支持大量的细粒度的对象)
享元模式的应用
-
享元模式的优点
享元模式是一个非常简单的模式,它可以大大减少应用程序创建的对象,降低程序内存的占用,增强程序的性能
-
享元模式的缺点
提高了系统复杂性,需要分离出外部状态和内部状态,而且外部状态具有固化特性,不应该随内部状态改变而改变,否则导致系统的逻辑混乱。
-
享元模式的使用场景。
系统中存在大量的相似对象。
细粒度的对象都具备较接近的外部状态,而且内部状态与环境无关,也就是说对象没有特定身份。
需要缓冲池的场景。
享元模式的实现
/**
* 报考信息
*/
public class SignInfo {
//报名人员的ID
private String id;
//考试地点
private String location;
//考试科目
private String subject;
//邮寄地址
private String postAddress;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getPostAddress() {
return postAddress;
}
public void setPostAddress(String postAddress) {
this.postAddress = postAddress;
}
}
/**
* 报考信息工厂
*/
public class SignInfoFactory {
//池容器
private static HashMap<String, SignInfo> pool = new HashMap<String, SignInfo>();
//从池中获得对象
@Deprecated
public static SignInfo getSignInfo(String key) {
//设置返回对象
SignInfo result = null;
//池中没有该对象,则建立,并放入池中
if (!pool.containsKey(key)) {
result = new SignInfo();
pool.put(key, result);
} else {
result = pool.get(key);
}
return result;
}
}
//多线程场景
public class MultiThread extends Thread {
private SignInfo signInfo;
public MultiThread(SignInfo _signInfo) {
this.signInfo = _signInfo;
}
public void run() {
if (!signInfo.getId().equals(signInfo.getLocation())) {
System.out.println("编号:" + signInfo.getId());
System.out.println("考试地址:" + signInfo.getLocation());
System.out.println("线程不安全了");
}
}
}
public class Client {
public static void main(String[] args) {
//在对象池中初始化4个对象
SignInfoFactory.getSignInfo("科目1");
SignInfoFactory.getSignInfo("科目2");
SignInfoFactory.getSignInfo("科目3");
SignInfoFactory.getSignInfo("科目4");
//取得对象
SignInfo signInfo = SignInfoFactory.getSignInfo("科目2");
while (true) {
signInfo.setId("zhangsan");
signInfo.setLocation("zhangsan");
new MultiThread(signInfo).start();
signInfo.setId("lisi");
signInfo.setLocation("lisi");
new MultiThread(signInfo).start();
}
}
}
享元模式源码中的应用
Handler 消息机制中的 Message 消息池就是使用享元模式复用了 Message 对象。
使用 Message 时一般会用到 Message.obtain 来获取消息。如果使用 new Message() 会构造大量的 Message 对象。