单例模式

单例模式:

    理解:就是整个类中只有一个实例,并提供它的一个全局静态访问点。

    方式:一个办法就是将构造函数变为私有的(至少是受保护的),使得外面的类不能通过引用来产生对象。

    分类:单例模式可分为有状态的和无状态的。有状态的单例对象一般也是可变的单例对象,多个单态对象在一起就可以作为一个状态仓库一样向外提供服务。没有状态的单例对象也就是不变单例对象,仅用做提供工具函数。

实现:

     1) 饿汉式:

package 单实例模式;

 

public class A {

 

private static A a = new A();

 

/**

 * 构造私有的构造方法

 */

private A(){

 

}

 

/**

 * 得到类A的实例

 */

public static A getInstance(){

return a;

}

 

}

               2)懒模式:

package 单实例模式;

 

public class B {

 

private static B instance = null;

 

/**

 * 构造私有的构造方法

 */

private B(){

 

}

 

/**

 * 得到类A的实例

 */

public static synchronized B getInstance(){

ifinstance == null ){

instance = new B();

}

return instance;

}

 

}

              3)注册表方式:

package 单实例模式;

 

import java.util.HashMap;

 

/**

 * 注册表方式

 * @author Administrator

 *

 */

public class C {

 

//构建一个注册表

private static HashMap<String, Object> instance_HashMap = new HashMap<String, Object>();

 

protected C(){

 

}

 

/**

 * 得到一个实例

 * @param name 类名

 * @return

 */

public static Object getInstance(String name){

 

if(name == null){

name = "Singleton";

}

 

if(instance_HashMap.get(name)==null){

try {

instance_HashMap.put(name, Class.forName(name).newInstance());

catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

 

return instance_HashMap.get(name);

 

}

package 单实例模式;

 

public class D extends C{

 

/**

 * 因为子类的构造方法不能比父类的构造方法的范围小

 */

public D(){

 

}

 

public static void main(String[] args) {

//得到子类的一个实例,要添加包名

d = (D)C.getInstance("单实例模式.D");

}

 

}

 

}

       分析:首先前两种方式的构造函数都是私有的,彻底断开了使用构造函数来得到类的实例的通道,但是这样也使得类失去了多态性(大概这就是为什么有人将这种模式称作单态模式)。

       在第二种方式中,对静态工厂方法进行了同步处理,原因很明显——为了防止多线程环境中产生多个实例;而在第一种方式中则不存在这种情况。

       在第二种方式中将类对自己的实例化延迟到第一次被引用的时候。而在第一种方式中则是在类被加载的时候实例化,这样多次加载会照成多次实例化。但是第二种方式由于使用了同步处理,在反应速度上要比第一种慢一些。

  在第三种方式中由于在 java 中子类的构造函数的范围不能比父类的小,所以可能存在不守规则的客户程序使用其构造函数来产生实例,造成单例模式失效。

弊端:

1)多个虚拟机:在不同虚拟机上,各个单例对象保存的状态很可能是不一样的。

2)多个类加载器:当存在多个类加载器加载类的时候,即使它们加载的是相同包名,相同类名甚至每个字节都完全相同的类,也会被区别对待的。因为不同的类加载器会使用不同的命名空间(namespace)来区分同一个类。因此,单例类在多加载器的环境下会产生多个单例对象。

3)错误的同步处理:在使用懒汉式单例模式时,同步处理的恰当与否也是至关重要的。不然可能会达不到得到单个对象的效果,还可能引发死锁等错误。

4)子类破坏了对象控制:在使用注册表的单实例模式中有所体现。

5)串行化(可序列化):为了使一个单例类变成可串行化的,仅仅在声明中添加“implements Serializable”是不够的。因为一个串行化的对象在每次返串行化的时候,都会创建一个新的对象,而不仅仅是一个对原有对象的引用。为了防止这种情况,可以在单例类中加入 readResolve 方法。

 

 

 

 

    

 

<!--EndFragment-->
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值