设计模式面试最常问的20道面试题
设计模式面试最常问的20道面试题
全部面试题答案,更新日期:01月30日,直接下载吧!
下载链接:高清500+份面试题资料及电子书,累计 10000+ 页大厂面试题 PDF
设计模式
题1:Java 中外观模式有什么优势?
1)它对客户屏蔽子系统组件,因而减少了客户处理的对象的数目并使得子系统使用起来更加方便。
2)它实现了子系统与客户之间的松耦合关系,而子系统内部的功能组件往往是紧耦合的。松耦合关系使得子系统的组件变化不会影响到它的客户。Facade模式有助于建立层次结构系统,也有助于对对象之间的依赖关系分层。Facade模式可以消除复杂的循环依赖关系。
这一点在客户程序与子系统是分别实现的时候尤为重要。在大型软件系统中降低编译依赖性至关重要。在子系统类改变时,希望尽量减少重编译工作以节省时间。用Facade可以降低编译依赖性,限制重要系统中较小的变化所需的重编译工作。Facade模式同样也有利于简化系统在不同平台之间的移植过程,因为编译一个子系统一般不需要编译所有其他的子系统。
3)如果应用需要,它并不限制它们使用子系统类。因此你可以在系统易用性和通用性之间加以选择。
题2:Java 中什么是原型模式?
原型模式是一种创建型设计模式,通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象。
原型设计模式简单来说就是克隆,原型模式多用于创建复杂的或者构造耗时的实例,因为这种情况下,复制一个已经存在的实例可使程序运行更高效。
原型模式有两种表现形式:
1)简单形式;
2)登记形式,这两种表现形式仅仅是原型模式的不同实现。
简单形式的原型模式,涉及到三种角色分别如下:
1)客户(Client)角色:客户类提出创建对象的请求。
2)抽象原型(Prototype)角色:这是一个抽象角色,通常由一个Java接口或Java抽象类实现。此角色给出所有的具体原型类所需的接口。
3)具体原型(Concrete Prototype)角色:被复制的对象。此角色需要实现抽象的原型角色所要求的接口。
题3:什么是高内聚、低耦合?
内聚关注模块内部的元素结合程度,耦合关注模块之间的依赖程度。
1)内聚性
又称块内联系。指模块的功能强度的度量,即一个模块内部各个元素彼此结合的紧密程度的度量。若一个模块内各元素(语名之间、程序段之间)联系的越紧密,则它的内聚性就越高。
所谓高内聚是指一个软件模块是由相关性很强的代码组成,只负责一项任务,也就是常说的单一责任原则。
2)耦合性
也称块间联系。指软件系统结构中各模块间相互联系紧密程度的一种度量。模块之间联系越紧密,其耦合性就越强,模块的独立性则越差。模块间耦合高低取决于模块间接口的复杂性、调用的方式及传递的信息。
对于低耦合,粗浅的理解是:一个完整的系统,模块与模块之间,尽可能的使其独立存在。也就是说,让每个模块,尽可能的独立完成某个特定的子功能。模块与模块之间的接口,尽量的少而简单。如果某两个模块间的关系比较复杂的话,最好首先考虑进一步的模块划分。这样有利于修改和组合。
题4:Java 中如何实现策略模式?
实例:假设张三要到北方做买卖,走之前张三的父亲给仆人三个锦囊,说是危机关头按顺序依次拆开能解决相应的问题。场景中出现三个要素:妙计(具体策略类)、锦囊(环境事件类)、仆人(调用者)。
1、抽象策略类(Strategy)
public interface Strategy {
public void operate();
}
2、妙计一,初到北方地界,实现类:
public class NorthernBoundary implements IStrategy {
@Override
public void operate() {
System.out.println("钱财打通官府,求照应,方便行事");
}
}
3、妙计二,在当地开展买卖事宜,实现类:
public class UnderstandingCustomsCulture implements IStrategy {
@Override
public void operate() {
System.out.println("了解当地风俗文化");
}
}
4、妙计三,地皮流氓闹事,官府快速接入处理,实现类:
public class AccessProcessing implements IStrategy {
@Override
public void operate() {
System.out.println("地皮流氓闹事,官府快速接入处理");
}
}
5、环境事件类(Context):
public class ContextEvent {
private Strategy strategy;
//构造函数
public ContextEvent(Strategy strategy){
this.strategy = strategy;
}
public void setStrategy(Strategy strategy){
this.strategy = strategy;
}
public void operate(){
this.strategy.operate();
}
}
6、简单测试类:
public class BlogYoodb {
public static void main(String[] args) {
ContextEvent context;
System.out.println("----------初到北方地界使用锦囊一---------------");
context = new ContextEvent(new NorthernBoundary());
context.operate();
System.out.println("\n");
System.out.println("----------开展买卖事宜使用锦囊二---------------");
context.setStrategy(new UnderstandingCustomsCulture());
context.operate();
System.out.println("\n");
System.out.println("----------地皮流氓闹事,使用锦囊三---------------");
context.setStrategy(new AccessProcessing());
context.operate();
System.out.println("\n");
}
}
题5:Java 中原型模式有什么应用场景?
1、类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。这时我们就可以通过原型拷贝避免这些消耗。
2、通过new产生的一个对象需要非常繁琐的数据准备或者权限,这时可以使用原型模式。
3、一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用,即保护性拷贝。
题6:Java 中什么是建造者模式?
建造模式是一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示,将其复杂的内部创建封装在内部,对于外部调用的人来说,只需要传入建造者和建造工具,对于内部是如何建造成成品的,调用者无需关心。
建造者模式涉及四个角色分别如下:
1、抽象建造者(Builder)角色:给 出一个抽象接口,以规范产品对象的各个组成成分的建造。一般而言,此接口独立于应用程序的商业逻辑。模式中直接创建产品对象的是具体建造者 (ConcreteBuilder)角色。具体建造者类必须实现这个接口所要求的两种方法:一种是建造方法(buildPart1和 buildPart2),另一种是返还结构方法(retrieveResult)。一般来说,产品所包含的零件数目与建造方法的数目相符。换言之,有多少 零件,就有多少相应的建造方法。
2、具体建造者(ConcreteBuilder)角色:担任这个角色的是与应用程序紧密相关的一些类,它们在应用程序调用下创建产品的实例。这个角色要完成的任务包括:
1)实现抽象建造者Builder所声明的接口,给出一步一步地完成创建产品实例的操作。
2)在建造过程完成后,提供产品的实例。
3、导演者(Director)角色:担任这个角色的类调用具体建造者角色以创建产品对象。应当指出的是,导演者角色并没有产品类的具体知识,真正拥有产品类的具体知识的是具体建造者角色。
4、产品(Product)角色:产品便是建造中的复杂对象。一般来说,一个系统中会有多于一个的产品类,而且这些产品类并不一定有共同的接口,而完全可以是不相关联的。
题7:Java 中如何实现建造者模式?
1、创建产品对象,具体代码如下:
package com.yoodb;
public class Product {
private String partA;
private String partB;
public String getPartA() {
return partA;
}
public void setPartA(String partA) {
this.partA = partA;
}
public String getPartB() {
return partB;
}
public void setPartB(String partB) {
this.partB = partB;
}
}
2、创建接口,具体代码如下:
package com.yoodb;
public interface Builder {
public void buildPartA();
public void buildPartB();
public Product getResult();
}
3、实现Builder的接口以构造和装配该产品的各个部件, 定义并明确它所创建的表示,具体代码如下:
package com.yoodb;
public class ConcreteBuilder implements Builder {
private Product product = new Product();
@Override
public void buildPartA() {
// TODO Auto-generated method stub
product.setPartA("产品-yoodb-001");
}
@Override
public void buildPartB() {
// TODO Auto-generated method stub
product.setPartB("产品-yoodb-002");
}
@Override
public Product getResult() {
// TODO Auto-generated method stub
return product;
}
}
4、构造一个使用Builder接口的对象,具体代码如下:
package com.yoodb;
public class Director {
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
public void construct(){
builder.buildPartA();
builder.buildPartB();
}
}
5、测试实现,具体代码如下:
package com.yoodb;
public class ClientMain {
public static void main(String[] args) {
Builder builder = new ConcreteBuilder();
Director director = new Director(builder);
director.construct();
Product product = builder.getResult();
System.out.println(product.getPartA());
System.out.println(product.getPartB());
}
}
题8:Java 中策略模式有什么应用场景?
策略模式是针对一组算法或逻辑,将每一个算法或逻辑封装到具有共同接口的独立的类中,从而使得它们之间可以相互替换。
实例1:根据不同会员等级打折力度不同的三种策略,初级会员,中级会员,高级会员(三种不同的计算)。
实例2:一个支付模块,要有微信支付、支付宝支付、银联支付等。
实例场景3:张三要到北方做买卖,走之前张三的父亲给仆人三个锦囊,说是危机关头按顺序依次拆开能解决相应的问题。场景中出现三个要素:妙计(具体策略类)、锦囊(环境事件类)、仆人(调用者)。
题9:Java 中单例模式有什么优缺点?
单例模式优点
1、在单例模式中,活动的单例只有一个实例,对单例类的所有实例化得到的都是相同的一个实例。这样就防止其它对象对自己的实例化,确保所有的对象都访问一个实例。
2、单例模式具有一定的伸缩性,类自己来控制实例化进程,类就在改变实例化进程上有相应的伸缩性。
3、提供了对唯一实例的受控访问。
4、由于在系统内存中只存在一个对象,因此可以节约系统资源,当需要频繁创建和销毁的对象时单例模式无疑可以提高系统的性能。
5、允许可变数目的实例。
6、避免对共享资源的多重占用。
单例模式缺点
1、不适用于变化的对象,如果同一类型的对象总是要在不同的用例场景发生变化,单例就会引起数据的错误,不能保存彼此的状态。
2、由于单利模式中没有抽象层,因此单例类的扩展有很大的困难。
3、单例类的职责过重,在一定程度上违背了“单一职责原则”。
4、滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;如果实例化的对象长时间不被利用,系统会认为是垃圾而被回收,这将导致对象状态的丢失。
题10:Java 中如何实现模板方法模式?
举例:去餐厅吃饭,餐厅给我们提供了一个模板就是:看菜单,点菜,吃饭,付款,走人。注意这里“点菜和付款”是不确定的由子类来完成的,其他的则是一个模板。
1、先定义一个模板。把模板中的点菜和付款,让子类来实现。
package com.yoodb.blog;
//模板方法
public abstract class RestaurantTemplate {
// 1.看菜单
public void menu() {
System.out.println("看菜单");
}
// 2.点菜业务
abstract void spotMenu();
// 3.吃饭业务
public void havingDinner(){ System.out.println("吃饭"); }
// 3.付款业务
abstract void payment();
// 3.走人
public void GoR() { System.out.println("走人"); }
//模板通用结构
public void process(){
menu();
spotMenu();
havingDinner();
payment();
GoR();
}
}
2、具体的模板方法子类
package com.yoodb.blog;
public class RestaurantGinsengImpl extends RestaurantTemplate {
void spotMenu() {
System.out.println("人参");
}
void payment() {
System.out.println("5快");
}
}
3、具体的模板方法子类
package com.yoodb.blog;
public class RestaurantLobsterImpl extends RestaurantTemplate {
void spotMenu() {
System.out.println("龙虾");
}
void payment() {
System.out.println("50块");
}
}
4、测试
package com.yoodb.blog;
public class Client {
public static void main(String[] args) {
RestaurantTemplate restaurantTemplate = new RestaurantGinsengImpl();
restaurantTemplate.process();
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律