单例模式
就像任务管理器一样,只能由一个实例,你不能同时打开两个任务管理器,所以单例模式的对象不可以再外部通过new来创建,只能再类里通过private static
来保证她的单例属性,再声明一个public函数来访问她。
** 私有静态成员单例**+
私有单例构造函数+
公有访问函数
任务管理器例子
//由于每次使用new关键字来实例化TaskManager类时都将产生一个新对象, 为了确保
//TaskManager实例的唯一性, 我们需要禁止类的外部直接使用new来创建对象, 因此需要将
//TaskManager的构造函数的可见性改为private
//构造函数改为private修饰后该如何创建对象呢? 不要着急, 虽然类的外部无法再使用new
//来创建对象, 但是在TaskManager的内部还是可以创建的, 可见性只对类外有效。 因此, 我们
//可以在TaskManager中创建并保存这个唯一实例。 为了让外界可以访问这个唯一实例, 需要在
//TaskManager中定义一个静态的TaskManager类型的私有成员变量,
//为了保证成员变量的封装性, 我们将TaskManager类型的tm对象的可见性设置为private, 但
//外界该如何使用该成员变量并何时实例化该成员变量呢? 答案是增加一个公有的静态方法,
class TaskManager{
private static TaskManager tm = null;
private TaskManager(){}
public static TaskManager getInstance(){
if (tm==null){
tm = new TaskManager();
}
return tm;
}
public void displayProcess(){}
}
负载均衡器
不管客户端代码。调用几次访问函数,她返回的都是唯一实例(地址相同)
import java.util.*;
class LoadBalancer {
private static LoadBalancer instance = null;
private List serverList = null;
//私有构造函数
private LoadBalancer(){
serverList =new ArrayList();
}
//公有静态成员方法。返回唯一实例
public static LoadBalancer getLoadBalancer(){
if(instance==null){
instance =new LoadBalancer();
}
return instance;
}
//add server
public void addServer(String server){
serverList.add(server);
}
//delete server
public void removeServer(String server){
serverList.remove(server);
}
//using Random class randomly gets server
public String getServer(){
Random random = new Random();
int i = random.nextInt(serverList.size());
return (String)serverList.get(i);
}
}
存在的缺陷
如果把上列的单例模式放再生产线中,会出现一个问题:如果线程A首次访问,发现为null则去创建一个新的,再创建的过程中,线程B也访问,又创建了一个。这样就违背了单例原创,一个系统中则存在好几个单例,如何解决这个问题呢,有两个方案,饿汉和懒汉。
饿汉
在声明的时候就初始化,不给多线程而带来的初始化时间差机会。
public class EagerSingleton {
private static final EagerSingleton instance =new EagerSingleton;
private EagerSingleton(){}
public static EagerSingleton getInstance(){
return instance;
}
}
懒汉
使用同步锁synchronized
package method.Singleton;
public class LazySingleton {
private static LazySingleton instance = null;
private LazySingleton(){}
public static LazySingleton getInstance(){
if(instance == null){
synchronized(LazySingleton.calss){
instance = new LazySingleton();
}
}
return instance;
}
}