开篇介绍
大家好,我是Java最全面试题库
的提裤姐
,今天这篇是Java设计模式,主要总结了设计模式相关的问题,在后续,会沿着第一篇开篇的知识线路一直总结下去,做到日更!如果我能做到百日百更,希望你也可以跟着百日百刷,一百天养成一个好习惯。
设计模式有哪些?
创建型
- 工厂模式与抽象工厂模式 (Factory Pattern)(Abstract Factory Pattern)
- 单例模式 (Singleton Pattern)
- 建造者模式 (Builder Pattern)
- 原型模式 (Prototype Pattern)
结构型
- 适配器模式 (Adapter Pattern)
- 装饰器模式 (Decorator Pattern)
- 桥接模式 (Bridge Pattern)
- 外观模式 (Facade Pattern)
- 代理模式 (Proxy Pattern)
- 过滤器模式 (Filter、Criteria Pattern)
- 组合模式 (Composite Pattern)
- 享元模式 (Flyweight Pattern)
行为型
- 责任链模式(Chain of Responsibility Pattern)
- 观察者模式(Observer Pattern)
- 模板模式(Template Pattern)
- 命令模式(Command Pattern)
- 解释器模式(Interpreter Pattern)
- 迭代器模式(Iterator Pattern)
- 中介者模式(Mediator Pattern)
- 策略模式(Strategy Pattern)
- 状态模式(State Pattern)
- 备忘录模式(Memento Pattern)
- 空对象模式(Null Object Pattern)
JDK 类库常用的设计模式有哪些?
- 工厂模式
- 适配器模式
- 代理模式
- 单例模式
- 装饰器
- 模板方法模式
Spring 中都使用了哪些设计模式?
- 代理模式:在 AOP 中有使用
- 单例模式:bean 默认是单例模式
- 模板方法模式:jdbcTemplate
- 工厂模式:BeanFactory
- 观察者模式:Spring 事件驱动模型就是观察者模式很经典的一个应用,比如,ContextStartedEvent 就是 ApplicationContext 启动后触发的事件
- 适配器模式:Spring MVC 中也是用到了适配器模式适配 Controller
Java中什么叫单例设计模式?请用 Java 写出线程安全的单例模式
单例模式重点在于在整个系统上共享一些创建时较耗资源的对象。整个应用中只维护一个特定类实例,它被所有组件共同使用。Java.lang.Runtime 是单例模式的经典例子。
静态内部类:
JVM提供了同步控制功能:static final,利用JVM进行类加载的时候保证数据同步。
在内部类中创建对象实例,只要应用中不使用内部类,JVM就不会去加载该类,就不会创建我们要创建的单例对象。
public class StaticInnerSingleton {
private StaticInnerSingleton(){
}
/**
* 在第一次加载StaticInnerSingleton时不会初始化instance,
* 只在第一次调用了getInstance方法时,JVM才会加载StaticInnerSingleton并初始化instance
* @return
*/
public static StaticInnerSingleton getInstance(){
return SingletonHolder.instance;
}
//静态内部类
private static class SingletonHolder{
private static final StaticInnerSingleton instance = new StaticInnerSingleton();
}
}
优点:JVM本身机制保证了线程安全,没有性能缺陷。
枚举:
public enum EnumSingleton {
//定义一个枚举的元素,它就是Singleton的一个实例
INSTANCE;
public void doSomething(){
}
}
注意:如果在枚举类中有其他实例方法或实例变量,必须确保是线程安全的。
使用工厂模式最主要的好处是什么?在哪里使用?
工厂模式的最大好处是增加了创建对象时的封装层次。如果你使用工厂来创建对象,之后你可以使用更高级和更高性能的实现来替换原始的产品实现或类,这不需要在调用层做任何修改。
什么是观察者设计模式(observer design pattern )?实现一个观察者设计模式。
观察者模式是定义对象间的一种一对多
依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式又叫做发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式
优点
观察者模式可以实现表示层和数据逻辑层的分离,并定义了稳定的消息更新传递机制,抽象了更新接口,使得可以有各种各样不同的表示层作为具体观察者角色;
观察者模式在观察目标和观察者之间建立一个抽象的耦合;
观察者模式支持广播通信;
观察者模式符合开闭原则(对拓展开放,对修改关闭)的要求。
缺点
如果一个观察目标对象有很多直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间;
如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃;
观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
public class Subject {
private List<Observer> observers
= new ArrayList<Observer>();
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
notifyAllObservers();
}
public void attach(Observer observer){
observers.add(observer);
}
public void notifyAllObservers(){
for (Observer observer : observers) {
observer.update();
}
}
}
public abstract class Observer {
protected Subject subject;
public abstract void update();
}
public class BinaryObserver extends Observer{
public BinaryObserver(Subject subject){
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println( "Binary String: "
+ Integer.toBinaryString( subject.getState() ) );
}
}
public class OctalObserver extends Observer{
public OctalObserver(Subject subject){
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println( "Octal String: "
+ Integer.toOctalString( subject.getState() ) );
}
}
public class HexaObserver extends Observer{
public HexaObserver(Subject subject){
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println( "Hex String: "
+ Integer.toHexString( subject.getState() ).toUpperCase() );
}
}
public class ObserverPattern {
public static void main(String[] args) {
Subject subject = new Subject();
new HexaObserver(subject);
new OctalObserver(subject);
new BinaryObserver(subject);
System.out.println("First state change: 15");
subject.setState(15);
System.out.println("Second state change: 10");
subject.setState(10);
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。