Java面试题冲刺第十五天--设计模式

目录
  • 面试题1:面向对象程序设计(OOP)的六大原则分别有哪几个
  • 面试题2:你说一下什么是设计模式
    • 追问1:那你怎么理解高内聚和低耦合?
  • 面试题3:设计模式有哪几种?
    • 追问1:你比较熟悉哪种设计模式?说说原理。
    • 追问2:那你说说适配器模式的原理吧
    • 适配器模式优缺点
  • 总结

面试题1:面向对象程序设计(OOP)的六大原则分别有哪几个

开闭原则(Open Close Principle)及“开放-封闭原则”单一职责原则(Single Responsibility Principle)里氏替换原则(Liskov Substitution Principle)依赖倒置原则(Dependence Inversion Principle)接口隔离原则(Interface Segregation Principle)最少知识原则(Law Of Demeter)

面向对象程序设计中,需要遵守的原则主要有6个,称为六大原则。面向对象程序设计原则也是我们用于评价一个设计模式的重要指标之一。在设计模式中,很多设计模式都遵守了这些原则。

原则名称 内容说明
开闭原则 对扩展开放,对修改关闭。
单一职责原则 即一个类只负责相应领域的职责,即不要存在多于一个导致类变更的原因。
里氏代换原则 子类型必须能够替换它们的父类型。一个软件实体如果使用的是一个父类,那么当把这个父类替换成继承该父类的子类,程序的行为不会发生任何变化。软件实体察觉不出父类对象和子类对象的区别。
依赖倒置原则 要依赖于抽象,不要依赖于具体。客户端依赖于抽象耦合。抽象不应当依赖于细节;细节应当依赖于抽象;要针对接口编程,不针对实现编程。
接口隔离原则 客户端不应该依赖它不需要的接口。一个类对另一个类的依赖应该建立在最小的接口上。
最少知识原则 对象与对象之间应该使用尽可能少的方法来关联,避免千丝万缕的关系。

面试题2:你说一下什么是设计模式

设计模式(Design pattern) 是解决软件开发某些特定问题而提出的一些解决方案也可以理解成解决问题的一些思路。通过设计模式可以帮助我们增强代码的可重用性、可扩充性、 可维护性、灵活性。我们使用设计模式最终的目的是实现代码的 高内聚 和低耦合。

追问1:那你怎么理解高内聚和低耦合?

耦合:

也称块间联系。指软件系统结构中各模块间相互联系紧密程度的一种度量。模块之间联系越紧密,其耦合性就越强,模块的独立性则越差。

内聚:

故名思议,表示内部间聚集、关联的程度,那么高内聚就是指要高度的聚集和关联。内聚是从功能角度来度量模块内的联系,一个好的内聚模块应当恰好做一件事。它描述的是模块内的功能联系。

高内聚低耦合,是软件工程中的概念,是判断软件设计好坏的标准,主要用于程序的面向对象的设计,主要看类的内聚性是否高,耦合度是否低。目的是使程序模块的可重用性、移植性大大增强。通常程序结构中各模块的内聚程度越高,模块间的耦合程度就越低。

面试题3:设计模式有哪几种?

总体来说设计模式分为三大类:

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

除了23种常见设计模式外,其实还有两类:并发型模式和线程池模式。

