---
url: /notes/面试/设计模式/index.md
---
\[TOC]

## 单例模式

[请解释什么是单例模式，并给出一个使用场景 - 设计模式面试题 - 面试鸭 - 程序员求职面试刷题神器](https://www.mianshiya.com/bank/1801559627969929217/question/1801818689919852545)

确保一个类在整个程序运行过程中只有一个实例，并提供全局访问，延迟加载

最佳实践：双重检查锁定

线程池、日志记录、配置文件管理

## 工厂模式

[请描述简单工厂模式的工作原理。 - 设计模式面试题 - 面试鸭 - 程序员求职面试刷题神器](https://www.mianshiya.com/bank/1801559627969929217/question/1802171196621791233)

根据传入的参数创建并返回不同类型的对象实例

## 建造者模式

[什么是建造者模式？一般用在什么场景？ - 设计模式面试题 - 面试鸭 - 程序员求职面试刷题神器](https://www.mianshiya.com/bank/1801559627969929217/question/1802171325634387970)

将复杂对象的构建过程与其表示分离。如报表对象的生成

## 适配器模式

[什么是适配器模式？一般用在什么场景？ - 设计模式面试题 - 面试鸭 - 程序员求职面试刷题神器](https://www.mianshiya.com/bank/1801559627969929217/question/1802171589225422850#heading-0)

将一个类的接口转换成期望的另一个接口

已有代码无法修改，第三方库的整合、统一接口

## 装饰器模式

[什么是装饰器模式？一般用在什么场景？ - 设计模式面试题 - 面试鸭 - 程序员求职面试刷题神器](https://www.mianshiya.com/bank/1801559627969929217/question/1803766849256890369#heading-0)

不改变现有类的情况下动态地增加新功能

## 模板模式

[什么是模板方法模式？一般用在什么场景？ - 设计模式面试题 - 面试鸭 - 程序员求职面试刷题神器](https://www.mianshiya.com/bank/1801559627969929217/question/1802939152477790209)

抽象类定义了需要的业务骨架，具体步骤由子类实现

## 策略模式

[什么是策略模式？一般用在什么场景？ - 设计模式面试题 - 面试鸭 - 程序员求职面试刷题神器](https://www.mianshiya.com/bank/1801559627969929217/question/1803305303140720641)

避免大量的if else、switch，实现解耦

## 外观模式（门面模式）

[什么是外观模式？一般用在什么场景？ - 设计模式面试题 - 面试鸭 - 程序员求职面试刷题神器](https://www.mianshiya.com/bank/1801559627969929217/question/1802557443223658498)

提供统一的接口，简化客户端与多个子系统之间的交互

## 代理模式

[什么是代理模式？一般用在什么场景？ - 设计模式面试题 - 面试鸭 - 程序员求职面试刷题神器](https://www.mianshiya.com/bank/1801559627969929217/question/1802557695141945346)

在不改变原始对象的前提下，引入代理对象来控制对原始对象的访问。如日志、远程调用

## 责任链模式

[什么是责任链模式？一般用在什么场景？ - 设计模式面试题 - 面试鸭 - 程序员求职面试刷题神器](https://www.mianshiya.com/bank/1801559627969929217/question/1803305518413373442#heading-7)

简单易懂的例子：请假审批流程假设公司有一个请假审批流程，员工请假需要经过不同级别的领导审批：

1. 小组长：可以批准不超过3天的请假。

2. 部门经理：可以批准不超过7天的请假。

3. 总经理：可以批准超过7天的请假。

   如果员工请假天数超过某个领导的权限范围，请求会自动传递给下一个更高权限的领导。

   实现步骤：

   1. 定义一个抽象的处理者类：包含处理请求的方法和指向下一个处理者的引用。
   2. 创建具体的处理者类：实现抽象类的方法，决定是否处理请求以及如何传递请求。
   3. 构建责任链：将具体处理者对象连接起来，形成一条链。
   4. 发起请求：从链的起点开始处理请求。

```java
// 抽象处理者类
abstract class Handler {
    protected Handler nextHandler; // 下一个处理者

    // 设置下一个处理者
    public void setNextHandler(Handler nextHandler) {
        this.nextHandler = nextHandler;
    }

    // 处理请求的方法
    public abstract void handleRequest(int days);
}

// 小组长
class TeamLeader extends Handler {
    @Override
    public void handleRequest(int days) {
        if (days <= 3) {
            System.out.println("TeamLeader approved " + days + " days of leave.");
        } else {
            // 超出权限范围，传递给下一个处理者
            if (nextHandler != null) {
                nextHandler.handleRequest(days);
            } else {
                System.out.println("No one can approve " + days + " days of leave.");
            }
        }
    }
}

// 部门经理
class DepartmentManager extends Handler {
    @Override
    public void handleRequest(int days) {
        if (days <= 7) {
            System.out.println("DepartmentManager approved " + days + " days of leave.");
        } else {
            // 超出权限范围，传递给下一个处理者
            if (nextHandler != null) {
                nextHandler.handleRequest(days);
            } else {
                System.out.println("No one can approve " + days + " days of leave.");
            }
        }
    }
}

// 总经理
class GeneralManager extends Handler {
    @Override
    public void handleRequest(int days) {
        System.out.println("GeneralManager approved " + days + " days of leave.");
    }
}

// 测试代码
public class ChainOfResponsibilityExample {
    public static void main(String[] args) {
        // 创建具体的处理者对象
        Handler teamLeader = new TeamLeader();
        Handler departmentManager = new DepartmentManager();
        Handler generalManager = new GeneralManager();

        // 构建责任链
        teamLeader.setNextHandler(departmentManager);
        departmentManager.setNextHandler(generalManager);

        // 发起请求
        System.out.println("Request for 2 days of leave:");
        teamLeader.handleRequest(2);

        System.out.println("\nRequest for 5 days of leave:");
        teamLeader.handleRequest(5);

        System.out.println("\nRequest for 10 days of leave:");
        teamLeader.handleRequest(10);
    }
}
```

```java
Request for 2 days of leave:
TeamLeader approved 2 days of leave.

Request for 5 days of leave:
DepartmentManager approved 5 days of leave.

Request for 10 days of leave:
GeneralManager approved 10 days of leave.
```
