JAVA面试题-设计模式(七)

1. 说一下你熟悉的设计模式?

单例模式:保证被创建一次,节省系统开销。

工厂模式(简单工厂、抽象工厂):解耦代码。

观察者模式:定义了对象之间的一对多的依赖,这样一来,当一个对象改变时,它的所有的依赖者都会收到通知并自动更新。

外观模式:提供一个统一的接口,用来访问子系统中的一群接口,外观定义了一个高层的接口,让子系统更容易使用。

模版方法模式:定义了一个算法的骨架,而将一些步骤延迟到子类中,模版方法使得子类可以在不改变算法结构的情况下,重新定义算法的步骤。

状态模式:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。

2. 简单工厂和抽象工厂有什么区别?

简单工厂:用来生产同一等级结构中的任意产品,对于增加新的产品,无能为力。

工厂方法:用来生产同一等级结构中的固定产品,支持增加任意产品。

抽象工厂:用来生产不同产品族的全部产品,对于增加新的产品,无能为力;支持增加产品族。

 

3.懒汉和饿汉

在程序编写上,一般将单例模式分为两种,分别是饿汉式和懒汉式,

饿汉式:在类加载时就完成了初始化,所以类加载比较慢,但获取对象的速度快。

懒汉式:在类加载时不初始化,等到第一次被使用时才初始化

 

1、饿汉式 (可用)

public class  自己类名{

    private final static  自己类名 别名 = new 自己类名();
    //无参构造方法
    private 自己类名(){}

   public static 自己类名 get自己(){
        return 别名;
    }

 

2、普通的懒汉式 (线程不安全,不可用)

public class Singleton {

    private static Singleton instance = null;

    private Singleton() {
    }

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

}

这是懒汉式中最简单的一种写法,只有在方法第一次被访问时才会实例化,达到了懒加载的效果。但是这种写法有个致命的问题,就是多线程的安全问题。假设对象还没被实例化,然后有两个线程同时访问,那么就可能出现多次实例化的结果,所以这种写法不可采用。
 3、同步方法的懒汉式 (可用)

 

public class Singleton {

    private static Singleton instance = null;

    private Singleton() {
    }

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

}
这种写法是对getInstance()加了锁的处理,保证了同一时刻只能有一个线程访问并获得实例,但是缺点也很明显,因为synchronized是修饰整个方法,每个线程访问都要进行同步,而其实这个方法只执行一次实例化代码就够了,每次都同步方法显然效率低下,为了改进这种写法,就有了下面的双重检查懒汉式。
 

public class Singleton {

    private static volatile Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }

}
也就是Double-Check,并且同步的不是方法,而是代码块,效率较高,是对第三种写法的改进。为什么要做两次判断呢?这是为了线程安全考虑,还是那个场景,对象还没实例化,两个线程A和B同时访问静态方法并同时运行到第一个if判断语句,这时线程A先进入同步代码块中实例化对象,结束之后线程B也进入同步代码块,如果没有第二个if判断语句,那么线程B也同样会执行实例化对象的操作了。
 

5、静态内部类 (可用,推荐)

 

public class Singleton {

    private Singleton() {}

    private static class SingletonInstance {
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonInstance.INSTANCE;
    }

}

单例模式的优缺点
优点
单例类只有一个实例,节省了内存资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能;

单例模式可以在系统设置全局的访问点,优化和共享数据,例如前面说的Web应用的页面计数器就可以用单例模式实现计数值的保存。

缺点
单例模式一般没有接口,扩展的话除了修改代码基本上没有其他途径。
 单例模式

 

4.单例应用场景

1.Windows的任务管理器,只能打开一个任务管理器。

2.Windows系统的回收站。

3.网站的计数器,通过单例模式可以很好实现。

4.应用程序的日志应用,一般都何用单例模式实现,这是由于系统一般共用一个日志。

5.数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库资源。数据库软件系统中使用数据库连接池,主要是节省打开或者关闭数据库连接所引起的效率损耗,这种效率上的损耗还是非常昂贵的,因为何用单例模式来维护,就可以大大降低这种损耗。

6.多线程的线程池的设计一般也是采用单例模式,这是由于线程池要方便对池中的线程进行控制。

 5.未完待续。。。。。。。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值