Android的开发之&java23中设计模式------>单例模式

单例对象(SingletonMethod)是一种常用的设计模式。单例对象能保证在一个JVM中,该对象只有一个实例存在。
 * 这样的模式有几个好处:
 1、某些类创建比较频繁,对于一些大型的对象,这是一笔很大的系统开销。
 2、省去了new操作符,降低了系统内存的使用频率,减轻GC压力。
 3、有些类如交易所的核心交易引擎,控制着交易流程,如果该类可以创建多个的话,系统完全乱了。
 (比如一个军队出现了多个司令员同时指挥,肯定会乱成一团),所以只有使用单例模式,才能保证核心交易服务器独立控制整个流程。
主要缺点:
 1、由于单利模式中没有抽象层,因此单例类的扩展有很大的困难。
 2、单例类的职责过重,在一定程度上违背了“单一职责原则”。
 3、滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;
 如果实例化的对象长时间不被利用,系统会认为是垃圾而被回收,这将导致对象状态的丢失。


一:
/**
 * Created by Administrator on 2017-8-23.
 * 懒汉式,线程不安全
 * 这种写法lazy loading很明显,但是致命的是在多线程不能正常工作。
 */
public class SingletonMethod {
    /**
     * 持有私有静态实例,防止被引用,此处赋值为null,
     * 目的是实现延迟加载
     */
    private static SingletonMethod instance=null;


    /**
     * 私有构造方法,防止被实例化
     */
    private SingletonMethod(){}


    /**
     * 静态工程方法,创建实例
     */
    public static SingletonMethod getInstance(){
        if (instance==null){
            instance=new SingletonMethod();
        }
        return instance;
    }
}


二:
/**
 * Created by Administrator on 2017-8-23.
 * 懒汉式,线程安全
 *  这种写法能够在多线程中很好的工作,而且看起来它也具备很好的lazy loading,但是,遗憾的是,效率很低,99%情况下不需要同步。
 */
public class SingletonMethod2 {
    private static SingletonMethod2 instance;
    private SingletonMethod2(){}


    public static synchronized SingletonMethod2 getInstance(){
        if (instance==null){
            instance=new SingletonMethod2();
        }
        return instance;
    }
}


三:
/**
 * Created by Administrator on 2017-8-23.
 * 饿汉式
 * 这种方式基于classloder机制避免了多线程的同步问题,不过,instance在类装载时就实例化,
 * 虽然导致类装载的原因有很多种,在单例模式中大多数都是调用getInstance方法,
 * 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,
 * 这时候初始化instance显然没有达到lazy loading的效果。
 */
public class SingletonMethod3 {
    private static SingletonMethod3 instance=new SingletonMethod3();
    private SingletonMethod3(){}


    public static SingletonMethod3 getInstance(){
        return instance;
    }
}


四:
/**
 * Created by Administrator on 2017-8-23.
 * 饿汉,变种
 * 基于静态 代码块,在实例化或者第一次调用时执行
 * 既可以延迟加载,又线程安全
 */
public class SingletonMethod4 {
    private static SingletonMethod4 instance=null;
    static {
        instance=new SingletonMethod4();
    }
    
    private SingletonMethod4(){}
    
    public static SingletonMethod4 getInstance(){
        return instance;
    }
}


五:
/**
 * Created by Administrator on 2017-8-23.
 * 静态内部类
 */
public class SingletonMethod5 {
    /**
     * 这种方式同样利用了classloder的机制来保证初始化instance时只有一个线程,
     * 它跟第三种和第四种方式不同的是(很细微的差别):第三种和第四种方式是只要Singleton类被装载了,那么instance就会被实例化(没有达到lazy loading效果),
     * 而这种方式是Singleton类被装载了,instance不一定被初始化。因为SingletonHolder类没有被主动使用,只有显示通过调用getInstance方法时,才会显示装载SingletonHolder类,
     * 从而实例化instance。想象一下,如果实例化instance很消耗资源,我想让他延迟加载,
     * 另外一方面,我不希望在Singleton类加载时就实例化,因为我不能确保Singleton类还可能在其他的地方被主动使用从而被加载,
     * 那么这个时候实例化instance显然是不合适的。这个时候,这种方式相比第三和第四种方式就显得很合理。


     * 恶汉模式的优化版,在类被装载时,静态内部类并没有被实例化,
     * 只有getInstance()时才 会装载 SingletonHolder 类,静态内部类方式也能很好地,实现线程安全、高效率和延迟加载特性。
     */
    private static class SingletonHolder{
        private static final SingletonMethod5 instance=new SingletonMethod5();
    }


    private SingletonMethod5(){}


    public static final SingletonMethod5 getInstance(){
        return SingletonHolder.instance;
    }
}
六:
/**
 * Created by Administrator on 2017-8-23.
 * 枚举
 *  这种方式是Effective Java作者Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象,可谓是很坚强的壁垒啊,
 *  不过,个人认为由于1.5中才加入enum特性,用这种方式写不免让人感觉生疏,在实际工作中,我也很少看见有人这么写过。
 */
public enum SingletonMethod6 {
    SINGLETON;
}


七:
/**
 * Created by Administrator on 2017-8-23.
 * (双重校验锁):
 * 懒汉模式的优化版,拥有线程安全、高效率以及延迟加载等特性。
 * 但是这种方式需要jdk1.5以上,且在一些平台和编译器下有错。
 */
public class SingletonMethod7 {
    private volatile static SingletonMethod7 singleton;


    private SingletonMethod7(){}


    public static SingletonMethod7 getSingleton(){
        if (singleton==null){
            synchronized (SingletonMethod7.class){
                if (singleton==null){
                    singleton=new SingletonMethod7();
                }
            }
        }
        return singleton;
    }
}
/**
 * 总结:
 * 1、单例模式理解起来简单,但是具体实现起来还是有一定的难度。
 * 2、synchronized关键字锁定的是对象,在用的时候,一定要在恰当的地方使用(注意需要使用锁的对象和过程,可能有的时候并不是整个对象及整个过程都需要锁)。


 * 采用类的静态方法,实现单例模式的效果,也是可行的,此处二者有什么不同?
 首先,静态类不能实现接口(从类的角度说是可以的,但是那样就破坏了静态了。因为接口中不允许有static修饰的方法,所以即使实现了也是非静态的)
 其次,单例可以被延迟初始化,静态类一般在第一次加载是初始化。之所以延迟加载,是因为有些类比较庞大,所以延迟加载有助于提升性能。
 再次,单例类可以被继承,他的方法可以被覆写。但是静态类内部方法都是static,无法被覆写。
 单例类比较灵活,毕竟从实现上只是一个普通的Java类,只要满足单例的基本需求,你可以在里面随心所欲的实现一些其它功能,
 但是静态类不行。从上面这些概括中,基本可以看出二者的区别,


 但是,从另一方面讲,我们上面最后实现的那个单例模式,内部就是用一个静态类来实现的,
 所以,二者有很大的关联,只是我们考虑问题的层面不同罢了。
 两种思想的结合,才能造就出完美的解决方案,就像HashMap采用数组+链表来实现一样,其实生活中很多事情都是这样,
 单用不同的方法来处理问题,总是有优点也有缺点,
 最完美的方法是,结合各个方法的优点,才能最好的解决问题!
 */


github地址:https://github.com/zyj18410105150/DesignMode


最后感谢下:cantellow作者,http://cantellow.iteye.com/blog/838473

猜你喜欢

转载自blog.csdn.net/jie1123161402/article/details/78423752