《Java 后端面试经》设计模式篇

得意时要看淡,失意时要看开。不论得意失意,切莫大意;不论成功失败,切莫止步。志得意满时,需要的是淡然,给自己留一条退路;失意落魄时,需要的是泰然,给自己觅一条出路《Java 后端面试经》设计模式篇,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

《Java 后端面试经》专栏文章索引:
《Java 后端面试经》Java 基础篇
《Java 后端面试经》Java EE 篇
《Java 后端面试经》数据库篇
《Java 后端面试经》多线程与并发编程篇
《Java 后端面试经》JVM 篇
《Java 后端面试经》操作系统篇
《Java 后端面试经》Linux 篇
《Java 后端面试经》设计模式篇
《Java 后端面试经》计算机网络篇
《Java 后端面试经》微服务篇

🚀你了解的设计模式有哪些?

总的设计模式有 23 种,可以分为三大类:

  1. 创建型模式(共五种)工厂方法模式抽象工厂模式单例模式、建造者模式、原型模式
  2. 结构型模式(共七种):适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
  3. 行为型模式(共十一种):策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

🚀在 Spring 框架中都用到了哪些设计模式,并举例说明?

  1. 单例模式:Spring 中的 Bean 默认情况下都是单例的。
  2. 工厂模式:工厂模式主要是通过 BeanFactory 和 ApplicationContext 来生产 Bean 对象。
  3. 代理模式:最常见的 AOP 的实现方式就是通过代理来实现,Spring 主要是使用 JDK 动态代理和 CGLIB 代理。
  4. 模板方法模式:主要是一些对数据库操作的类用到,比如 JdbcTemplate、JpaTemplate,因为查询数据库的建立连接、执行查询、关闭连接几个过程,非常适用于模板方法。
  5. 观察者模式:定义对象键一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知被制动更新,如 Spring中listener 的实现 ApplicationListener.
  6. 适配器模式:SpringMVC 中的适配器 HandlerAdatper,它会根据 Handler 规则执行不同的 Handler. 即 DispatcherServlet 根据 HandlerMapping 返回的 handler,向 HandlerAdatper 发起请求处理 Handler. HandlerAdapter 根据规则找到对应的 Handler 并让其执行,执行完毕后Handler 会向 HandlerAdapter 返回一个 ModelAndView,最后由 HandlerAdapter 向DispatchServelet 返回一个 ModelAndView.
  7. 策略模式:Spring 框架的资源访问 Resource 接口。该接口提供了更强的资源访问能力,Spring 框架本身大量使用了 Resource 接口来访问底层资源。Resource 接口是具体资源访问策略的抽象,也是所有资源访问类所实现的接口。

🚀设计模式的原则有哪些?

设计模式共有六大原则,分别是:单一职责原则、开闭原则、里氏代换原则、依赖倒转原则、接口隔离原则、迪米特法则:

  1. 单一职责:一个类只负责一个功能领域中相应的职责,或者可以定义为:就一个类而言,应该只有一个引起它变化的原因。
  2. 开闭原则:软件实体应该对扩展开放,对修改关闭。其含义是说一个软件实体应该通过扩展来实现变化,而不是通过修改已有的代码来实现变化。
  3. 里氏代换原则:通俗点讲,只要父类能出现的地方子类就可以出现,而且替换为子类也不会产生任何错误或异常,使用者可能根本就不需要知道是父类还是子类。但是,反过来就不行了,有子类出现的地方,父类未必就能适应。
  4. 依赖倒转原则:这个是开闭原则的基础,具体内容:真对接口编程,依赖于抽象而不依赖于具体。
  5. 接口隔离原则:使用多个隔离的接口,比使用单个接口要好。还是一个降低类之间的耦合度的意思,从这儿我们看出,其实设计模式就是一个软件的设计思想,从大型软件架构出发,为了升级和维护方便。所以上文中多次出现:降低依赖,降低耦合。
  6. 迪米特法则:为什么叫最少知道原则,就是说:一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。

🚀谈谈单例模式?

所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法)。例如,在 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

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!