单例模式--投篮时最好保持一种姿势

来源:互联网 发布:电视剧大全软件 编辑:程序博客网 时间:2024/06/11 18:46

1)概述
单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例,提供一个访问它的全局访问点。核心是创建私有的构造函数。可拓展到有限个实例。
相似情形
1.家兴作为一个资深野球场上的投手,球场全场无死角,投篮技术可是真的很牛逼呀,但是细看他的投篮姿势都是一种,无论在哪一个角度都是一样。下面个人去分析一下家兴的投篮姿势,投篮可是千变万化,每一个位置、高度,加速度都是不一样的,但是家兴很聪明知道以一种投篮方式去实现,这样对他的投篮影响也是最小。因为无论外界因素怎么变,家兴只需要调控力度,和弧度就能完成每一个漂亮的投篮。
2.现在计划生育已经放松了,以前实行计划生育一个家庭只能生育一个孩子,把责任交给家庭,让家庭去执行,无论外界什么要求,只能生一个。

2)问题
1.对于某一些要求,我们只要求一个对象,任何需要来调用允许一个唯一对象,但是每次实例化都会产生新的对象,应该怎么去实现?

3)解决方案
通过建立私有的构造函数,不让外界初始化,定义唯一的私有静态初始化变对象,创建一个公共方法获取已经初始化的唯一静态的对象。

4)使用场景
对于哪些只要求产生一个对象,不允许再产生其它的对象。

5)结构
Singleton:单例类,通过使用private的构造函数,确保了在一个应用中只产生一个实例,并且是自行实例化。
Client:客户端类,通过调用Singleton类的公共方法来获取唯一实例化对象。

6)单例模式XML图
这里写图片描述

7)代码实现

public class Singleton {    private static Singleton singleton;    private Singleton(){    }    public static Singleton getSingleton(){        if(singleton==null){            singleton =  new Singleton();        }        return singleton;    }    public static void operation(){        System.out.println(singleton);    }}public class Client {    public static void main(String[] args) {        // TODO Auto-generated method stub        Singleton singleton = Singleton.getSingleton();        Singleton singleton1 = Singleton.getSingleton();        singleton.operation();        singleton1.operation();    }}

程序执行结果
com.yatming.singleton.Singleton@3a18cecd
com.yatming.singleton.Singleton@3a18cecd

8)单例模式的优点
1.保证唯一的实例
2.由于是因为Singleton类封装它的唯一实例,这样它可以严格地控制客户怎样访问它。

9)针对多线程时的单例
问题:java多线程的情况下,对于同时访问Singleton类的时候可能getSingleton方法的时候存在创建多个实例,对于这种情况该怎么去解决呢?
解决办法,对于当前线程进行锁定,让后来的的线程在外面等待,直到该实例已经被建立好
用synchronized关键子对getSingleton锁定,只有当前线程执行完毕后,下一个线程才能执行调用

但是同步getSingleton的做法可是会拖垮性能,该怎么去处理?
1.如果你的程序允许你忽略getSingleton()造成性能的负担,你可以不用理会这件事。但是你要考虑到这样一个问题,同步一个方法可能会造成程序执行效率降低100倍。特别是getSingleton方法如果在频繁使用,你就要很重视去看待这样一个问题。
2.如果应用程序总是创建并使用单件案例,或者在创建和运行时方面的负担不太繁重,你可能想要迫切创建此单件,如下所示:

private static Singleton singleton = new Singleton ();public static Singleton getSingleton(){    return singleton;}

利用这个做法我们依赖JVM在加载这个类时马上创建此唯一的单件案例。JVM保证在任何线程访问singleton静态变量,一定会先创建此实例。
那么如果这样一个实例一直没有被使用,创建一个实例会占用空间,该怎么去完善呢?
3.如果在调用getSingleton方法的时候,首先检查是否实例化,如果还没有创建,我们才去让它实现同步。这样一来,这是满足我们的效果。

public class Singleton(){    private volatitle static Singleton singleton;    private Singleton(){    }    public static Singleton getSingleton(){        if(singleton == null){            sysnchronized (Singleton.class){                if(singleton==null){                    singleton = new Singleton();                }            }        }        return singleton;}}

这个方法就是双重检查加锁(double-check locking)

还有一个问题的是:
如果程序有两个类加载器,就可能各自创建自己的单件实例;这是一般采取的解决办法是自行指定一个类加载器,并指定同一个类加载器。

1 0
原创粉丝点击