当程序运行时,有时会希望在程序中,只能存在一个实例,为了达到目的,所以设计了Singleton模式,即单例模式。

单例模式的特征:

  • 想确保任何情况下只存在一个实例
  • 想在程序上表现出只存在一个实例

示例程序:

  • Singleton单例类
package site.wangxin520.gof.singleton;

/**
 * 单例模式获取单例对象的类
 * @author wangXgnaw
 *
 */
public class Singleton {
    
    //将创建出来的对象设为静态的私有对象
    private static Singleton singleton=new Singleton();
    //将构造方法私有化,不允许外部类中使用new 去创建对象
    private Singleton(){}
    //对外提供一个静态方法,获取到对象,因为对象是静态的私有属性
    //所以是随着类的加载而加载的,并且只加载一次,这样一来,就只返回同一个对象了
    public static Singleton getInstance(){
        return singleton;
    }
    
}
  • Singleton单例测试程序
package site.wangxin520.gof.singleton;

/**
 * 单例模式的测试类
 * @author wangXgnaw
 *
 */
public class SingletonTest {

    public static void main(String[] args) {
        //使用getInstance获取实例化的方法,创建两个对象
        Singleton s1 = Singleton.getInstance();
        Singleton s2 = Singleton.getInstance();
        //==双等号,在判断对象的时候,是比较对象的地址值,如果地址值为一样的话,那么就代表,单例模式创建成功。
        if (s1==s2) {
            System.out.println("单例模式创建成功");
        }else {
            System.out.println("单例模式创建失败");
        }
        
    }
    
}
  • 测试结果:

image

 

在单例模式中,需要注意的是,多线程情况下单例模式可能存在的问题,这里不做讨论。还有就是static关键字的用法——静态随着类加载而加载,且只加载一次。

 

补充一个测试练习题:

编写Triple类,实现最多只能生成三个实例,实例编号为0,1,2,并且可以通过getInstance(int id)方法来获取到该编号对应的实例:

  • Triple类
package site.wangxin520.gof.singleton;

import java.util.ArrayList;

public class Triple {
    
    //建立一个静态的数组,用于保存创建的实例
    private static ArrayList<Triple> arr=new ArrayList<Triple>();
    
    //属性id
    private int id;
    
    //私有化构造函数
    private Triple(){}
    
    //通过id去获取对应的实例
    public static Triple getInstance(int id){
        try{
            //尝试从静态数组中获取,这里采用的是try catch接异常的方法
            Triple triple = arr.get(id);
            //如果数组中存在所需要的,那么就直接返回,否则抛异常
            return triple;
        }catch(Exception e){
            //调用getInstance()方法进行操作
            return getInstance();
        }
    }
    
    //没有参数,就不会造成异常的产生
    public static Triple getInstance(){
        //判断是否创建超过了3
        if(arr.size()<3){
            Triple t=new Triple();
            t.id=arr.size();
            arr.add(t);
            return t;
        }else{
            //如果创建超过了3个,那么就返回第一个实例s
           return getInstance(0);
        }
    }
    
}
  • 测试类
package site.wangxin520.gof.singleton;

public class TripleTest {
    public static void main(String[] args) {
        
        Triple t1 = Triple.getInstance();
        Triple t2 = Triple.getInstance();
        Triple t3 = Triple.getInstance();
        Triple t4 = Triple.getInstance();
        
        System.out.println(t1==t2);
        System.out.println(t1==t3);
        System.out.println(t1==t4);
        System.out.println(t2==t3);
        System.out.println(t2==t4);
        System.out.println(t3==t4);
        
    }
}
  • 结果

image

可见t1和t4是相同的,因为超过三个了,就直接返回第一个,getInstance()方法正常

  • 测试2
package site.wangxin520.gof.singleton;

public class TripleTest {
    public static void main(String[] args) {
        Triple t1 = Triple.getInstance(0);
        Triple t2 = Triple.getInstance(1);
        Triple t3 = Triple.getInstance(2);
        Triple t4 = Triple.getInstance(3);
        System.out.println(t1==t2);
        System.out.println(t1==t3);
        System.out.println(t1==t4);
        System.out.println(t2==t3);
        System.out.println(t2==t4);
        System.out.println(t3==t4);
        
    }
}
  • 结果

image

同样的,当想要获取编号不在0,1,2三个里面的话,就会返回第0个,所以t4和t1是相同的。

posted on 2017-09-28 20:31  博客王大锤  阅读(278)  评论(0编辑  收藏  举报