1、一个严格意义上的不可变对象
a、类本身使用final修饰:防止其子类改变其定义行为。
b、所有字段都用final修饰
c、在对象的创建过程中,this关键字没有泄露给其他类:防止其他类(包括内部匿名类)在对象创建过程中修改其状态。
d、任何字段,若引用了其他状态可变的对象(如集合、数组、对象等),则这些字段必须是private修饰,并且这些字段不能对外暴露,应该进行防御性复制(defensive Copy)
2、适用场景
a、被建模对象的状态改变不频繁。
b、同时对一组相关的数据进行些操作,因此需要保证原子性
c、适用某个对象为安全的HashMap的Key
3、volatile内存可见 + 只改变对象引用 = 无需加锁也是安全的
代码
/**
* 彩信路由类
* 不可变对象需用final修饰
* @author huzhiqiang
*
*/
public final class MMSCRouter {
/**
* static 变量归类所有,
* volatile 保持实体的内存可见性
*/
private static volatile MMSCRouter instance = new MMSCRouter();
private final Map<String, MMSCInfo> routerMap;
public MMSCRouter(){
routerMap = MMSCRouter.getDataFromDB();
}
private static Map<String, MMSCInfo> getDataFromDB() {
// TODO Auto-generated method stub
Map<String, MMSCInfo> map = new HashMap<String, MMSCInfo>();
/**
* 从数据库获取数据
*/
return map;
}
/**
* 通过手机号码前缀获取彩信中心
* @param msisdnPrefix 手机号码前缀
* @return
*/
public MMSCInfo getMMSCInfo(String msisdnPrefix){
return routerMap.get(msisdnPrefix);
}
public Map<String, MMSCInfo> getRoutermap(){
//做防御性复制,不可将类的真实变量引用返回给其他用户
return Collections.unmodifiableMap(deepcopy(routerMap));
}
private Map<String, MMSCInfo> deepcopy(Map<String, MMSCInfo> m) {
Map<String, MMSCInfo> result = new HashMap<String, MMSCInfo>();
for(String key : m.keySet()){
result.put(key, m.get(key));
}
return result;
}
public static MMSCRouter getInstance() {
return instance;
}
public static void setInstance(MMSCRouter instance) {
MMSCRouter.instance = instance;
}
}
/**
* 彩信中心信息
* 不可变对象需用final修饰
* @author huzhiqiang
*
*/
public final class MMSCInfo {
/**
* 变量用final修饰
* 设备编号
*/
private final String deviceID;
/**
* 彩信中心URL
*/
private final String url;
/**
* 设置彩信中心允许的最大附件大小
*/
private final String maxAttachmentSizeinBytes;
public MMSCInfo(String deviceID, String url, String maxAttachmentSizeinBytes) {
super();
this.deviceID = deviceID;
this.url = url;
this.maxAttachmentSizeinBytes = maxAttachmentSizeinBytes;
}
public MMSCInfo(MMSCInfo info) {
super();
this.deviceID = info.getDeviceID();
this.url = info.getUrl();
this.maxAttachmentSizeinBytes = info.getMaxAttachmentSizeinBytes();
}
public String getDeviceID() {
return deviceID;
}
public String getUrl() {
return url;
}
public String getMaxAttachmentSizeinBytes() {
return maxAttachmentSizeinBytes;
}
}
public class OMCAgent extends Thread {
@Override
public void run() {
boolean isTableModificationMsg = false;
String updateTableName=null;
while(true){
//省略其他代码
/**
* 从与OMC连接的Socket中读取消息并进行解析,
* 解析到数据表更新消息后,重置MMSCRouter实例
*/
if(isTableModificationMsg){
if("MMSCInfo".equals(updateTableName)){
MMSCRouter.setInstance(new MMSCRouter());
}
}
//省略其他代码
}
}
}