设计模式(一):单例模式 java实现

参考:http://blog.csdn.net/jason0539/article/details/23297037/

单例模式:指的是一个类只有一个实例对象。它的设计是为了实现类的单一功能。专注于自己的事情。

有如下三个特点:

  1. 单例类只有一个实例
  2. 单例类必须自己创建这一个实例
  3. 单例类必须将自己的这个实例提供给其他对象

因此我们在实现单例类的时候要注意一下几点:

  1. 首先禁止他人创建实例对象,故它的构造函数必须是私有的;
  2. 其次自己创建实例要在类加载时创建,故必须有一个静态的实例对象的成员变量;
  3. 要给他人提供实例,故要有一个获取该方法的公有成员方法。

常见的单例模式的实现有5中方法

  1. 懒汉式:需要时创建实例,线程不安全
  2. 饿汉式:类加载时就创建,线程不安全
  3. 使用同步方法的懒汉式
  4. 使用双重检查加锁的懒汉式
  5. 使用静态内部类的懒汉式(这个比较推荐)

下面将一一实现:

一、懒汉式

public class Singleton1 {

    private Singleton1(){

    }
    private static Singleton1 instance = null;

    //测试方法
    public void sayHello(String name){
        System.out.println("Hello, " + name);
    }
    /**
     * 线程不安全的写法
     * @return
     */
    public static Singleton1 getInstance(){
        if(instance == null){
            instance = new Singleton1();
        }

        return instance;
    }
}

测试:

public class TestSingleton1 {


    public static void main(String[] args){

        Singleton1 ins = Singleton1.getInstance();

        ins.sayHello("Mike");

        Singleton1 ins2 = Singleton1.getInstance();

        ins2.sayHello("Mike");

        if(ins == ins2){
            System.out.println("同一个实例");
        }else{
            System.out.println("不同的实例");
        }

}

二、饿汉式

public class Singleton2 {

    private Singleton2(){

    }

    private static Singleton2 instance = new Singleton2();

    private static Singleton2 getInstance(){
        return instance;
    }
}

三、懒汉式+同步机制

public class Singleton1 {

    private Singleton1(){

    }
    private static Singleton1 instance = null;

    //测试方法
    public void sayHello(String name){
        System.out.println("Hello, " + name);
    }
    public static synchronized Singleton1 getInstance(){
        if(instance == null){
            instance = new Singleton1();
        }

        return instance;
    }
}

四、懒汉式+双重检查锁定

public class Singleton1 {

    private Singleton1(){

    }
    private static Singleton1 instance = null;

    //测试方法
    public void sayHello(String name){
        System.out.println("Hello, " + name);
    }
    public static Singleton1 getInstance(){
        if(instance == null){

            synchronized(Singleton1.class){
                if(instance == null){
                    instance = new Singleton1();
                }
            }
        }

        return instance;
    }
}

五、懒汉式+静态内部类

public class Singleton1 {

    private Singleton1(){

    }
    private static Singleton1 instance = null;

    //测试方法
    public void sayHello(String name){
        System.out.println("Hello, " + name);
    }
    private static class LazyHolder{
        private static final Singleton1 INSTANCE = new Singleton1();
    }
    public static Singleton1 getInstance(){
        return LazyHolder.INSTANCE;
    }
}

六、登记式单例类

package designpattern.singleton;

import java.util.HashMap;
import java.util.Map;


/**
 * 登记式单例模式
 * @author wenbaoli
 *
 */
public class Singleton3 {

    private static Map<String, Singleton3> map = new HashMap<String, Singleton3>();

    static{
        Singleton3 single = new Singleton3();
        map.put(single.getClass().getName(), single);

    }

    //保护的默认构造子
    protected Singleton3(){}

    //静态工厂方法,返回此类唯一的实例
    public static Singleton3 getInstance(String name){
        if(name == null){
            name = Singleton3.class.getName();
            System.out.println("name == null" + "---> name = " + name);
        }

        if(map.get(name) == null){
            try{
                map.put(name, (Singleton3) Class.forName(name).newInstance());
            }catch(InstantiationException e){
                e.printStackTrace();
            }catch(IllegalAccessException e){
                e.printStackTrace();
            }catch(ClassNotFoundException e){
                e.printStackTrace();
            }
        }

        return map.get(name);
    }

    //一个示意性的商业方法
    public String about(){
        return "Hello, I am RegSingleton.";
    }

    public static void main(String[] args){
        Singleton3 single3 = Singleton3.getInstance(null);
        System.out.println(single3.about());
    }

}

测试:

public class TestSingleton3 {


    public static void main(String[] args){


        Singleton3 single1 = Singleton3.getInstance(null);

        System.out.println(single1.about());

        System.out.println("------------我是分割线----------");
        Singleton3 single2 = Singleton3.getInstance(single1.getClass().getName());

        System.out.println(single1.about());

        if(single1 == single2){
            System.out.println("他们是同一个实例");
        }else{
            System.out.println("他们是不同的实例");
        }
    }

}

附录:查漏补缺——代码中我不熟悉或不知道的事

  1. name = Singleton3.class.getName(); : 表示获取Singleton3这个类的名字。一个类的name是它所在的包名.类名
  2. (Singleton3) Class.forName(name).newInstance() : 表示去加载name(包名.类名)的下的这个类。。。

例如:给你一个字符串变量,它代表一个类的包名和类名,你怎么实例化它?只有你提到的这个方法了,不过要再加一点。 A a = (A)Class.forName(“pacage.A”).newInstance(); 这和你 A a = new A(); 是一样的效果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值