模式类型 名称 定义
创建型 工厂方法模式(Factory Pattern) 定义一个用于创建对象的接口,让子类决定实例化哪个类。工厂方法模式是一个类的实例化延迟到子类。
创建型 抽象工厂模式(Abstract Factory Pattern) 提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。
创建型 单例模式(Singleton Pattern) 确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。
创建型 建造者模式(Builder Pattern) 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
创建型 原型模式(Prototype Pattern) 用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。
结构型 适配器模式(Adapter Pattern) 将一个接口转换成客户希望的另一个接口,使接口不兼容的那些类可以一起工作
结构型 桥接模式(Bridge Pattern) 将抽象部分与它的实现部分分离,使它们都可以独立地变化。
结构型 组合模式(Composite Pattern) 组合多个对象形成树形结构以表示具有“整体—部分”关系的层次结构。使得用户对单个对象和组合对象的使用具有一致性。
结构型 装饰器模式(Decorator Pattern) 动态地给一个对象增加一些额外的职责,就增加对象功能来说,装饰模式比生成子类实现更为灵活。
结构型 外观模式(Facade Pattern) 为子系统中的一组接口提供一个统一的入口。外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用
结构型 享元模式(Flyweight Pattern) 运用共享技术有效地支持大量细粒度对象的复用。
结构型 代理模式(Proxy Pattern) 为其他对象提供一种代理以控制对这个对象的访问。
行为型 责任链模式(Chain of Responsibility Pattern) 使多个对象都有机会处理请求,从而避免请求发送者与接收者耦合在一起。将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。
行为型 命令模式(Command Pattern) 将一个请求封装为一个对象,从而可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。
行为型 解释器模式(Interpreter Pattern) 给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
行为型 迭代器模式(Iterator Pattern) 提供一种方法来访问聚合对象中的各个元素,而不用暴露这个对象的内部表示。
行为型 中介者模式(Mediator Pattern) 用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
行为型 备忘录模式(Memento Pattern) 在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。
行为型 观察者模式(Observer Pattern) 定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。
行为型 状态模式(State Pattern) 允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。
行为型 策略模式(Strategy Pattern) 定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法独立于使用它的客户而变化。
行为型 模板方法模式(Template Pattern) 定义一个操作中算法的框架,而将一些步骤延迟到子类中。模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
行为型模式 访问者模式(Visitor Pattern) 表示一个作用于某对象结构中的各元素的操作,它使我们可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

追问1:你比较熟悉哪种设计模式?说说原理。

面试者老王:我都略懂一些。

面试官:那你走吧,简历还你。

面试者老王:???

面试者老王:那我比较了解工厂、单例、代理和适配器模式。

追问2:那你说说适配器模式的原理吧

二狗不知道在哪听说华为手机就是牛,非要新买了一个华为手机,它高高兴兴的拿到新手机,想要插上耳机听歌,但发现手机没有通用的原型耳机孔,仔细看了说明书之后发现,华为手机是充电孔耳机孔在一起,在插耳机时需要一个耳机口转接器,才能插耳机。我们用程序员的眼观来看,这里相当于增加了一个转接器类用于适配耳机,这就类似于设计模式 —— 适配器模式(Adapter)。

适配器模式包装目标类即适配者(Adaptee)成适配器。适配器提供客户端所需要的接口,把客户端的请求转化成对适配者的调用。也就是说,客户端访问适配器时,在适配器内部将调用适配者的方法。

  • Client:客户端,调用自己需要的接口
  • TargetTarget:定义客户端需要的跟特定需求相关的接口
  • Apaptee:已存在接口,通常满足功能需求但与特定需求接口不一致
  • Adapter:适配器,将Adaptee适配为Client需要的Target接口。

适配器模式的主要功能是进行转换匹配,用来复用已有的功能。适配器模式将某个类的接口转换成客户端期望的另一个接口,目的是消除由于接口不匹配所造成的类的兼容性问题。主要分为三类:类适配器模式、对象适配器模式、接口适配器模式。

三种适配器模式有各自的应用场景:

  • 类的适配器模式:将一个类转换成满足另一个新接口的类,创建一个新类,继承原有的类,实现新的接口即可。
  • 对象的适配器模式:将一个对象转换成满足另一个新接口的对象,可以创建一个Wrapper类,持有原类的一个实例,在Wrapper类的方法中,调用实例的方法即可。
  • 接口的适配器模式:当不希望实现一个接口中所有的方法时,可以创建一个抽象类Wrapper,实现所有方法,我们写别的类的时候,继承抽象类即可。

