eBay 面试真题:设计一个可扩展的 Logger – VO 辅助 – 代面试 – 一亩三分地

这是一道看起来很简单、实际重点在软件设计能力的题目。面试官并不关心日志格式、文件轮转或复杂配置,而是想看候选人能否设计出一个稳定、容易扩展的接口。

Implement a simple logger that can write messages to different destinations — a file or the console. It should be easily extensible to support new destinations without modifying the core logger logic.

实现一个简单的日志记录器,可以把消息写入不同位置,例如控制台或文件。

系统还需要方便扩展。未来增加数据库、网络服务或其他日志目的地时,不应该修改 Logger 的核心逻辑。

例如:

Logger:
  ConsoleDestination
  FileDestination

logger.log("Hello")

调用一次 log 后,消息会同时发送到控制台和文件。

未来增加 DatabaseDestination 时,只需要实现新的目的地,不需要修改 Logger。

解题思路

Logger 不应该自己判断消息要写入控制台、文件还是数据库。它只负责保存一组日志目的地,并把收到的消息发送给它们。

所有目的地都遵循同一个接口,例如:

write(message)

控制台目的地负责打印消息,文件目的地负责写入文件。Logger 只依赖这个统一接口,不依赖任何具体实现。

这样,Logger 的核心逻辑始终保持不变:

for each destination:
    destination.write(message)

新增日志目的地时,只需要创建一个实现相同接口的新类。这体现了一个很重要的设计原则:系统应该允许通过增加新实现来扩展功能,而不是不断修改已经稳定的核心代码。

关键追问

候选人一开始已经提出了正确的基本结构:Logger 内部保存一个 destinations 集合,每个 destination 自己实现 write 方法。

面试官随后向 destinations 中加入了一个普通对象。这个对象没有 write 方法,因此程序在真正发送日志时才出现运行时错误。

候选人最初考虑使用异常处理捕获错误,或者发现无效对象后将其删除。面试官继续追问:能否从设计上阻止这种错误,而不是等到发送日志时再处理?

更好的答案是定义统一的接口或抽象类。所有日志目的地必须实现 write 方法,不符合要求的对象不应该被当作合法 destination 使用。这样可以让错误更早暴露,也能让 Logger 的使用方式更加清晰。

容易出现的问题

一种常见写法是在 Logger 内部判断类型:

if destination is console
if destination is file
if destination is database

这种实现暂时可以运行,但每增加一种目的地,都必须修改 Logger。系统规模扩大后,核心类会不断出现新的条件分支。

另一种问题是完全依赖动态调用,默认所有对象都有 write 方法。代码虽然简短,但错误通常要到运行时才会被发现。

异常捕获也不能替代良好的接口设计。异常处理可以决定某个目的地失败后是否继续写入其他目的地,但不能解决传入对象本身不符合约定的问题。

Csoahelp 提供技术面试实时文本辅助与 Mock Interview,帮助候选人在算法、系统设计和项目追问中更清晰地表达思路。

我们也有代面试,面试辅助,OA代写等服务助您早日上岸~

Leave a Reply

Your email address will not be published. Required fields are marked *