《Java 后端面试经》专栏文章索引:
《Java 后端面试经》Java 基础篇
《Java 后端面试经》Java EE 篇
《Java 后端面试经》数据库篇
《Java 后端面试经》多线程与并发编程篇
《Java 后端面试经》JVM 篇
《Java 后端面试经》操作系统篇
《Java 后端面试经》Linux 篇
《Java 后端面试经》设计模式篇
《Java 后端面试经》计算机网络篇
《Java 后端面试经》微服务篇
《Java 后端面试经》设计模式篇
🚀你了解的设计模式有哪些?
总的设计模式有 23 种,可以分为三大类:
- 创建型模式(共五种):工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
- 结构型模式(共七种):适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
- 行为型模式(共十一种):策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
🚀在 Spring 框架中都用到了哪些设计模式,并举例说明?
- 单例模式:Spring 中的 Bean 默认情况下都是单例的。
- 工厂模式:工厂模式主要是通过 BeanFactory 和 ApplicationContext 来生产 Bean 对象。
- 代理模式:最常见的 AOP 的实现方式就是通过代理来实现,Spring 主要是使用 JDK 动态代理和 CGLIB 代理。
- 模板方法模式:主要是一些对数据库操作的类用到,比如 JdbcTemplate、JpaTemplate,因为查询数据库的建立连接、执行查询、关闭连接几个过程,非常适用于模板方法。
- 观察者模式:定义对象键一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知被制动更新,如 Spring中listener 的实现 ApplicationListener.
- 适配器模式:SpringMVC 中的适配器 HandlerAdatper,它会根据 Handler 规则执行不同的 Handler. 即 DispatcherServlet 根据 HandlerMapping 返回的 handler,向 HandlerAdatper 发起请求处理 Handler. HandlerAdapter 根据规则找到对应的 Handler 并让其执行,执行完毕后Handler 会向 HandlerAdapter 返回一个 ModelAndView,最后由 HandlerAdapter 向DispatchServelet 返回一个 ModelAndView.
- 策略模式:Spring 框架的资源访问 Resource 接口。该接口提供了更强的资源访问能力,Spring 框架本身大量使用了 Resource 接口来访问底层资源。Resource 接口是具体资源访问策略的抽象,也是所有资源访问类所实现的接口。
🚀设计模式的原则有哪些?
设计模式共有六大原则,分别是:单一职责原则、开闭原则、里氏代换原则、依赖倒转原则、接口隔离原则、迪米特法则:
- 单一职责:一个类只负责一个功能领域中相应的职责,或者可以定义为:就一个类而言,应该只有一个引起它变化的原因。
- 开闭原则:软件实体应该对扩展开放,对修改关闭。其含义是说一个软件实体应该通过扩展来实现变化,而不是通过修改已有的代码来实现变化。
- 里氏代换原则:通俗点讲,只要父类能出现的地方子类就可以出现,而且替换为子类也不会产生任何错误或异常,使用者可能根本就不需要知道是父类还是子类。但是,反过来就不行了,有子类出现的地方,父类未必就能适应。
- 依赖倒转原则:这个是开闭原则的基础,具体内容:真对接口编程,依赖于抽象而不依赖于具体。
- 接口隔离原则:使用多个隔离的接口,比使用单个接口要好。还是一个降低类之间的耦合度的意思,从这儿我们看出,其实设计模式就是一个软件的设计思想,从大型软件架构出发,为了升级和维护方便。所以上文中多次出现:降低依赖,降低耦合。
- 迪米特法则:为什么叫最少知道原则,就是说:一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。
🚀谈谈单例模式?
所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法)。例如,在 Hiberate 框架中的 SessionFactory,它充当数据存储源的代理,并负责创建 Session 对象,SessionFactory 并不是轻量级的,一般情况下一个项目通常只需要一个 SessionFactory,这时使用的就是单列模式。
饿汉式单例模式:
public class Singleton {
private static Singleton instance = new Singleton();
// 私有构造方法,保证外界无法直接实例化。
private Singleton() {}
// 通过公有的静态方法获取对象实例
public static Singleton getInstace() {
return instance;
}
}
懒汉式单例模式:
public class Singleton {
private static Singleton instance = null;
// 私有构造方法,保证外界无法直接实例化。
private Singleton() {}
// 通过公有的静态方法获取对象实例
public static Singleton getInstace() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
在懒汉式单例模式基础上实现线程同步:
public class Singleton {
private static Singleton instance = null;
// 私有构造方法,保证外界无法直接实例化。
private Singleton() {}
// 通过公有的静态方法获取对象实例
public static synchronized Singleton getInstace() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
上述代码对静态方法 getInstance() 进行同步,以确保多线程环境下只创建一个实例。如果getInstance() 方法未被同步,并且线程 A 和线程 B 同时调用此方法,则执行 if (instance == null)
语句时都为真,那么线程 A 和线程 B 都会创建一个对象,在内存中就会出现两个对象,这样就违反了单例模式。而使用 synchronized
关键字进行同步后,则不会出现此种情况。
优缺点:
- 解决了线程安全问题
- 效率低,每个线程在想获得类的实例的时候,执行 getInstance() 方法都要进行同步,而其实这个方法只执行一次实例化代码代码就够了,对方法进行同步的效率太低。
双重检查的懒汉单例模式:
public class Singleton {
private static volatile Singleton instance;
// 私有构造方法,保证外界无法直接实例化。
private Singleton() {}
// 通过公有的静态方法获取对象实例
public static synchronized Singleton getInstace() {
if (instance == null) {
synchronized(Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
优缺点:
- 进行了两次
if(instance == null)
检查,保证了线程安全。 - 实例化代码只用执行一次,后面再访问时,判断
if (instance == null)
,直接返回实例化对象,避免了反复进行方法同步。 - 线程安全,延迟加载,效率较高
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/157046.html