设计模式之--单例模式

来源:互联网 发布:服务器域名怎么看 编辑:程序博客网 时间:2024/06/10 17:25

1、什么是单例模式?

  单例模式也属于创建型模式,所以也是用于创建对象的,顾名思义,“例”是“实例”的意思,“单”是“单独、唯一”的意思,所以单例模式就是指使类在内存中只能有一个对象的模式。

2、单例模式的应用?

  单例模式在线程池、数据库连接池、网站计数器等其他地方中被应用,因为每次创建线程和数据库连接是相对而言比较麻烦的,所以我们可以只创建一次,然后对其进行重复使用,当被使用完毕之后,重新将其放入池中,等再次用时直接从池里取出来应用。对于网站计数器用来统计网站访问人数来说,如果有多个计数器同时统计肯定会有出现错误数据的可能,所以只能够有一个计数器在使用。

3、单例模式的理念?

  应用单例模式使得类在内存中只能有一个对象,那么要实现就必须要保证外界不能够随意创建这个类的对象,也就是说不能让外界随意的调用这个类的构造方法,解决方案只能是将这个类的构造方法私有化,从而使外界不能直接调用。

  外界不能创建这个类的对象了,那么这个类必须创建一个本类的对象,而且还必须提供一个公共的方式来让外界使用。这个公共的方式就是定义一个public修饰的方法,方法的返回值就是这个类那个唯一的对象的引用。方法要由static关键字修饰,也就是做成静态方法,从而能够直接用类名调用方法(如果是非静态方法则必须创建类的对象进行调用,这就和之前说的不能让外界创建对象矛盾了)。

4、单例模式的使用分类

  单例模式的使用共分成两类,分别是饿汉式(类一加载就创建对象)和懒汉式(什么时候用什么时候创建),下面分别来进行代码分析。

  饿汉式:

    像个饿汉一样,类一加载就创建了对象,不管你以后是否用不用这个对象代码实现如下:

<span style="font-size:14px;">public class Student {// 把构造方法私有,是为了不让外界随意创建对象private Student() {}// 类本身创建一个唯一的对象。//加私有是为了不让外界通过类名直接访问s,进而修改s的值private static Student s = new Student();//饿汉式,类一加载就会创建这个唯一的对象// 提供公共的方法让外界使用// 为了让外界能够直接通过类名访问该方法,需要对该方法加静态//因为静态方法只能访问静态成员,所以s也要用静态修饰public static Student getStudent() {// 调用方法只能返回对象的引用return s;}}</span>
    这个时候,我们像如下调用时:

<span style="font-size:14px;">        Student s1 = Student.getStudent();        Student s2 = Student.getStudent();System.out.println(s1 == s2);</span>
    打印出的返回值为true,也印证了单例模式作用下,类只能创建唯一的对象。

  懒汉式:

    像一个懒汉一样,什么时候用什么时候才创建对象。代码实现如下:

<span style="font-size:14px;">public class Student {private Student() {}//声明对象的引用,但是不创建对象private static Student s = null;//调用公共方法时才创建对象public static Student getStudent() {// 如果t是null的时候,创建对象if (s == null) {s = new Student();}//否则,返回sreturn s;}}</span>

5、饿汉式和懒汉式的优缺点?

  饿汉式:由于首先创建了对象,所以调用方法的时候可以直接返回对象的引用,提高了调用效率;但是也因为提前创建了对象,所以不管你用不用这个对象,这个对象都会在内存中存在,消耗你的内存空间。

  懒汉式:什么时候用什么时候创建对象,如果你不用,不会像饿汉式那样消耗你的内存空间;但是懒汉式存在线程安全问题。

附:什么是线程安全问题?

  在懒汉式中,如果是在多线程环境下,有1号、2号、3号线程同时执行到了if (s == null)这一步,此时1号线程抢到了CPU的执行权,1号线程就通过了if(s==null)这一步,但是当1号执行s = new Student()之前,2号线程又抢到了CPU执行权,因为这时候1号还没有创建s指向的对象,所以2号线程也能通过if(s==null)的验证,来到s = new Student()这一步,从而就会创建两遍s指向的对象。

  那么线程安全问题如何解决呢?

  可以在可能出现问题的代码上加锁,锁上就行了,代码如下:

<span style="font-size:14px;">public class Student {private Student() {}private static Student s = null;//在方法之上加锁public synchronized static Student getStudent() {if (s == null) {s = new Student();}return s;}}</span>
  小结:单例模式保证了一个类只能创建一个对象,而对于饿汉式和懒汉式各有千秋,其实际应用要依据实际情况而定。

1

3 0
原创粉丝点击