15道设计模式⾯试题
Q1:设计模式有哪些原则?
开闭原则:OOP 中最基础的原则,指⼀个软件实体(类、模块、⽅法等)应该对扩展开放,对修改关闭。强调⽤抽象构建框架,⽤实现扩展细节,提⾼代码的可复⽤性和可维护性。
单⼀职责原则:⼀个类、接⼝或⽅法只负责⼀个职责,降低代码复杂度以及变更引起的风险。
依赖倒置原则:程序应该依赖于抽象类或接⼝,⽽不是具体的实现类。
接⼝隔离原则:将不同功能定义在不同接⼝中实现接⼝隔离,避免了类依赖它不需要的接⼝,减少了接⼝之间依赖的冗余性和复杂性。
⾥⽒替换原则:开闭原则的补充,规定了任何⽗类可以出现的地⽅⼦类都⼀定可以出现,可以约束继承泛滥,加强程序健壮性。
迪⽶特原则:也叫最少知道原则,每个模块对其他模块都要尽可能少地了解和依赖,降低代码耦合度。
合成/聚合原则:尽量使⽤组合(has-a)/聚合(contains-a)⽽不是继承(is-a)达到软件复⽤的⽬的,避免滥⽤
继承带来的⽅法污染和⽅法爆炸,⽅法污染指⽗类的⾏为通过继承传递给⼦类,但⼦类并不具备执⾏此⾏为的能⼒;⽅法爆炸指继承树不断扩⼤,底层类拥有的⽅法过于繁杂,导致很容易选择错误。
Q2:设计模式的分类,你知道哪些设计模式?
创建型: 在创建对象的同时隐藏创建逻辑,不使⽤ new 直接实例化对象,程序在判断需要创建哪些对象时更灵活。包括⼯⼚/抽象⼯⼚/单例/建造者/原型模式。
**结构型: **通过类和接⼝间的继承和引⽤实现创建复杂结构的对象。包括适配器/桥接模式/过滤器/组合/装饰器/外观/享元/代理模式。
**⾏为型: **通过类之间不同通信⽅式实现不同⾏为。包括责任链/命名/解释器/迭代器/中介者/备忘录/观察者/状态/策略/模板/访问者模式。Q3:说⼀说简单⼯⼚模式
简单⼯⼚模式指由⼀个⼯⼚对象来创建实例,客户端不需要关注创建逻辑,只需提供传⼊⼯⼚的参数。
适⽤于⼯⼚类负责创建对象较少的情况,缺点是如果要增加新产品,就需要修改⼯⼚类的判断逻辑,违背开闭原则,且产品多的话会使⼯⼚类⽐较复杂。
java接口可以创建对象吗Calendar 抽象类的 getInstance ⽅法,调⽤ createCalendar ⽅法根据不同的地区参数创建不同的⽇历对象。
Spring 中的 BeanFactory 使⽤简单⼯⼚模式,根据传⼊⼀个唯⼀的标识来获得 Bean 对象。
Q4:说⼀说⼯⼚⽅法模式
⼯⼚⽅法模式指定义⼀个创建对象的接⼝,让接⼝的实现类决定创建哪种对象,让类的实例化推迟到⼦类中进⾏。
客户端只需关⼼对应⼯⼚⽽⽆需关⼼创建细节,主要解决了产品扩展的问题,在简单⼯⼚模式中如果产品种类变多,⼯⼚的职责会越来越多,不便于维护。
Collection 接⼝这个抽象⼯⼚中定义了⼀个抽象的 iterator ⼯⼚⽅法,返回⼀个 Iterator 类的抽象产品。该⽅法通过 ArrayList 、HashMap
等具体⼯⼚实现,返回 Itr、KeyIterator 等具体产品。
理。两种代理都在运⾏期⽣成字节码,JDK 动态代理直接写字节码,⽽ CGLib 动态代理使⽤ ASM 框架写字节码,ASM 的⽬的是⽣成、转换和分析以字节数组表⽰的已编译 Java 类。 JDK 动态代理调⽤代理⽅法通过反射机制实现,⽽ GCLib 动态代理通过 FastClass 机制直接调⽤⽅法,它为代理类和被代理类各⽣成⼀个类,该类为代理类和被代理类的⽅法分配⼀个 int 参数,调⽤⽅法时可以直接定位,因此调⽤效率更⾼。
Q9:讲⼀讲装饰器模式
装饰器模式属于结构型模式,在不改变原有对象的基础上将功能附加到对象,相⽐继承可以更加灵活地扩展原有对象的功能。
装饰器模式适合的场景:在不想增加很多⼦类的前提下扩展⼀个类的功能。
java.io 包中,InputStream 字节输⼊流通过装饰器 BufferedInputStream 增强为缓冲字节输⼊流。
Q10:装饰器模式和动态代理的区别?
装饰器模式的关注点在于给对象动态添加⽅法,⽽动态代理更注重对象的访问控制。动态代理通常会在代理类中创建被代理对象的实例,⽽装饰器模式会将装饰者作为构造⽅法的参数。
Q11:讲⼀讲适配器模式
适配器模式属于结构型模式,它作为两个不兼容接⼝之间的桥梁,结合了两个独⽴接⼝的功能,将⼀个类的接⼝转换成另外⼀个接⼝使得原本由于接⼝不兼容⽽不能⼀起⼯作的类可以⼀起⼯作。
缺点是过多使⽤适配器会让系统⾮常混乱,不易整体把握。
java.io 包中,InputStream 字节输⼊流通过适配器 InputStreamReader 转换为 Reader 字符输⼊流。
Spring MVC 中的 HandlerAdapter,由于 handler 有很多种形式,包括 Controller、HttpRequestHandler、Servlet 等,但调⽤⽅式⼜是确定的,因此需要适配器来进⾏处理,根据适配规则调⽤ handle ⽅法。
Arrays.asList ⽅法,将数组转换为对应的集合(注意不能使⽤修改集合的⽅法,因为返回的 ArrayList 是 Arrays 的⼀个内部类)。
Q12:适配器模式和和装饰器模式以及代理模式的区别?
适配器模式没有层级关系,适配器和被适配者没有必然连续,满⾜ has-a 的关系,解决不兼容的问题,是⼀种后置考虑。
装饰器模式具有层级关系,装饰器与被装饰者实现同⼀个接⼝,满⾜ is-a 的关系,注重覆盖和扩展,是⼀种前置考虑。
适配器模式主要改变所考虑对象的接⼝,⽽代理模式不能改变所代理类的接⼝。
Q13:讲⼀讲策略模式
策略模式属于⾏为型模式,定义了⼀系列算法并封装起来,之间可以互相替换。策略模式主要解决在有多种算法相似的情况下,使⽤ if/else 所带来的难以维护。
优点是算法可以⾃由切换,可以避免使⽤多重条件判断并且扩展性良好,缺点是策略类会增多并且所有策略类都需要对外暴露。
在集合框架中,经常需要通过构造⽅法传⼊⼀个⽐较器 Comparator 进⾏⽐较排序。Comparator 就是⼀个抽象策略,⼀个类通过实现该接⼝并重写 compare ⽅法成为具体策略类。
创建线程池时,需要传⼊拒绝策略,当创建新线程使当前运⾏的线程数超过 maximumPoolSize 时会使⽤相应的拒绝策略处理。
Q14:讲⼀讲模板模式
模板模式属于⾏为型模式,使⼦类可以在不改变算法结构的情况下重新定义算法的某些步骤,适⽤于抽取⼦类重复代码到公共⽗类。
优点是可以封装固定不变的部分,扩展可变的部分。缺点是每⼀个不同实现都需要⼀个⼦类维护,会增加类的数量。
为防⽌恶意操作,⼀般模板⽅法都以 final 修饰。
HttpServlet 定义了⼀套处理 HTTP 请求的模板,service ⽅法为模板⽅法,定义了处理HTTP请求的基本流程,doXXX 等⽅法为基本⽅法,根据请求⽅法的类型做相应的处理,⼦类可重写这些⽅法。
Q15:讲⼀讲观察者模式
观察者模式属于⾏为型模式,也叫发布订阅模式,定义对象间的⼀种⼀对多的依赖关系,当⼀个对象的状态发⽣改变时,所有依赖于它的对象都得到通知并被⾃动更新。主要解决⼀个对象状态改变给其他对象通知的问题,缺点是如果被观察者对象有很多的直接和间接观察者的话通知很耗时,如果存在循环依赖的话可能导致系统崩溃,另外观察者⽆法知道⽬标对象具体是怎么发⽣变化的。
ServletContextListener 能够监听 ServletContext 对象的⽣命周期,实际上就是监听 Web 应⽤。当 Servlet 容器启动 Web 应⽤时调⽤ contextInitialized ⽅法,终⽌时调⽤ contextDestroyed ⽅法。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论