设计模式之单例模式

定义
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
结构和说明
Singleton负责创建Singleton类自己的唯一实例,并且提供一个getInstance的方法,为外部提供一个访问全局访问点。
    //懒汉式实现
public class Singleton {
    //定义一个变量来存储创建好的实例
    //因为变量在静态方法中使用 所以使用static
    private static Singleton uniqueInstance = null;
    //构造器私有化
    private Singleton(){}
    //提供一个方法来为客户端提供类实例并且定义类方法,也要加static
    public static synchronized getInstance(){
        //是否实例存在
        if (uniqueInstance == null){
        //不存在实例化
        uniqueInstance = new Singleton();
    }
    return uniqueInstance;
}   
//时间上:(以时间换空间)
//线程安全:一般不加synchronized,严重影响性能 线程不安全
}

//饿汉式实现
public class Singleton{
    //定义一个静态变量来存储创建好的实例
    //类装载时候初始化,由虚拟机来保证只会创建一次
    private static Singleton instance = new Singleton();
    //构造器私有化
    private Singleton(){}
    //定义一个方法为客户端提供实例并且定义类方法,也要加static
    public static Singleton getInstance(){
    return instance;
    }
    //时间上去看:(以空间换时间)
    //线程安全 :线程安全
}
理解单例模式
a.读取配置文件(应用)
读取配置文件一般使用单例模式,只初始化一次文件配置。
b.单例模式的功能
单例模式的功能是用来保证这个类在运行期间只被创建一个实例,并且提供一个全局唯一访问这个实例的访问点。
单例模式的范围是个一个ClassLoader及其子ClassLoader范围。
c.延迟加载的思想
延迟加载,就是一开始不要加载资源或者数据,一直等到马上就要使用这个资源或数据躲不过了才加载Lazy Load,延迟加载,在实际开发中是一种很常见的思想,尽可能的节省资源。懒汉式单例getInstance()方法判断实例是否存在,是否需初始化。
d. 缓存思想
单例模式懒汉式实现体现了缓存思想,缓存也是实际开发中非常常见的功能,缓存是一种典型的空间换取时间的方案。
public class JavaCache{
    private Map<String,Object> map = new HashMap<>();
    public Object getValue(String key){
        Object obj = map.get(key)
        if (obj == null){
            obj = key +",value"
            map.put(key,obj);
        }
        return obj;
    }
    //1.定义一个缓存数据容器
    //2.从缓存中获取数据
    //2.1从缓存中取值
    //2.2判断缓存中是否有值
    //2.3如果有值,就直接使用这个值
    //2.4如果没有,那么去获取响应数据,或者创建相应的对象
    //2.4.1把新值放入缓存中
}
  • 使用缓存实现单例模式
public class Singleton{
        private final static String DEFAULT_KEY = "singleton"
        private static Map<String,Singleton> map = new HashMap<>();
        private Singleton(){}
        public static Singleton getInstance(){
            Singleton instance = (Singleton) map.get(DEFAULT_KEY)
            if (instance == null) {
                instance = new Singleton();
                map.put(DEFAULT_KEY,instance);
            }
            return instance;
        }
    }
  • 单例模式的优缺点

    • 时间和空间:懒汉式是典型的时间换取空间,饿汉式是典型的空间换取时间。
    • 线程安全:不加同步 的懒汉式是线程不安全的。饿汉式是线程安全的。因为虚拟机保证只会加载一次。懒汉式线程安全:加上synchronized即可。
  • 双重检查

public class Singleton{
    //volatile 修饰的变量线程共享
    private volatile static Singleton instance = null;
    private Singleton(){}
    public static Singleton getInstance(){
        if (instance == null){
            synchronized(Single.class){
                if (instance == null){
                    instance = new Singleton();
                }
            }
        }
    }   
}
  • java一种更好的单例实现方式
public class Singleton{
    //类级的内部类,也就是静态的成员内部类,该内部类实例与外部类实例没有绑定关系,而且只有被调到才会装载,从而实现延迟加载
    private static class SingletonHolder{
        //静态初始化,由jvm来保证线程安全
        private static Singleton instance = new Singleton();
    }
    private Singleton(){
    }
    public static Singleton getInstance(){
        return SingletonHolder.instance;
    }
}
  • 单例和枚举
    使用枚举来实现单例的实例
public enum Singleton{
    //定义一个枚举的元素,它就代表了Singleton的实例
    uniqueInstance;
    public void SingletonOperation(){
    //自身功能处理
    }
}
单例模式的本质
控制实例数目 如何实现实例数目?比如说控制实例数目3个?
public class OneExtend{
            private final static String DEFAULT_PREKEY = "Cache"//缓存实例容器
            private static Map<String,OneExtend> map = new HashMap<>();
            //用来记录当前正在使用第几个实例,到了控制的最大数目,那就返回从1开始
            private static int num =1 ;
            //定义控制实例的最大数目
            private static int NUM_MAX = 3;
            private OneExtend(){}
            public static OneExtend getInstance(){
                String key = DEFAULT_PREKEY + num;
                OneExtend oneExtend = map.get(key);
                if (oneExtend == null){
                    oneExtend = new OneExtend();
                    map.put(key,oneExtend);
                    num++;
                    if (num > NUM_MAX){
                    //若果实例序号已经达到最大数目了那么重1开始
                    num = 1
                }
                return oneExtend;
            }
        }   
        public static void main(String[] args){
            OneExtend t1 = getInstance();
            OneExtend t2 = getInstance();
            OneExtend t3 = getInstance();
            OneExtend t4 = getInstance();
            OneExtend t5 = getInstance();
            OneExtend t6 = getInstance();
            System.out.println("t1="+t1);
            System.out.println("t2="+t2);
            System.out.println("t3="+t3);
            System.out.println("t4="+t4);
            System.out.println("t5="+t5);
            System.out.println("t6="+t6);
        }
    }
何时选用单例模式
当需要控制一个类的实例只能有一个,而且客户只能从一个全局访问点访问它时,可以选用单例模式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值