当前位置: 首页 > article >正文

第29周 面试题精讲(4)

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):抽象角色,定义更新接口。
    • 具体目标:实现目标类,维护自身状态,状态变化时通知观察者。
    • 具体观察者:实现观察者接口,维护指向目标的引用,实现更新逻辑。
  • 使用场景
    • 界面交互(如按钮点击事件)。
    • 数据变化联动(如在线拍卖新出价通知其他出价者)。
    • 消息订阅与发布(如群消息通知)。

示例

// 目标类
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动态代理基于目标类字节码生成子类,重写方法增加扩展逻辑。
    • 灵活性高,无需手动创建代理类,尤其适用于大量目标类的场景。

示例

// 静态代理
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())
);

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

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

答案

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

示例

// 目标接口
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();
    }
}

http://www.kler.cn/a/591684.html

相关文章:

  • KNN算法性能优化技巧与实战案例
  • vue网格布局--grid布局
  • 采用贝塞尔函数,进行恒定束宽波束形成算法
  • 如何用AI制作PPT,轻松实现高效演示
  • Node.js 和 Vite 配置文件中`__dirname`
  • Mysql如何解决幻读问题
  • 提示词prompt如何写
  • 【R语言】二项分布,正态分布,极大似然估计实现
  • 探索 Ollama Deep Researcher:本地网络研究助手的新选择
  • Git 本地常见快捷操作
  • 【html中文本超出元素的宽度后显示省略号...】
  • 【漫话机器学习系列】147.Softmax 归一化(Softmax Normalization)
  • 【数据库】掌握MySQL事务与锁机制-数据一致性的关键
  • 鸿蒙应用程序包HAP的开发与使用
  • TensorFlow 与 TensorFlow Lite:核心解析与层应用
  • angular中的路由传参
  • 什么是站群服务器?站群服务器应该怎么选?
  • Trae AI 能力:开启跨系统开发新时代,让远程协作与定制化开发触手可及
  • 【Docker】windows本地docker使用compose编排容器化部署mysql
  • [动手学习深度学习]26. 网络中的网络 NiN