最新2021年设计模式面试题及答案汇总版
最新2021年设计模式面试题及答案汇总版
全部面试题答案,更新日期:01月30日,直接下载吧!
下载链接:高清500+份面试题资料及电子书,累计 10000+ 页大厂面试题 PDF
设计模式
题1:Java 中代理模式如何实现静态代理?
如果代理类在程序运行前就已经存在,那么这种代理方式被成为静态代理,这种情况下的代理类一般都是在Java代码中定义的。
通常情况下, 静态代理中的代理类和委托类会实现同一接口或是派生自相同的父类。下面说一下如何实现静态代理模式。
接口(或抽象类),具体代码如下:
package com.yoodb;
public interface Business {
public void doAction();
}
此处是真正意义上实现业务逻辑的类,具体代码如下:
package com.yoodb;
public class BusinessImpl implements Business {
@Override
public void doAction() {
// TODO Auto-generated method stub
System.out.println("实现业务逻辑.");
}
}
自己并未实现业务逻辑接口,而是调用实现,具体代码如下:
package com.yoodb;
public class BusinessImplProxy implements Business{
private BusinessImpl impl;
@Override
public void doAction() {
// TODO Auto-generated method stub
if(impl == null){
impl = new BusinessImpl();
}
doBefore();
impl.doAction();
doAfter();
}
private void doBefore(){
System.out.println("调用目标对象前做相关操作");
}
private void doAfter(){
System.out.println("调用目标对象后做相关操作");
}
}
单元测试,具体代码如下:
package com.yoodb;
public class MainTest {
public static void main(String[] args) {
Business business = new BusinessImplProxy();
business.doAction();
}
}
运行之后结果如下:
调用目标对象前做相关操作
实现业务逻辑.
调用目标对象后做相关操作
题2:Java 中外观模式有什么使用场景?
1、当你要为一个复杂子系统提供一个简单接口时。子系统往往因为不断演化而变得越来越复杂。大多数模式使用时都会产生更多更小的类。这使得子系统更具可重用性,也更容易对子系统进行定制,但这也给那些不需要定制子系统的用户带来一些使用上的困难。Facade可以提供一个简单的缺省视图,这一视图对大多数用户来说已经足够,而那些需要更多的可定制性的用户可以越过Facade层。
2、客户程序与抽象类的实现部分之间存在着很大的依赖性。引入Facade将这个子系统与客户以及其他的子系统分离,可以提高子系统的独立性和可移植性。
3、当你需要构建一个层次结构的子系统时,使用Facade模式定义子系统中每层的入口点,如果子系统之间是相互依赖的,你可以让它们仅通过Facade进行通讯,从而简化了它们之间的依赖关系。
题3:Java 中装饰模式有什么优缺点?
装饰模式优点
1、装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。装饰模式允许系统动态决定“贴上”一个需要的“装饰”,或者除掉一个不需要的“装饰”。继承关系则不同,继承关系是静态的,它在系统运行前就决定了。
2、通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。
装饰模式缺点
由于使用装饰模式,可以比使用继承关系需要较少数目的类。使用较少的类,当然使设计比较易于进行。但是,在另一方面,使用装饰模式会产生比使用继承关系更多的对象。更多的对象会使得查错变得困难,特别是这些对象看上去都很相像。
题4:Java 中三种代理模式有什么区别?
1、静态代理:简单代理模式,是动态代理的理论基础。常见使用在代理模式。
2、jdk动态代理:使用反射完成代理。需要有顶层接口才能使用,常见是mybatis的mapper文件是代理。
3、cglib动态代理:也是使用反射完成代理,可以直接代理类(jdk动态代理不行),使用字节码技术,不能对final类进行继承。(需要导入jar包)。
题5:Java 中原型模式如何实现浅拷贝?
浅拷贝是指对值类型的成员变量进行值的复制,对引用类型的成员变量只复制引用,不复制引用的对象。
浅拷贝只负责克隆按值传递的数据(比如基本数据类型、String类型),而不复制它所引用的对象,换言之,所有的对其他对象的引用都仍然指向原来的对象。
1、实体类,具体代码如下:
package com.yoodb;
public class Prototype implements Cloneable{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
protected Object clone() {
// TODO Auto-generated method stub
try {
return super.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
2、测试方法,具体代码如下:
package com.yoodb;
public class TestMain {
public static void main(String[] args) {
Prototype pro = new Prototype();
pro.setName("欢迎收藏blog.yoodb.com");
Prototype prot = (Prototype) pro.clone();
prot.setName("欢迎收藏blog.yoodb.com");
System.out.println("original object:" + pro.getName());
System.out.println("cloned object:" + prot.getName());
}
}
3、运行结果如下:
original object:欢迎收藏blog.yoodb.com
cloned object:欢迎收藏blog.yoodb.com
题6: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();
}
}
题7:Java 中工厂模式有什么优势?
1、工厂模式是最常用的实例化对象模式,是用工厂方法代替new操作的一种模式。
2、利用工厂模式可以降低程序的耦合性,为后期的维护修改提供了很大的便利。
3、将选择实现类、创建对象统一管理和控制,从而将调用者跟我们的实现类解耦。
题8:Java 中工厂模式分为哪几大类?
工厂模式分为三类,如下:
1)简单工厂模式(Simple Factory),又称静态工厂方法模式,是由一个具体的类去创建其他类的实例,父类是相同的,父类是具体的, 不利于产生系列产品;
2)工厂方法模式(Factory Method),又称为多形性工厂是有一个抽象的父类定义公共接口,子类负责生成具体的对象,这样做的目的是将类的实例化操作延迟到子类中完成;
3)抽象工厂模式(Abstract Factory),又称为工具箱,提供一个创建一系列相关或相互依赖对象的接口,而无须指定他们具体的类。它针对的是有多个产品的等级结构,产生产品族但不利于产生新的产品,而工厂方法模式针对的是一个产品的等级结构。
题9:设计模式有多少种,都有哪些设计模式?
Java有23种设计模式
设计模式总体分为三大类:
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
其实还有两类:并发型模式和线程池模式。
题10:Java 中什么是简单工厂模式?
简单工厂模式又称静态工厂方法模式,在简单工厂模式中,一个工厂类处于对产品类实例化调用的中心位置上,它决定那一个产品类应当被实例化,如同一个交通警察站在来往的车辆流中,决定放行那一个方向的车辆向那一个方向流动一样。
简单工厂模式的具体组成如下:
1)工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑,用来创建产品。
2)抽象产品角色:它一般是具体产品继承的父类或者实现的接口。
3)具体产品角色:工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现。
下面举例猫与狗吃饭的故事,具体代码实现如下:
1)创建共用接口,代码如下:
package com.yoodb;
public interface Dinner{
public void eat();
}
2)创建实现类,代码如下:
package com.yoodb;
public class CatDinner implements Dinner{
@Override
public void eat() {
// TODO Auto-generated method stub
System.out.println("小猫来吃饭了!");
}
}
package com.yoodb;
public class DogDinner implements Dinner{
@Override
public void eat() {
// TODO Auto-generated method stub
System.out.println("小狗来吃饭了!");
}
}
3)创建工厂,代码如下:
package com.yoodb;
public class DinnerFactory {
public Dinner produce(String animal){
if(animal.equals("cat")){
return new CatDinner();
}else if(animal.equals("dog")){
return new DogDinner();
}else{
System.out.println("请输入存在的动物!");
return null;
}
}
}
或者静态化,代码如下:
package com.yoodb;
public class DinnerFactory {
public static Dinner produce(String animal){
if(animal.equals("cat")){
return new CatDinner();
}else if(animal.equals("dog")){
return new DogDinner();
}else{
System.out.println("请输入存在的动物!");
return null;
}
}
}
4)main函数测试,代码如下:
package com.yoodb;
public class FactoryTest {
public static void main(String[] args) {
DinnerFactory factory = new DinnerFactory();
Dinner dinner = factory.produce("cat");
dinner.eat();
}
}
或者静态化调用,代码如下:
package com.yoodb;
public class FactoryTest {
public static void main(String[] args) {
Dinner dinner = DinnerFactory.produce("cat");
dinner.eat();
}
}