适配器模式的本质是:转换匹配,复用功能。适配器模式中被适配的接口Adaptee与适配的接口Target没有关系,他们中的方法可以相同,也可以完全不同,适配器模式的实现方式是通过组合对象的方式进行的,将功能委托给被适配的对象进行的。适配器模式调用的序列图如下所示:

适配器模式的实现有以下几种:

  • 常见适配:适配器类会实现接口,在实现过程中调用待适配的类中的方法
  • 智能适配器:在适配器类中实现接口中定义的新方法,通常来说,适配器类中既可以通过借助继承类中的方法实现高层功能,也可以实现接口中定义的新方法,进行功能扩展。
  • 缺省适配:即对接口的缺省实现,即接口适配器模式。

此外,在适配过程中,可能接口功能的实现需要多个待适配类中的方法交互才能满足需求,即同时适配多个类。适配实现的复杂度取决于待适配类与接口的相似度,相似程度越高,适配类的实现难度越低。

在实际项目过程中,通常会存在两个版本共存的情况,这就是需要使用到双向适配器。

两个版本的实现代码:

public interface Targetable1 {
	public void produce1();
}
public class Target1 implements Targetable1 {
	@Override
	public void produce1() {
		System.out.println("Targetable1的produce1实现");
	}
}

public interface Targetable2 {
	public void produce2();
}
public class Target2 implements Targetable2 {
	@Override
	public void produce2() {
		System.out.println("Targetable2的produce2实现");
	}
}

适配器类的代码如下:

public class Adapter implements Targetable1, Targetable2 {

    private Targetable1 target1;
    private Targetable2 target2;

    @Override
    public void produce1() {
        target1.produce1();
    }

    @Override
    public void produce2() {
        target2.produce2();
    }
}

实际上,在使用适配器过程中存在一个问题:被适配的对象不兼容Adapter适配器类,这使得适配器类的适用范围受到限制。而双向适配器则解决了这样的问题,可以满足不同客户采用不同方式查看同一不同对象的需求。

适配器模式优缺点

优点:

  • 更好的复用性。适配器模式可复用已实现接口的兼容。
  • 更好的扩展性。实现适配器的过程中可以调用自己开发的功能,实现系统的扩展。

缺点:

过多使用适配器,系统会比较混乱,不易理解。

总结

本篇文章就到这里了,希望能给你带来帮助,也希望您能够多多关注我们的更多内容!

(0)

