返回首页

未命名 1

分类:elysia
发布于:
阅读时间:10 分钟

在软件架构设计中,理解**接口(Interface)抽象类(Abstract Class)**的区别是消除代码混乱的关键。结合你当前的项目结构(AbstractStorageBunS3Storage),以下是它们的详细对比以及关于“继承”与“实现”的界定:

1. 抽象类 vs 接口:本质区别

特性接口 (Interface)抽象类 (Abstract Class)
本质意义能力的定义(能做什么)。它是一份契约,规定了外部调用的标准。事物的抽象(是什么)。它是多个具体子类的共性提取。
代码复用不能包含逻辑。只能定义方法名、参数和返回值(在 TS 中)。可以包含逻辑。可以编写通用的代码供子类直接使用。
成员变量不能定义实例变量(只能定义类型)。可以定义并存储状态(如 this.config)。
多继承一个类可以实现多个接口。一个类只能继承一个抽象类。

2. 哪些是“实现”,哪些是“继承”?

在你的代码库中,这两个概念分别对应以下结构:

继承 (Inheritance / Extends)

“继承”用于子类与父类之间。 当你希望子类自动拥有父类已经写好的方法时,使用继承。

  • 代码体现:使用关键字 extends

  • 你的项目示例

    • BunS3Storage 继承AbstractImageStorage

    • OSSStorage 继承AbstractStorage

    • 含义BunS3StorageAbstractImageStorage 的一种,它自动获得了父类中 generateUniqueFileNamevalidateFileSize 等已经写好的通用工具方法。

实现 (Implementation / Implements)

“实现”用于类与接口之间。 当你定义了一个标准,要求不同的类必须按照这个标准提供功能时,使用实现。

  • 代码体现:使用关键字 implements(虽然在你目前的 TS 代码中多采用直接继承抽象类的方式)。

  • 你的项目示例(如果你采用了 IStorage 方案):

    • BunS3StorageImpl 实现IStorage 接口。

    • 含义IStorage 规定了必须有 upload 方法,BunS3StorageImpl 保证提供这个方法的具体代码。


3. 在你项目中的实际应用建议

你之前的代码之所以感觉“混乱”,是因为你在继承关系上做了重复:

  1. 抽象类(继承的源头)

    • AbstractStorage 提供了基础的文件处理逻辑,如 processFileData

    • AbstractImageStorage 也提供了类似的逻辑,如 generateUniqueFileName

    • 建议:保留一个 AbstractStorage 即可。

  2. 具体类(实现者/继承者)

    • BunS3StorageLocalStorage 应该直接继承自唯一的抽象类 AbstractStorage

    • 它们通过重写(Override)父类的抽象方法(如 uploadFile)来提供具体实现

总结

  • 如果你想定义标准(比如:所有存储插件都必须有上传和删除功能),用接口抽象类中的抽象方法

  • 如果你想少写重复代码(比如:阿里云和本地存储都要生成随机文件名),把这段代码写在抽象类里,让子类去继承它。

在现代 TypeScript 开发中,通常直接使用一个抽象类作为顶层设计(如你的 AbstractStorage),因为它既能定义标准(抽象方法),又能复用代码(普通方法),比单纯的接口更实用。