2025高频面试设计模型总结篇

文章目录


设计模型概念

设计模式是前人总结的软件设计经验和解决问题的最佳方案,它们为我们提供了一套可复用、易维护、可扩展的设计思路。

(1)定义: 设计模式是一套经过验证的解决特定设计问题的模板,这些模板并不是代码,而是对类、对象以及它们之间如何协作的抽象描述。

(2)目的: 降低系统的耦合性、提高代码的复用性和可维护性,以及应对不断变化的需求。

(3)设计模式主要可以分为三大类:创建型、结构型和行为型。以下是一些在 JAVA 开发工程师面试中常见的设计模式:

1. 创建型模式

  • 单例模式(Singleton Pattern)
    • 定义: 确保一个类只有一个实例,并提供一个全局访问点。
    • 使用场景: 当系统中需要唯一一个对象来协调各部分工作,如配置管理、线程池、日志对象等。
  • 工厂模式(Factory Pattern)
    • 定义: 定义一个用于创建对象的接口,由子类决定实例化哪一个类。
    • 使用场景: 当系统中有大量对象创建需求,且对象之间具有共同接口或父类时,可以使用工厂模式封装对象的创建逻辑,降低耦合。
  • 建造者模式(Builder Pattern)
    • 定义: 将一个复杂对象的构建过程与它的表示分离,使得同样的构建过程可以创建不同的表示。
    • 使用场景: 当一个对象的构造过程复杂,涉及多个步骤或多个可选参数时,使用建造者模式能让代码更清晰、更易扩展。

2. 结构型模式

  • 适配器模式(Adapter Pattern)
    • 定义: 将一个类的接口转换成客户期望的另一个接口,使得原本因接口不兼容而不能一起工作的类可以协同工作。
    • 使用场景: 当你想要使用一些现有的类,但它们的接口与当前系统不匹配时,可以使用适配器模式。
  • 装饰器模式(Decorator Pattern)
    • 定义: 动态地给一个对象添加一些额外的职责,而不影响其他对象。
    • 使用场景: 当系统需要在不改变原有对象结构的情况下增加功能时,装饰器模式提供了一种灵活的解决方案。
  • 外观模式(Facade Pattern)
    • 定义: 为复杂的子系统提供一个简单的接口,使得客户端可以更容易地使用子系统。
    • 使用场景: 当系统中存在多个相互依赖的类或接口时,通过外观模式可以将复杂性隐藏起来,提供一个统一的接口。

3. 行为型模式

  • 观察者模式(Observer Pattern)
    • 定义: 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,其相关依赖对象会收到通知并自动更新。
    • 使用场景: 当一个对象状态的变化需要通知其他对象,且不知道这些对象的数量或具体类型时,可以使用观察者模式,如事件监听机制。
  • 策略模式(Strategy Pattern)
    • 定义: 定义一系列算法,把它们一个个封装起来,并使它们可以互换。
    • 使用场景: 当系统中存在多种算法或行为,并且需要根据具体情况选择不同的算法时,策略模式能使算法切换更为灵活。
  • 模板方法模式(Template Method Pattern)
    • 定义: 在一个方法中定义一个算法的骨架,将某些步骤延迟到子类中实现,从而使子类可以不改变算法结构的情况下重新定义算法的某些步骤。
    • 使用场景: 当多个子类有很多相同的行为,只在细节上略有不同的情况下,模板方法模式可以复用公共代码,同时让子类实现具体差异部分。
  • 代理模式(Proxy Pattern)
    • 定义: 为其他对象提供一种代理以控制对这个对象的访问。
    • 使用场景: 当你需要在访问对象时附加一些额外操作(如懒加载、安全控制、缓存等)时,可以使用代理模式来控制对象的访问。

单例模式

确保一个类只有一个实例,并提供一个全局访问点。
Spring 框架中,默认 bean 的作用域为单例(singleton),即在整个应用上下文中只存在一个实例。

如 Spring 的 ApplicationContext 在加载 bean 时会确保同一个 bean 只被实例化一次(除非配置为其他作用域)。

java 复制代码
public class Singleton {
    // 饿汉式单例
    private static volatile Singleton instance = null;

    // 私有构造方法,防止外部实例化
    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {
           sychronized(Singleton.class) {
               if (instance == null) {
                  instance = new Singleton();
               }
           }
        }
        return instance;
    }
}

工厂模式

定义一个用于创建对象的接口,由子类决定实例化哪一个类。
Spring 的 BeanFactoryApplicationContext 实际上就是一个工厂,通过配置文件或注解来实例化并管理对象。

