结合JDK谈谈了解的设计模式

单例模式:JDK的lang包中Runtime类的getRuntime()对Runtime实例的获取就是饿汉式单例的体现

抽象工厂:JDK的sql包中的Connection接口就将一个产品族的构建方法进行了统一定义

工厂方法:JDK的util包中的Collection接口中的iterator()方法就是一个工厂方法,使用这个方法来返回一个由子类实现的Iterator对象

建造者模式:JDK的lang包中的StringBuilder类

原型模式:JDK的lang包中Object的clone()方法,如果一个类的初始化要消耗较多资源或者new产生一个对象需要非常繁琐的过程,以及一个循环体中产生大量对象时就可以使用

适配器模式:javax.xml.bind.annotation.adapters.XMLAdapter

装饰者模式:比如BufferedInputStream(InputStream)继承了InputStream类,同时需要传入的参数也是InputStream类,通过DataInputStream这种继续在原有方法的基础上附加职责

代理模式:JDK中的lang.reflect包下的Proxy类,通过反射实现的动态代理

策略模式:JDK中util包下的Comparator接口就是一个实现策略模式的接口,在需要进行比较的时候实现对应的比较器,之后便会按照比较器对应的比较策略进行比较排序等等工作

观察者模式:JDK中Observable类和Observer接口就是实现这种模式的典型,通过继承Observable进行事件记录派发,实现Observer接口进行事件监听达到监听方法的目的

命令模式:JDK中的lang包下的Runnable接口

 

讲几个设计模式,哪些地方用到了,为什么要用 ?

单例模式:JDK中的getRuntime()

工厂方法模式:ThreadPoolExcutor用到ThreadFactory

观察者模式Java.util包下面的Observable和Observer

 

说一下单例模式和多例模式(也叫原型模式)的区别及联系

联系:

在GoF(Gang of four:四人组,23种设计模式的提出者)的23种设计模式中均是属于创建型模式,用于构建对象实例

同时为了让对象的具体实例化操作对用户不可见(即封装具体实例化细节),两种模式的构造方法不对外开放,均需要设置访问权限为private

区别:

首先是获取对象的方式不同,单例模式多次进行对象实例获取操作时,会返回同一个实例对象,而多例模式则会返回不同的对象实例

 

单例模式是如何实现线程安全的?

由于单例模式的实现有多种类型,因此分类讨论

首先是线程安全的懒汉式,可以通过使用synchronized关键字修饰静态的单例获取方法来对类进行加锁,保证线程安全,以及由它优化演进而来的双重校验锁,也能保证线程安全

然后是线程安全的饿汉式,可以在类的加载过程中进行单例对象的构建(具体的构建过程分别是:在链接的准备阶段进行内存分配,初始化阶段进行初始化赋值,这儿即是对象的真正实例化),后面获取的时候直接进行调用即可,保证线程安全

也可以通过静态内部类的方式,将线程安全交给虚拟机进行保证

最后可以通过枚举类来保证线程安全,底层实现依旧是和类似于饿汉式在类加载过程中实例化单例对象来保证线程安全的

 

有一个方法接收一个消息类型数据,通过if-else处理,如何优化?

可以结合工厂模式和策略模式来进行优化,将if-else中的业务代码抽象出一个策略接口,再通过这个策略接口将各类业务代码转化为对应的执行策略类,将用来判断的逻辑做为关键字,通过对应的策略工厂来构建对应的策略,最后执行策略即可。

 

对于单例模式,有什么使用场景?

比如JDK中的Runtime实例,就是通过饿汉式来实现的线程安全的单例模式。

Spring中的AbstractFactoryBean获取

分布式id生成器也是单例的。

网站的在线人数、文章阅读数的统计器。

 

除了单例模式,知道适配器模式怎么实现么?有什么用?

首先适配器要做的工作就是将一个被适配的接口或类转化为另一个类能够使用的接口

因此有两种方法可以实现这种工作:

第一种是通过继承实现的类适配模式,继承被适配的类,同时实现目标接口,实现目标接口方法,在该方法中执行被适配类的对应方法

第二种是通过组合实现的对象适配模式,直接在适配器中创建出被适配类的实例,实现目标接口,在目标接口中调用被适配类实例对象的对应方法

能提高类的透明性和复用,现有的类复用但不需要改变,提高目标类和适配器类解耦,提高程序扩展性,符合开闭原则