[关闭]
@lzb1096101803 2016-03-19T09:56:14.000000Z 字数 1994 阅读 557

单例,模板,观察者,策略模式

电话面试


策略模式

策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。

模板方法模式

java.util.Arrays sort(Object[] a)中,首先是数组的赋值,然后传入mergeSort开始排序,依赖于传入对象的compareTo方法,需要我们实现

观察者模式

单例模式的书写(3种)

Java中的应用: Spring中的上下文对象,java.lang.Runtime(第一种)

从速度和反应时间角度来讲,非延迟加载(又称饿汉式)好;从资源利用效率上说,延迟加载(又称懒汉式)好

第一种:

public class Dao{

    private static Dao dao = new Dao();
    private Dao(){};
    public  static getDaoInstance(){
        return dao;
    }   
}

第二种:

public class Dao{

    private static Dao dao;
    private Dao(){};
    public synchronized static getDaoInstance(){
        if(dao==null){
            dao = new Dao();
        }
        return dao;
    }   
}

第三种:
没有volatile修饰符,可能出现Java中的另一个线程看到个初始化了一半的_instance的情况,但使用了volatile变量后,就能保证先行发生关系(happens-before relationship)。对于volatile变量_instance,所有的写(write)都将先行发生于读(read),
在Java 5之前不是这样,所以在这之前使用双重检查锁有问题。现在,有了先行发生的保障(happens-before guarantee),你可以安全地假设其会工作良好。

public class Dao{

    private volatile Dao dao;
    private Dao(){};
    public static getDaoInstance(){
        if(dao==null){
            synchronized(Dao.class){
                if(dao==null){
                    dao = new Dao();
                }
            }

        }
        return dao;
    }   
}

第四种:使用枚举

1、 自由序列化;
2、 保证只有一个实例(即使使用反射机制也无法多次实例化一个枚举量);
3、 线程安全;

好处不外乎三点:1.线程安全 2.不会因为序列化而产生新实例
3.防止反射攻击

关于第二点序列化问题,有一篇文章说枚举类自己实现了readResolve()方法,所以抗序列化,这个方法是当前类自己实现的(解决)

关于第一点线程安全,从反编译后的类源码中可以看出也是通过类加载机制保证的,应该是这样吧(解决)

关于第三点反射攻击,我有自己试着反射攻击了以下,不过报错了...看了下方的反编译类源码,明白了,因为单例类的修饰是abstract的,所以没法实例化。(解决)

传统的单例模式的另外一个问题是一旦你实现了serializable接口,他们就不再是单例的了,因为readObject()方法总是返回一个 新的实例对象,就像java中的构造器一样。你可以使用readResolve()方法来避免这种情况,通过像下面的例子中这样用单例来替换新创建的实 例:

public enum SingletonEnum
{
    INSTANCE01,INSTANCE02;
    private String name;
    publicString getName()
    {
       returnname;
    }
     publicvoid setName(String name)
    {
       this.name = name;
    }
 }

测试

public class Test
{
    public static void main(String[] args)
    {
        SingletonEnum instance01=SingletonEnum.INSTANCE01;
        instance01.setName("terje");
        System.out.println(instance01.getName());

        SingletonEnum instance02=SingletonEnum.INSTANCE01;
        System.out.println(instance02.getName());

        SingletonEnum instance03=SingletonEnum.INSTANCE02;
        instance03.setName("liu");
        System.out.println(instance03.getName());

        SingletonEnum instance04=SingletonEnum.INSTANCE02;
        instance04.setName("liu");
        System.out.println(instance04.getName());

    }

}
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注