FactoryBean 接口允许开发者自定义 bean 的创建逻辑。

java 复制代码
// 定义产品接口
public interface Product {
    void use();
}

// 具体产品A
public class ConcreteProductA implements Product {
    @Override
    public void use() {
        System.out.println("使用产品A");
    }
}

// 具体产品B
public class ConcreteProductB implements Product {
    @Override
    public void use() {
        System.out.println("使用产品B");
    }
}

// 工厂类
public class ProductFactory {
    public static Product createProduct(String type) {
        if ("A".equals(type)) {
            return new ConcreteProductA();
        } else if ("B".equals(type)) {
            return new ConcreteProductB();
        }
        throw new IllegalArgumentException("未知产品类型:" + type);
    }
}

// 测试入口
public class FactoryDemo {
    public static void main(String[] args) {
        Product productA = ProductFactory.createProduct("A");
        productA.use();
        Product productB = ProductFactory.createProduct("B");
        productB.use();
    }
}

策略模式

定义一系列算法,把它们一个个封装起来,并使它们可以互换。

当系统中有多种算法或行为需要在运行时动态切换时,可以使用策略模式。

Spring MVC 中,通过 HandlerAdapter 接口支持多种类型的控制器(如 @Controller@RestController 等),根据实际请求选择合适的适配器来处理业务逻辑。

事务管理、缓存策略等也采用了类似思想,通过接口和多种实现来动态选择行为。

java 复制代码
// 策略接口
public interface Strategy {
    void execute();
}

// 具体策略A
public class ConcreteStrategyA implements Strategy {
    @Override
    public void execute() {
        System.out.println("执行策略A");
    }
}

// 具体策略B
public class ConcreteStrategyB implements Strategy {
    @Override
    public void execute() {
        System.out.println("执行策略B");
    }
}

// 上下文,使用策略
public class Context {
    private Strategy strategy;

    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    public void executeStrategy() {
        strategy.execute();
    }
}

// 测试入口
public class StrategyDemo {
    public static void main(String[] args) {
        Context contextA = new Context(new ConcreteStrategyA());
        contextA.executeStrategy();

        Context contextB = new Context(new ConcreteStrategyB());
        contextB.executeStrategy();
    }
}

责任链模式

将请求的处理对象连成一条链,每个处理者持有对下一个处理者的引用,按顺序处理请求或将其传递给下一个处理者。

当一个请求可能由多个对象处理,但不清楚到底由哪一个对象处理时,可采用责任链模式进行动态分派。

在 Spring Security 中,FilterChainProxy 维护了一系列过滤器(Filter),每个过滤器依次处理 HTTP 请求,决定是否放行、拒绝或进一步处理。

Spring MVC 中的拦截器链(HandlerInterceptor)也是一个责任链,每个拦截器按顺序处理请求的预处理和后处理工作。

java 复制代码
// 责任链中的抽象处理者
public abstract class Handler {
    protected Handler next;

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

    // 处理请求
    public abstract void handleRequest(String request);
}

// 具体处理者A
public class ConcreteHandlerA extends Handler {
    @Override
    public void handleRequest(String request) {
        if (request.contains("A")) {
            System.out.println("ConcreteHandlerA 处理请求: " + request);
        } else if (next != null) {
            next.handleRequest(request);
        }
    }
}

// 具体处理者B
public class ConcreteHandlerB extends Handler {
    @Override
    public void handleRequest(String request) {
        if (request.contains("B")) {
            System.out.println("ConcreteHandlerB 处理请求: " + request);
        } else if (next != null) {
            next.handleRequest(request);
        }
    }
}

// 测试责任链模式
public class ChainDemo {
    public static void main(String[] args) {
        Handler handlerA = new ConcreteHandlerA();
        Handler handlerB = new ConcreteHandlerB();

        // 设置责任链顺序
        handlerA.setNext(handlerB);

        // 测试请求:包含 "B" 的请求由 ConcreteHandlerB 处理
        handlerA.handleRequest("Request with B");
        // 测试请求:包含 "A" 的请求由 ConcreteHandlerA 处理
        handlerA.handleRequest("Request with A");
    }
}

相关推荐
千千寰宇4 小时前
[设计模式/Java/多线程] 设计模式之单例模式【9】
设计模式·操作系统-进程/线程/并发
uhakadotcom5 小时前
视频直播与视频点播:基础知识与应用场景
后端·面试·架构
拉不动的猪5 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪5 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
uhakadotcom6 小时前
快速开始使用 n8n
后端·面试·github
uhakadotcom6 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom6 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom6 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom7 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom7 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试