Java实现泛型单例模式
(注:如果使用静态变量保存变量,可能会造成内存泄漏,因此慎用)
单例模式是设计模式中的一个,今天因为需求需要实现一个基于List的固定长度的列表,因为内容需要在多个地方共享,因此想到用单例模式实现是不错的选择。把要共享的实例设为static然后通过单例模式获取。由于考虑到可能固定列表的内容可能多样,因此使用泛型实现这个单例模式是个不错的选择。因此,有了如下的代码:
package cn.letsbook.running.model;
import java.util.ArrayList;
import java.util.List;
/**
* 泛型定长列表
*
* @author Jywang
* @email jywangkeep@163.com
* @param
* 列表内容类型
*/
public class FixedLengthList {
private List elementList = new ArrayList();
private int capacity;
private static final int DEFAULT_CAPACITY = 100;
private static FixedLengthList> instance;
@SuppressWarnings("unchecked")
public synchronized static FixedLengthList newInstance() {
if (instance == null)
instance = new FixedLengthList();
return (FixedLengthList) instance;
}
public FixedLengthList(int capacity) {
this.capacity = capacity;
}
public FixedLengthList() {
this.capacity = DEFAULT_CAPACITY;
}
protected synchronized void resizeCapacity(int capacity) {
if (capacity <= 0)
return;
while (elementList.size() > capacity) {
elementList.remove(0);
}
this.capacity = capacity;
}
public synchronized int getCapacity() {
return this.capacity;
}
public synchronized boolean addElement(T element) {
if (element == null)
return false;
return elementList.add(element);
}
public synchronized T getElement(int position) {
if (position < 0 || position >= elementList.size())
return null;
return elementList.get(position);
}
public synchronized T removeElement(int position) {
if (position < 0 || position >= elementList.size())
return null;
return elementList.remove(position);
}
public synchronized T getLastElement() {
return getElement(elementList.size() - 1);
}
}
单例新建的时候采用默认大小,resizeCapacity(int capacity)用于重新修改列表容量。修改的过程会根据实际的大小进行部分元素的删除。
对于静态泛型方法,在static修饰符之后在返回值之前,要声明要使用的泛型类型。如果只有一个类型就用即可,如果是两个,可以使用即可。对了,泛型中不同的参数有不同的含义:
T普通的泛型类型
E错误类型
K键值对的键值类型
V键值对的值类型
如果需要其他类型,可以使用T附近的变量,比如U
静态变量不能使用类的泛型类型,而必须使用确定的类型:比如Integer,Object之类的,也可以使用通配符?。开始的时候我尝试使用private static FixedLengthList instance,可是会报错。推测可能是因为,静态的变量数据类,而不是某个实例,与泛型类实例没有依赖关系。因此泛型类实例的类型不可用在静态变量上面。
方法都使用了synchronized关键字,可以认为方法是线程安全的。
我实现的单例模式是懒汉模式,也是最常用的模式。还有
饿汉模式,这个是声明变量的时候就直接新建实例,获取实例的时候不进行判断。
双重锁模式,对instance进行两次null判断。据说这个模式在JDK1.5之后意义很大。
如果想实现延迟加载,可以使用静态内部类。
如果需要类有序列化的要求,可以使用枚举实现。