单例设计模式

---------------------- QQ:371524846 期待与您交流! ----------------------

设计模式:
  解决某一类问题最行之有效的方法

Java中23种设计模式:

  单例设计模式:解决一个类在内存只存在一个对象。

一、保证对象唯一的思想及其实现:
  1.为了避免其他程序过多建立该类对象。先禁止其他程序建立该类对象。
  2.还为了让其他程序可以访问到该类对象,只好在本类中,自定义一个对象。
  3.为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式。

  这三部怎么用代码体现呢?
    将构造函数私有化。
    在类中创建一个本类类型对象。
    提供一个方法可以获取到该对象。

  注意:对于事物该怎么描述,还怎么描述。当需要将该事物的对象保证在内存中唯一时,就将以上的三步加上即可。

二、单例设计模式的具体表现形式:

  1、先初始化对象,类一进内存就加载,称为:饿汉式
    SingleHungry类一进内存,就已经创建好了对象。
eg:

 1 class SingleHungry{
 2     private String name;
 3     public void setName(String name){
 4         this.name=name;
 5     }
 6     public String getName(){
 7         return name;
 8     }
 9     private static SingleHungry s=new SingleHungry(); 
10     private SingleHungry(){}
11     public static SingleHungry getInstance(){
12         return s;
13     }
14 }
15 public class SingleTest{
16      public static void main(String[] args) {
17         SingleHungry s1 = SingleHungry.getInstance();
18         SingleHungry s2 = SingleHungry.getInstance();
19         s1.setName("南贤俊");
20         System.out.println(s2.getName());
21     }
22 }

  2、类进内存,对象还有没存在,只getInstance方法被调用时,才初始化对象,也叫做对象的延时加载,成为:懒汉式
  对于第二种懒汉式的单例设计模式,会出现一些小小的问题,当一个线程调用时,是没什么问题的,如果多个线程调用此种方式,那么就会出现问题。所以用到同步锁。
  SingleLazy类进内存,对象还没有存在,只有调用了getInstance方法时,才建立对象。
eg:

 1 class SingleLazy {
 2     private String name;
 3     public void setName(String name){
 4         this.name=name;
 5     }
 6     public String getName(){
 7         return name;
 8     }
 9     private static SingleLazy s=null;
10     private SingleLazy(){}
11     public static SingleLazy getInstance(){
12         if(s==null){
13             synchronized(SingleLazy.class){
14                 if(s==null)
15                     s=new SingleLazy();
16             }
17         }
18         return s;
19     }
20 }
21 public class SingleTest{
22      public static void main(String[] args) {
23         SingleLazy s1 = SingleLazy .getInstance();
24         SingleLazy s2 = SingleLazy .getInstance();
25         s1.setName("南贤俊");
26         System.out.println(s2.getName());
27     }
28 }

运行的结果是:南贤俊;这是因为s1和s2引用的是同一个对象,所以符合条件。


比如说,当A调用时,当读到if(s1==null) 时,可能就停在这了,然后cpu再调用B,B也读到if(s1==null)这停下了,cpu再切换到A,接着创建一个对象,A就执行完了;
之后B也向下执行,又创建一个对象;此时,对象就不唯一了,就破坏了对象的唯一性的初衷。那么解决方案是这样的:
这利用了锁的机制。synchronized是java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。
这涉及到了多线程的问题。在这个例子中,比如说,当A调用时,当读到第二个if(s1==null) 时,可能就停在这了,然后cpu再调用B,
B读到第一个if(s1==null)这停下了,因为加上synchronized后,A进去就相当于将其他的调用锁在外面的语句上了,要先执行完A,那么A执行完后,就已经创建了一个对象;
当B再读到第二个if(s1==null)的时候不符合就直接结束了。如果再有其他C或D等调用的时候,就直接不符合第一个(s1==null)的条件,所以直接返回s。


---------------------- QQ:371524846 期待与您交流! ----------------------

posted @ 2013-08-18 11:24  JunKwok  阅读(235)  评论(0编辑  收藏  举报