第29周 面试题精讲(4)

Java面试题详解

一、简单工厂和工厂方法到底有哪些不同?

问题:简单工厂和工厂方法有哪些区别?

答案

  • 简单工厂
    • 通过一个工厂类实现对象创建,隐藏创建细节。
    • 所有对象创建基于一个方法,通过参数不同返回不同对象。
    • 客户端直接通过工厂方法获取对象,与工厂类解耦。
    • 新增产品时需修改工厂类代码,违反开闭原则。
  • 工厂方法
    • 提供抽象工厂接口,每种产品对应具体工厂。
    • 工厂接口定义创建方法,具体工厂实现该方法创建对应产品。
    • 客户端面对具体工厂实例化后调用方法获取对象。
    • 新增产品只需新增对应工厂和产品,不修改现有代码,符合开闭原则。

示例

java 复制代码
// 简单工厂
public class SimpleFactory {
    public static Product createProduct(String type) {
        if ("A".equals(type)) {
            return new ProductA();
        } else if ("B".equals(type)) {
            return new ProductB();
        }
        return null;
    }
}

// 工厂方法
public interface Factory {
    Product createProduct();
}

public class FactoryA implements Factory {
    @Override
    public Product createProduct() {
        return new ProductA();
    }
}

public class FactoryB implements Factory {
    @Override
    public Product createProduct() {
        return new ProductB();
    }
}

二、请介绍观察者模式,以及它的使用场景

问题:什么是观察者模式,它的应用场景有哪些?

答案

  • 定义:定义对象间一对多依赖关系,当一个对象状态改变时,所有依赖对象自动更新。
  • 角色
    • 目标(Subject):被观察对象,维护观察者列表,提供注册、移除、通知方法。
    • 观察者(Observer):抽象角色,定义更新接口。
    • 具体目标:实现目标类,维护自身状态,状态变化时通知观察者。
    • 具体观察者:实现观察者接口,维护指向目标的引用,实现更新逻辑。
  • 使用场景
    • 界面交互(如按钮点击事件)。
    • 数据变化联动(如在线拍卖新出价通知其他出价者)。
    • 消息订阅与发布(如群消息通知)。

示例

java 复制代码
// 目标类
public class Subject {
    private List<Observer> observers = new ArrayList<>();

    public void addObserver(Observer observer) {
        observers.add(observer);
    }

    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(this);
        }
    }

    // 模拟状态变化
    public void setState(String state) {
        // 状态改变逻辑
        notifyObservers();
    }
}

// 观察者接口
public interface Observer {
    void update(Subject subject);
}

// 具体观察者
public class ConcreteObserver implements Observer {
    @Override
    public void update(Subject subject) {
        // 更新逻辑
    }
}

三、静态代理与动态代理有什么区别?

问题:静态代理与动态代理的区别是什么?

答案

  • 静态代理
    • 手动创建代理类,实现与目标类相同接口。
    • 代理类持有目标类实例,通过代理类方法调用目标类方法,并在前后增加扩展逻辑。
    • 灵活性差,每新增一个目标类需创建对应代理类。
  • 动态代理
    • 使用反射机制或字节码增强技术动态生成代理类。
    • JDK动态代理基于接口,利用反射生成代理类,通过InvocationHandler处理方法调用。
    • CGlib动态代理基于目标类字节码生成子类,重写方法增加扩展逻辑。
    • 灵活性高,无需手动创建代理类,尤其适用于大量目标类的场景。

示例

java 复制代码
// 静态代理
public interface Service {
    void doSomething();
}

public class RealService implements Service {
    @Override
    public void doSomething() {
        // 目标方法
    }
}

public class ProxyService implements Service {
    private Service realService;

    public ProxyService(Service realService) {
        this.realService = realService;
    }

    @Override
    public void doSomething() {
        // 前置处理
        realService.doSomething();
        // 后置处理
    }
}

// 动态代理
public class DynamicProxy implements InvocationHandler {
    private Object target;

    public DynamicProxy(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 前置处理
        Object result = method.invoke(target, args);
        // 后置处理
        return result;
    }
}

// 使用动态代理
Service service = (Service) Proxy.newProxyInstance(
    Service.class.getClassLoader(),
    new Class[]{Service.class},
    new DynamicProxy(new RealService())
);

四、请说明适配器模式的作用

问题:适配器模式的作用是什么?

答案

  • 定义:将两个不兼容的接口进行衔接,使它们能够互联互通。
  • 应用场景
    • 系统迁移,上游接口变化,下游调用者需适配新接口。
    • 旧对象在新系统中运行,通过适配器完成接口转换。
  • 实现方式
    • 适配器实现目标接口。
    • 适配器持有目标对象。
    • 适配器重写目标接口方法,完成数据或接口转换。

示例

java 复制代码
// 目标接口
public interface TargetInterface {
    void operation();
}

// 需要适配的类
public class Adaptee {
    public void specificOperation() {
        // 特定操作
    }
}

// 适配器
public class Adapter implements TargetInterface {
    private Adaptee adaptee;

    public Adapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }

    @Override
    public void operation() {
        adaptee.specificOperation();
    }
}
相关推荐
考虑考虑3 小时前
Jpa使用union all
java·spring boot·后端
用户3721574261354 小时前
Java 实现 Excel 与 TXT 文本高效互转
java
浮游本尊5 小时前
Java学习第22天 - 云原生与容器化
java
渣哥6 小时前
原来 Java 里线程安全集合有这么多种
java
间彧6 小时前
Spring Boot集成Spring Security完整指南
java
间彧7 小时前
Spring Secutiy基本原理及工作流程
java
Java水解8 小时前
JAVA经典面试题附答案(持续更新版)
java·后端·面试
洛小豆10 小时前
在Java中,Integer.parseInt和Integer.valueOf有什么区别
java·后端·面试
前端小张同学10 小时前
服务器上如何搭建jenkins 服务CI/CD😎😎
java·后端
ytadpole10 小时前
Spring Cloud Gateway:一次不规范 URL 引发的路由转发404问题排查
java·后端