相关推荐

  • Java面试题冲刺第十三天--数据库(3)

    目录 面试题1:MySQL有哪些数据类型? 追问1:char 和 varchar 的区别是什么? 1.固定长度 & 可变长度 2.存储方式 3.存储容量 4.思考:既然VARCHAR长度可变,那我要不要定到最大? 5.在SQL中需要注意的点 追问2:varchar(50).char(50)中50的涵义是什么? 追问3:那int(10)中10的涵义呢?int(1)和int(20)有什么不同? 面试题2:MySQL 的内连接.左连接.右连接有什么区别? 面试题3:MySQL的隐式转换问题遇到过么?说

  • Java面试题冲刺第十四天--PRC框架

    目录 面试题1:说说你对RPC框架的理解? 追问1:RPC框架实现原理是什么样的 1.建立通信 2.服务寻址 3.网络传输 4.服务调用 面试题2:常见的RPC框架有哪些? 面试题3:说说RPC和SOA.SOAP.REST的区别吧 1.REST 2.SOAP 3.SOA 总结 面试题1:说说你对RPC框架的理解?   RPC (Remote Procedure Call)即远程过程调用,是分布式系统常见的一种通信方法.它允许程序调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数,而不

  • Java面试题冲刺第十一天--集合框架篇(2)

    目录 面试题1:说一下 HashMap 的实现原理? 正经回答: 深入追问: 追问1:如何实现HashMap的有序? 追问2:那TreeMap怎么实现有序的? 追问3:put方法原理是怎么实现的? 追问4:HashMap扩容机制原理 追问5:HashMap在JDK1.8都做了哪些优化? 追问6:链表红黑树如何互相转换?阈值多少? 面试题2:HashMap是线程安全的吗? 正经回答: 追问1:你是如何解决这个线程不安全问题的? 总结 面试题1:说一下 HashMap 的实现原理? 正经回答: 众所

  • Java面试题冲刺第十六天--消息队列

    目录 面试题1:说说你对消息队列的理解,消息队列为了解决什么问题? 解耦 异步 削峰 追问1:消息队列有什么优缺点 面试题2:对于消息中间机,你们是怎么做技术选型的? 面试题3:如何确保消息正确地发送至 RabbitMQ?如何确保消息接收方消费了消息? 发送方确认模式 接收方确认机制 追问1:如何保证MQ消息的可靠传输? 总结 面试题1:说说你对消息队列的理解,消息队列为了解决什么问题? 我们公司业务系统一开始体量较小,很多组件都是单机版就足够,后来随着用户量逐渐扩大,我们程序也采用了微服务的设

  • Java面试题冲刺第十二天--数据库(2)

    目录 面试题2:并发场景下事务会存在哪些数据问题? 正经回答: 深入追问: 追问1:那Innodb是如何解决幻读问题的呢? 面试题3:说一下MySQL中你都知道哪些锁? 正经回答: 深入追问: 追问1:那你来谈一谈你对表锁.行锁的理解吧. 追问2:那全局锁是什么时候用的呢? 追问2:那你再说一下按锁级别划分的那几种锁的使用场景和理解吧? 总结 面试题1:先说一下什么是MySQL事务吧 正经回答: 简单说,事务就是一组原子性的SQL执行单元.如果数据库引擎能够成功地对数据库应 用该组査询的全部语句

  • Java面试题冲刺第十五天--设计模式

    目录 面试题1:面向对象程序设计(OOP)的六大原则分别有哪几个 面试题2:你说一下什么是设计模式 追问1:那你怎么理解高内聚和低耦合? 面试题3:设计模式有哪几种? 追问1:你比较熟悉哪种设计模式?说说原理. 追问2:那你说说适配器模式的原理吧 适配器模式优缺点 总结 面试题1:面向对象程序设计(OOP)的六大原则分别有哪几个 开闭原则(Open Close Principle)及"开放-封闭原则"单一职责原则(Single Responsibility Principle)里氏替换

  • Java面试题冲刺第二十五天--实战编程2

    目录 面试题2:怎么理解负载均衡的?你处理负载均衡都有哪些途径? 1.[协议层]http重定向 2.[协议层]DNS轮询 3.[协议层]CDN 4.[协议层]反向代理负载均衡 5.[网络层]IP负载均衡 面试题3:你平时是怎样定位线上问题的? 总结 面试题1:当你发现一条SQL很慢,你的处理思路是什么? 发现Bug 确定Bug不是自己造成的,如果无法确定,不要理会步骤1 向组内宣传"程序里有一个未知Bug,错不在我" 谁响应,谁对Bug负责 没人响应,就要求特定人员配合调试 如果不配合

  • Java面试题冲刺第二十五天--并发编程3

    目录 面试题1:你了解线程池么?简单介绍一下. 追问1:连接池 和 线程池是一个意思么?有什么区别? 不同点 面试题2:线程池中核心线程数量大小你是怎么设置的? 追问1:核心线程数量过大或过小会造成什么后果? 面试题3:线程池都有哪些状态呀? 追问1:什么条件下会进入TERMINATED状态 总结 面试题1:你了解线程池么?简单介绍一下. java提供的一个java.util.concurrent.Executor接口的实现用于创建线程池. 线程池是一种多线程处理形式,处理过程中将任务提交到线程

  • Java面试题冲刺第二十五天--JVM2

    目录 面试题1:简单说一下java的垃圾回收机制. 面试题2:JVM会在什么时候进行GC呢? 追问1:介绍一下不同代空间的垃圾回收机制 追问2:能说一下新生代空间的构成与执行逻辑么? 追问3:说一下发生OOM时,垃圾回收机制的执行流程. 面试题3:Full GC .Major GC和 Minor GC有什么不同 (1)Minor GC / Young GC (2)Old GC (3)Full GC (4)Major GC (5)Mixed GC 总结 面试题1:简单说一下java的垃圾回收机制.

  • Java面试题冲刺第二十五天--并发编程1

    目录 面试题1:简单说下你对线程和进程的理解? 正经回答: 深入追问: 追问1:那进程和线程有哪些区别呢? 面试题2:守护线程和用户线程的区别? 正经回答: 面试题3:什么是线程死锁? 正经回答: 深入追问: 追问1:形成死锁的四个必要条件是什么? 追问2:我们该如何避免死锁? 追问3:死锁避免和死锁预防有啥不同? 总结 面试题1:简单说下你对线程和进程的理解? 正经回答: 进程 一个在内存中运行的应用程序.每个进程都有自己独立的一块内存空间,一个进程可以有多个线程,比如在Windows系统中,

  • Java面试题冲刺第二十五天--并发编程2

    目录 面试题1:简单说下你对线程和进程的理解? 正经回答: 深入追问: 追问1:那进程和线程有哪些区别呢? 面试题2:守护线程和用户线程的区别? 正经回答: 面试题3:什么是线程死锁? 正经回答: 深入追问: 追问1:形成死锁的四个必要条件是什么? 追问2:我们该如何避免死锁? 追问3:死锁避免和死锁预防有啥不同? 总结 面试题1:简单说下你对线程和进程的理解? 正经回答: 进程 一个在内存中运行的应用程序.每个进程都有自己独立的一块内存空间,一个进程可以有多个线程,比如在Windows系统中,

  • Java面试题冲刺第十四天--基础篇3

    目录 面试题1:JDK1.8的新特性有哪些? 接口的默认和静态方法: Lambda 表达式: 方法与构造函数引用: 函数式接口: Annotation 注解:支持多重注解: 新的日期时间 API: Base64编码: JavaScript引擎Nashorn: Stream的使用: Optional: 扩展注解的支持: 并行(parallel)数组: 编译器优化: 其他核心 API 的改进 Java IO改进 集合 API 的改进 面试题2:什么是内部类?内部类的作用? 内部类的作用 内部类特点

  • Java面试题冲刺第二十四天--并发编程

    目录 面试题1:说一下你对ReentrantLock的理解? CAS: AQS: 追问1:你认为 ReentrantLock 相比 synchronized 都有哪些区别? 面试题2:解释一下公平锁和非公平锁? 面试题3:能详细说一下CAS具体实现原理么? 追问1:那CAS的缺陷有哪些呢? 1.ABA: 2.自旋消耗资源: 3.多变量共享一致性问题: 追问2:讲一下什么是ABA问题?怎么解决? 总结 面试题1:说一下你对ReentrantLock的理解? ReentrantLock是JDK1.5

  • Java面试题冲刺第二十六天--实战编程

    目录 面试题1:你们是怎样保存用户密码等敏感数据的? 面试题2:怎么控制用户请求的幂等性的? 1.设置唯一索引:防止新增脏数据 2.token机制:防止页面重复提交 3.悲观锁 4.乐观锁 5.分布式锁 面试题3:你们是如何预防SQL注入问题的? 预防方式: 1.PreparedStatement(简单有效) 2.使用正则表达式过滤传入的参数 3.使用正则表达式过滤传入的URL 总结 面试题1:你们是怎样保存用户密码等敏感数据的? 本题回答参考朱晔的<Java业务开发常见错误100例> 我们知

随机推荐