你知道哪些设计模式
谈谈你知道的设计模式?手动实现单例模式,Spring 框架中使用了哪些设计模式?
设计模式分类
大致按照模式的应用目标分类,设计模式可以分为创建型模式、结构型模式和行为型模式。
创建型模式
创建型模式是对对象创建过程的各种问题和解决方案的总结,包括各种工厂模式(Factσry、 Abstract factory)、单例模式(siη geton、构建器模式( Builder) 原型模式(ProtoType)
结构型模式
结构型模式是针对软件设计结构的总结,关注于类、对象继承、组合方式的实践经验。常见的结构型模式,包括桥接模式( Bridge)、适配器模式( Adapter)、装饰者模式 ( Decorator)、代理模式( Proxy)、组合模式( Composite)、外观模式( Facade)、享元模式( Flyweight)等。
行为型模式
行为型模式是从类或对象之间交互、职责划分等角度总结的模式。比较常见的行为型模式有策略模式( stratτegγ)、解释器模式( Interpreter)、命令模式( Commaηd观察者模式( observer)、迭代器模式( (Iterator)、模板方法模式( Template Method)、访问者模式( Visitor)。分析这个问题主要是考察你对设计模式的了解和掌握程度,更多相关内容你可以参考:
举例说明--装饰器模式
装饰器模式本质上是包装同类型实例,我们对目标对象的调用,往往会通过包装类覆盖过的方法,调用被包装的实例,这就可以很自然地实现增加额外逻辑的目的,也就是所谓的装饰"。
装饰器模式的 UML 类图
- Component:接口,定义一个抽象接口,真实对象和装饰对象具有相同的接口,以便动态的添加职责。
- Concrete Component:具体的对象
- Decorator:装饰类,继承了Component从外类来扩展 Component类的功能,并且持有-个构建引用,进行请求转发
- Concrete Decorator:具体装饰类,用于给实际对象添加职责。
以 IO 框架说明 装饰器模式
BufferedInputstream经过包装,为输入流过程增加缓存,类似这种装饰器还可以多断地增加不同层次的功能
public BufferedInputstream(Inputstream in)
以 Log 为例 说明 创建者模式
创建型模式尤其是工厂模式,在我们的代码中随处可见,比如 Log4j2 中日志打印过程,就是典型的构建器模式(Builder),通常会被实现成 fluent风柊的API,也有人叫它方法链。
Log.newLog(false).keyword(null, null).keyword(map).keyword("key1", "val2").add("a").getMessage()
单例模式
实现一个日常非常熟悉的单例设计模式。看起来似乎很简单,那么下面这个样例符合基本需求吗?
public class Singleton { private static Singleton instance = new Singleton(); public static Singleton getInstance(){ return instance; } }
这样的实现有什么问题?可以完全不需要 getInstance() 声明出一个对象,完全可以使用 new Singleton() 方式 声明出一个对象。上面的这个方式,并不能保证单例。 那怎么办,为了避免声明出多个对象,可以声明一个 private 的构造函数。
public class Singleton { private static Singleton instance = new Singleton(); private Singleton() { } public static Singleton getInstance(){ if (instance == null){ instance = new Singleton(); } return instance; } }
上面的实现是否有问题呢?我们考虑一个并发的场景,多个线程在判断 instance = null 时,就会出现多个 Singleton 实例,并发场景也不能保证单例。怎么办呢,采用“双检锁”。
- 这里的 volatile能够提供可见性,以及保证 getinstance返回的是初始化完全的对象。
- 在同步之前进行nu检查,以尽量避免进入相对昂贵的同步块
- 直接在cass级别进行同步,保证线程安全的类方法调用。
public class Singleton { private static volatile Singleton instance = new Singleton(); private Singleton() { } public static Singleton getInstance(){ if (instance == null){// 避免重复进入同步块 synchronized(Singleton.class){ if(instance == null){ instance = new Singleton(); } } } return instance; } }
这里说下 Java 核心类库的单例实现 java.lang.Runntime
private static final Runtime currentRuntime = new Runtime(); private static Version version; public static Runtime getRuntime() { return currentRuntime; } private Runtime() {}
- 并没有使用 “双检锁”
- 静态变量被声明final ,保证了实例不被篡改,也有有限的保证执行顺序的语义。
当然还有一种,使用静态内部类的方式实现单例模式,写法比较晦涩。
public class singleton { private Singleton(){} public static singleton getsingleton(){ return Holder.singleton } private static class Holder { private Static Singleton singleton new Singleton(); }
Spring 中使用了哪些设计模式
- BeanFactory和 Application Context应用了工厂模式。
- 在Bean的创建中, Spring也为不同 scope定义的对象,提供了单例和原型等模式实现。
- AOP领域则是使用了代理模式、装饰器模式、适配器模式等。
- 各种事件监听器,是观察者模式的典型应用。
- 类似 JdbcTemplate等则是应用了模板模式。