单例设计模式简介
单例模式是设计模式中最简单的形式之一。这一模式的目的是使得类的一个对象成为系统中的唯一实例。要实现这一点,可以从客户端对其进行实例化开始。因此需要用一种只允许生成对象类的唯一实例的机制,“阻止”所有想要生成对象的访问。使用工厂方法来限制实例化过程。这个方法应该是静态方法(类方法),因为让类的实例去生成另一个唯一实例毫无意义。
为什么要有单例设计模式呢?
对于系统中的某些类来说,只有一个实例很重要,例如,一个系统中可以存在多个打印任务,但是只能有一个正在工作的任务;一个系统只能有一个窗口管理器或文件系统;一个系统只能有一个计时工具或ID(序号)生成器。如在Windows中就只能打开一个任务管理器。如果不使用机制对窗口对象进行唯一化,将弹出多个窗口,如果这些窗口显示的内容完全一致,则是重复对象,浪费内存资源;如果这些窗口显示的内容不一致,则意味着在某一瞬间系统有多个状态,与实际不符,也会给用户带来误解,不知道哪一个才是真实的状态。因此有时确保系统中某个对象的唯一性即一个类只能有一个实例非常重要。
举个简单的例子:我们玩游戏时里面会设置一些属性,声音大小,画质等等,我们修改了这些参数下次再启动时这些设置要继续实现而不用重复设置,此时单例设计模式就体现了其优势了。
如何保证一个类只有一个实例并且这个实例易于被访问呢?
我们要做三部工作:
1,将构造函数私有化,
2,在类中创建一个本类对象,
3,提供一个方法获取到该类对象
如下代码:
class Single{
private int num;
public void setNum(int num){
this.num = num;
}
public int getNum(){
return num;
}
private Single(){};//私有化,不能new一个对象
private static Single s = new Single();
public static Single getInstance(){
return s;
}
}
class SingleDemo
{
public static void main(String[] args)
{
Single s = Single.getInstance();
Single s2 = Single.getInstance();//s = s2
s.setNum(20);
System.out.println(s2.getNum());
s2.setNum(30);
System.out.println(s.getNum());
}
}
运行结果:
可以看到虽然我对对象s的的属性值num修改为20,让后输出对象s2num对象s2也显示20,,在把s2中的num修改成30,s中的num也显示的30,s和s2是同一个实例,这就保证的一个类只有一个实例。
单例设计模式的实现方式:
这里主要有两种
1,俄汉式
class Single{
private Single(){};
private static Single s = new Single();
public static Single getInstance(){
return s;
}
}
2,懒汉式
class Single_after{
private static Single_after s = null;
private Single_after(){};
public static synchronized Single_after getInstance(){
if(s==null)
s = new Single_after();
return s;
}
}
懒汉式和俄汉式有何区别:
俄汉式类一加载到内存中对象就被初始化。懒汉式对象是方法被调用时,才初始化,也叫做延时加载。类进内存,对象还没有存在,只有调用了getInstance方法才创建对象。
懒汉式在多个程序同时运行是容易出现错误要使用synchronized同步进行加锁比较麻烦
单例设计模式的优缺点:
优点:
实例控制:确保所有对象都访问唯一实例
灵活性:因为类控制了实例化过程,所以类可以更加灵活修改实例化过程
缺点:
开销:虽然数量很少,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销。
可能的开发混淆:使用single对象(尤其在类库中定义的对象)时,因为可能无法访问库源代码,因此应用程序开发人员可能会意外发现自己无法直接实例化此类。