什么是单体模式
在面向对象编程中,我们有时候需要只有一个对象或者实例,如注册表,线程池等。俗话说“一山不容二虎”,往往多个实例会导致软件系统出错,或者导致资源浪费。这时候可以引入单体的设计模式,来限制产生新实例或对象。
单体模式(Singleton Pattern)就是确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。 —《设计模式之禅》
java实现方式
- 定义私有访问权限的构造函数,避免被其他类new出新对象
- 解决方法:
public calss Singleton {
private static Singleton firstInstance = null;
private Singleton(){}
public static Singleton getInstance(){
if(firstInstance == null) {
firstInstance = new Singleton();
}
}
return firstInstance;
}
可以从上面例子看出,其他类对这个类的访问可以通过getInstance获得同一个对象。
不过,该方法在高并发条件下,可能出现线程不安全的情况。可以利用synchronized关键字来消除这种问题。这种解决方案也被称为懒汉式解决方法。
- 饿汉式解决方法:
该解决方案直接在类的内部先实例化一个私有变量。而外部如果需要获得该对象,必须通过getInstance方法来获取。
public calss Singleton {
private static Singleton firstInstance = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return firstInstance;
}
}
小扩展:有上限的多例模式
要想实现能产生固定数量的实例类,可以采用以下方法:
public class Apple{
//最多产生三个苹果实例
private static int maxNumOfApple = 3;
private static ArrayList<String> nameList = new ArrayList<String> ();
private static ArrayList<Apple> appleLisst = new ArrayList<Apple> ();
//当前序列号
private static int countNumOfApple = 0;
static{
for(int i = 0; i < maxNumOfApple; i++){
appleList.add(new Apple('第'+ (i+1) + '个'));
}
}
private Apple(){};
private Apple(String name){
nameList.add(name);
}
//随机获得实例
public static Apple getInstance(){
Random random = new Random();
countNumOfApple = random.nextInt(maxNumOfApple);
return appleList.get(countNumOfApple);
}
}
javascript实现方式
- example1:
var Singleton = {
attribute: atr1,
attribute: atr2,
fun1 : function(){},
fun2 : function(){}
};
在这个例子中,可以通过Singleton这个对象访问所有的属性和方法。但同时因为javascript对象的易变性,为了避免无意中改写变量,可以将单体对象中的代码组织在命名空间中。
在javascript中,可以利用单体模式封装某些专用的代码,避免其他页面的调用。
var dom = (function (){
var _counter = 0;
var instance;
function generateId() {
return 'customId' + _counter++;
}
function create(tagName, id) {
var el = document.createElement(tagName);
el.id = id || generateId();
}
function createInstance() {
return {
generateId: generateId,
create: create
};
}
return {
getInstance: function() {
return instance || (instance = createInstance());
}
}
}(););
适用场景
- 要求生成唯一序列号的环境
- 整个项目需要一个共享访问点或共享数据
- 创建一个对象消耗资源过多