面试必问:设计模式篇
面试必问:设计模式篇
1. 单例模式
保证系统中一类只有一个实例并且提供对外访问。其优点是:由于在系统内存中只存在一个对象,故可以节约系统资源,对于一些需要频繁创建和销毁的对象,单例模式无疑可以提高系统的性能;其缺点是:由于单例模式中没有抽象层,因此单例类的扩展有很大的困难。多用于web应用设计以及各种池的设计。实现要点是:构造函数私有化,类定义中含有一个该类的静态私有对象,以及一个暴露单例的静态方法。
1)饿汉模式
将对象放在类成员变量中,这样就可以在类加载时初始化实例。
优点:线程安全(jvm保证在多个线程想要加载类时,只有一个线程能加载,其它线程需要等待)。
缺点:创建一些暂时不需要使用的单例,耗费资源,降低启动速度。
2)懒汉模式
将创建的工作放在暴露方法中。
优点:延迟加载,资源利用率高。
缺点:线程不安全。
3)双重检测锁
为了实现线程安全可采用如下方式:
上述方案是线程安全,但是如果getInstance()方法被多个线程频繁的调用,会造成大量的锁争用而阻塞,将会导致程序执行性能的下降。反之,如果getInstance()方法不会被多个线程频繁的调用,那么这个延迟初始化方案将能提供令人满意的性能。改进方案为双重检测锁机制,即在创建实例的时候加锁。
4)静态内部类实现
当多个线程同时初始化同一类或接口时会有初始化锁与之对应,因此最后只会有一个线程执行初始化操作,其它线程则等待。
优点:线程安全,延迟加载(兼顾高效并发和延迟加载的特点)
缺点:无
5)枚举方式
class Resource{ }
public enum SomeThing {
INSTANCE;
private Resource instance;
SomeThing() {
instance = new Resource();
}
public Resource getInstance() { return instance; }
}
enum类似class
优点:实现简单,避免反射和反序列化的漏洞。
缺点:无。
2. 工厂模式
将对象的创建统一管理,同时屏蔽创建类的复杂过程的一种设计方法。
1)简单工厂模式
通过传入参数的不同,返回不同的实例;
优点:简单
缺点:不易扩展,如果增加类,则要修改factory。
2)工厂方法模式
如图所示:为每一个类均创建一个工厂,如果要使用某个car,则调用具体的car的factory即可。
优点:可扩展(增加类和factory即可)。
缺点:程序变复杂。
简单工厂模式与工厂方法模式对比?
1)简单工厂模式结构、代码更简单,客户端编程也简单(工厂方法模式需要知道各种工厂类)。
2)工厂方法模式符合设计模式,易于扩展
一般使用简单工厂模式。
3)抽象工厂模式(属于设计模式)
抽象工厂方式用来生成不同产品族(所谓产品族是指一系列产品组成的集合,如热带工厂)的全部产品
优点:保证客户端始终只使用同一个产品族中的对象,方便扩展产品族(非产品)
缺点:不易修改产品族类内容(如在产品族中新增一个产品),同时类的结构变得复杂
3.责任链模式
请求在一系列处理对象之间传递,直到某个对象决定处理此请求。每个具体的处理器均有处理程序以及指向下一个处理器的指针,处理器顺序的维护在client中或者配置文件中定义。
优点:
- 客户端和处理程序松耦合
客户端只需要提交处理请求即可,并不需要关心如何来处理请求,在职责链模式中,请求者并不知道接收者是谁,也不知道具体如何处理,请求者只是负责向职责链发送请求就可以了。而每个职责对象也不用管请求者或者是其他的职责对象,只负责处理自己的部分,其他的就交给其他的职责对象去处理。也就是说,请求者和接受者是完全解耦的。
- 动态组合职责
职责链模式会把功能处理分散到单独的职责对象中,然后再使用的时候,可以动态组合职责形成职责链,从而可以灵活地给对象分配职责,也可以灵活地实现和改变对象的职责。
应用场景
1)java的异常处理机制。一个try可以对应多个catch,从上外下依次来匹配exception
2 ) servlet的过滤器机制
3)springmvc的拦截器机制
4.观察者模式
让多个观察者对象同时监听某一个主题对象**。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己****,核心在于被观察者中维护一个观察者的链表,如果被观察者对象有变化就会遍历这个链表通知观察者。因此核心在于两个角色:观察者与被观察者。**
优点: Subject和Observer之间是松偶合的。缺点:如果Observer过多,Subject通知时会花费大量时间。
5. 装饰模式
动态的给对象添加新功能,核心:被装饰者(基类)、装饰者接口、用来装饰的具体类。