假如程序中有一个Person类,我的需求就是需要在整个应用程序中只能new一个Person,而且这个Person实例在应用程序中进行共享,那么我们该如何实现呢?
第一步:
新建一个Person类,类中我们将构造函数私有化,这样就不能再外部new一个了
第二步:
我们在公开一个Person属性实例或者获取Person实例的方法就可以在外部得到Person实例了,ok,看下面代码吧
代码如下:
单例模式的懒汉式实现
Person.java
package com.designpattern.singleton; public class Person { private String name; private int age; //饿汉式 public static final Person PERSON = new Person(); private Person(){} public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
MainClass.java
package com.designpattern.singleton; public class MainClass { public static void main(String[] args) { //假如我希望整个应用程序中只能有一个人,也就是说只能new Person()一次,只能存在一个Person实例 /* * 单例模式第一种实现:饿汉式 */ // Person person = Person.PERSON; // person.setName("jack"); // Person person2 = Person.PERSON; // person2.setName("jack1"); // System.out.println(person.getName()); // System.out.println(person2.getName());//结果姓名相同,都为jack1 /* * 单例模式第二种实现:懒汉式,这种方式在多线程下是不安全的 */ // Person2 person = Person2.getPerson2Instance(); // person.setName("jack"); // Person2 person2 = Person2.getPerson2Instance(); // person2.setName("jack1"); // System.out.println(person.getName()); // System.out.println(person2.getName());//结果姓名相同,都为jack1 /* * 单例模式第三种实现:双重验证,多线程下安全 */ Person2 person = Person2.getPerson2Instance2(); person.setName("jack"); Person2 person2 = Person2.getPerson2Instance2(); person2.setName("jack1"); System.out.println(person.getName()); System.out.println(person2.getName());//结果姓名相同,都为jack1 } }
单例模式的懒汉式和在多线程下双重验证实现
Person2.java
package com.designpattern.singleton; public class Person2 { private String name; private int age; private static Person2 person2; private Person2(){} public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } /** * 单线程获取person2单个实例 * @return */ public static Person2 getPerson2Instance(){ if (person2==null) { person2 = new Person2(); } return person2; } /** * 多线程获取person2单个实例 * @return */ public static Person2 getPerson2Instance2(){ if (person2==null) { synchronized (Person2.class) { if (person2==null) { person2 = new Person2(); } } } return person2; } }
一、什么是单例模式
单例模式是一种对象创建型模式,使用单例模式,可以保证为一个类只生成唯一的实例对象。也就是说,在整个程序空间中,该类只存在一个实例对象。
其实,GoF对单例模式的定义是:保证一个类、只有一个实例存在,同时提供能对该实例加以访问的全局访问方法。
二、为什么要使用单例模式呢?
在应用系统开发中,我们常常有以下需求:
- 在多个线程之间,比如servlet环境,共享同一个资源或者操作同一个对象
- 在整个程序空间使用全局变量,共享资源
- 大规模系统中,为了性能的考虑,需要节省对象的创建时间等等。
因为Singleton模式可以保证为一个类只生成唯一的实例对象,所以这些情况,Singleton模式就派上用场了。
三、单例模式实现
1.饿汉式。
2.懒汉式。
3.双重检查。
四、单例模式优缺点:
主要优点:
1、提供了对唯一实例的受控访问。
2、由于在系统内存中只存在一个对象,因此可以节约系统资源,对于一些需要频繁创建和销毁的对象单例模式无疑可以提高系统的性能。
3、允许可变数目的实例。
主要缺点:
1、由于单利模式中没有抽象层,因此单例类的扩展有很大的困难。
2、单例类的职责过重,在一定程度上违背了“单一职责原则”。
3、滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;如果实例化的对象长时间不被利用,系统会认为是垃圾而被回收,这将导致对象状态的丢失。