Vue3+TypeScript实现工厂模式

89 阅读7分钟

Vue3+TypeScript实现工厂模式:用电脑组装厂带你飞

工厂模式,听起来是不是有点像“程序员开电脑组装厂”?别慌!它其实是前端开发中一种超实用的创建型设计模式,能帮你把对象的创建过程收拾得服服帖帖,让代码优雅又灵活。今天我们用Vue3和TypeScript,结合一个“组装电脑”的幽默例子,带你从头到尾搞懂简单工厂、工厂方法和抽象工厂模式,保证通俗易懂,笑中带学!

一、工厂模式是个啥?

想象你开了一家电脑组装厂,客户点单时喊:“来台游戏电脑!”你总不能每次都从零开始选CPU、装主板吧?工厂模式就像你的电脑组装流水线:客户(代码调用者)只管下单,工厂(代码逻辑)负责生产电脑(对象),至于用啥CPU、显卡,客户完全不用操心。这不就是解耦的精髓吗?

工厂模式有三种“流水线”:简单工厂、工厂方法和抽象工厂。我们用Vue3+TypeScript实现一个前端版的“电脑组装厂”,让你边组装电脑边学设计模式!

二、工厂模式的三大形态

1. 简单工厂模式:一个柜台全搞定

定义:简单工厂就像电脑组装厂的前台小哥,客户点啥(传个参数),小哥就从车间端出对应的电脑(返回对象)。简单粗暴,但所有逻辑都挤在一个工厂类里。

前端场景:假设你用Vue3开发一个电脑选购页面,客户选择电脑类型,前端通过工厂生成对应的电脑组件或数据。

// src/models/Computer.ts
export interface Computer {
  name: string;
  assemble(): string;
}

// 游戏电脑
export class GamingComputer implements Computer {
  name = 'Gaming Computer';
  assemble() {
    return `💻 组装${this.name}:高性能CPU、RTX显卡,畅玩3A大作!`;
  }
}

// 办公电脑
export class OfficeComputer implements Computer {
  name = 'Office Computer';
  assemble() {
    return `💻 组装${this.name}:稳定CPU、集成显卡,办公无压力!`;
  }
}

// src/factories/SimpleComputerFactory.ts
export class SimpleComputerFactory {
  static createComputer(type: string): Computer {
    switch (type) {
      case 'gaming':
        return new GamingComputer();
      case 'office':
        return new OfficeComputer();
      default:
        throw new Error('😅 老板,这个电脑我们厂里没得卖!');
    }
  }
}

// src/components/ComputerOrder.vue
<script setup lang="ts">
import { ref } from 'vue';
import { SimpleComputerFactory } from '../factories/SimpleComputerFactory';

const computerType = ref('gaming');
const computerMessage = ref('');

const orderComputer = () => {
  try {
    const computer = SimpleComputerFactory.createComputer(computerType.value);
    computerMessage.value = computer.assemble();
  } catch (error) {
    computerMessage.value = (error as Error).message;
  }
};
</script>

<template>
  <div>
    <h2>简单工厂点单台</h2>
    <select v-model="computerType">
      <option value="gaming">游戏电脑</option>
      <option value="office">办公电脑</option>
    </select>
    <button @click="orderComputer">下单!</button>
    <p>{{ computerMessage }}</p>
  </div>
</template>

幽默讲解:简单工厂就像你厂里的全能小哥,啥电脑都会组装,但忙起来容易手忙脚乱(逻辑全塞在一个类里)。如果新加个“服务器电脑”,得改工厂代码,违反了“开闭原则”(对扩展开放,对修改关闭)。但它简单好上手,适合小型电脑组装厂!

优点

  • 代码简单,适合小型项目。
  • 客户端(Vue组件)只管下单,不用知道电脑咋组装的。

缺点

  • 新增电脑类型要改工厂代码,可扩展性差。
  • 逻辑集中在工厂类,规模大了容易变“意大利面条代码”。

2. 工厂方法模式:每种电脑专属生产线

定义:工厂方法模式就像给每种电脑开一条专属生产线(子类),每条生产线只组装一种电脑,客户找对应的生产线下单。

前端场景:在Vue3中,假设不同电脑厂(组件)有自己的组装逻辑,工厂方法让每个厂决定生产啥电脑。

// src/models/Computer.ts
export interface Computer {
  name: string;
  assemble(): string;
}

export class GamingComputer implements Computer {
  name = 'Gaming Computer';
  assemble() {
    return `💻 组装${this.name}:高频CPU、RTX显卡,游戏性能拉满!`;
  }
}

export class OfficeComputer implements Computer {
  name = 'Office Computer';
  assemble() {
    return `💻 组装${this.name}:低功耗CPU、集成显卡,办公利器!`;
  }
}

// src/factories/ComputerStore.ts
export abstract class ComputerStore {
  abstract createComputer(type: string): Computer;

  orderComputer(type: string) {
    const computer = this.createComputer(type);
    return computer.assemble();
  }
}

export class GamingComputerStore extends ComputerStore {
  createComputer(type: string): Computer {
    if (type === 'gaming') {
      return new GamingComputer();
    }
    throw new Error('😓 游戏厂只组装游戏电脑,别点别的!');
  }
}

export class OfficeComputerStore extends ComputerStore {
  createComputer(type: string): Computer {
    if (type === 'office') {
      return new OfficeComputer();
    }
    throw new Error('😓 办公厂专做办公电脑,别的没有!');
  }
}

// src/components/ComputerStore.vue
<script setup lang="ts">
import { ref } from 'vue';
import { GamingComputerStore, OfficeComputerStore } from '../factories/ComputerStore';

const storeType = ref('gaming');
const computerType = ref('gaming');
const computerMessage = ref('');

const orderComputer = () => {
  try {
    const store = storeType.value === 'gaming' ? new GamingComputerStore() : new OfficeComputerStore();
    computerMessage.value = store.orderComputer(computerType.value);
  } catch (error) {
    computerMessage.value = (error as Error).message;
  }
};
</script>

<template>
  <div>
    <h2>工厂方法点单台</h2>
    <select v-model="storeType">
      <option value="gaming">游戏电脑厂</option>
      <option value="office">办公电脑厂</option>
    </select>
    <select v-model="computerType">
      <option value="gaming">游戏电脑</option>
      <option value="office">办公电脑</option>
    </select>
    <button @click="orderComputer">下单!</button>
    <p>{{ computerMessage }}</p>
  </div>
</template>

幽默讲解:工厂方法就像开了好几家连锁电脑厂,每家厂专精一种电脑,互不干扰。想加新电脑?开个新厂(新子类)就行,老厂代码不动,符合“开闭原则”。但厂多了(子类多了),代码量也上去了,适合中型电脑组装帝国!

优点

  • 符合“开闭原则”,新增电脑类型只需加新厂(子类)。
  • 每种电脑的创建逻辑隔离,代码更清晰。

缺点

  • 每种电脑都要建一个工厂类,代码量增加。
  • 客户端需要知道具体工厂类(电脑厂)。

3. 抽象工厂模式:一站式配件生产线

定义:抽象工厂模式像个“电脑配件超市”,不仅生产电脑,还提供整套配件(CPU、显卡、主板等),确保每种电脑的配件风格统一。

前端场景:在Vue3中,假设电脑厂需要一整套配件(UI组件、数据模型等),抽象工厂负责提供整套风格一致的“配件”。

// src/models/Components.ts
export interface CPU {
  getType(): string;
}

export interface GPU {
  getType(): string;
}

export class GamingCPU implements CPU {
  getType() {
    return '高性能游戏CPU';
  }
}

export class GamingGPU implements GPU {
  getType() {
    return 'RTX系列显卡';
  }
}

export class OfficeCPU implements CPU {
  getType() {
    return '低功耗办公CPU';
  }
}

export class OfficeGPU implements GPU {
  getType() {
    return '集成显卡';
  }
}

// src/factories/ComputerComponentFactory.ts
export interface ComputerComponentFactory {
  createCPU(): CPU;
  createGPU(): GPU;
}

export class GamingComputerComponentFactory implements ComputerComponentFactory {
  createCPU(): CPU {
    return new GamingCPU();
  }
  createGPU(): GPU {
    return new GamingGPU();
  }
}

export class OfficeComputerComponentFactory implements ComputerComponentFactory {
  createCPU(): CPU {
    return new OfficeCPU();
  }
  createGPU(): GPU {
    return new OfficeGPU();
  }
}

// src/components/ComputerMaker.vue
<script setup lang="ts">
import { ref } from 'vue';
import { GamingComputerComponentFactory, OfficeComputerComponentFactory } from '../factories/ComputerComponentFactory';

const factoryType = ref('gaming');
const computerMessage = ref('');

const makeComputer = () => {
  const factory = factoryType.value === 'gaming' ? new GamingComputerComponentFactory() : new OfficeComputerComponentFactory();
  const cpu = factory.createCPU();
  const gpu = factory.createGPU();
  computerMessage.value = `💻 电脑配件:${cpu.getType()} + ${gpu.getType()}`;
};
</script>

<template>
  <div>
    <h2>抽象工厂配件台</h2>
    <select v-model="factoryType">
      <option value="gaming">游戏配置</option>
      <option value="office">办公配置</option>
    </select>
    <button @click="makeComputer">组装电脑!</button>
    <p>{{ computerMessage }}</p>
  </div>
</template>

幽默讲解:抽象工厂就像个“电脑配件批发市场”,你要游戏配置?给你整套游戏CPU+显卡!要办公配置?给你办公全套!客户下单时不用管配件细节,直接拿来组装电脑,完美统一风格!但这“批发市场”代码有点复杂,适合大型连锁电脑帝国。

优点

  • 保证一整套配件风格一致(例如UI组件风格统一)。
  • 支持复杂对象家族的创建,扩展性强。

缺点

  • 代码结构复杂,类和接口数量多。
  • 新增产品族需要改动较多代码。

三、应用场景

工厂模式在前端开发中超级实用,尤其在Vue3项目中:

  • 动态组件加载:根据用户选择加载不同Vue组件(例如不同风格的表单)。
  • 主题切换:抽象工厂可生成整套主题(按钮、输入框、卡片等),确保UI风格统一。
  • 数据模型生成:根据API返回的数据类型,生成对应的TypeScript模型实例。
  • 插件系统:为不同功能模块提供统一的插件创建接口,方便扩展。

幽mer例子:想象你的Vue3项目是个电脑组装厂,用户点“高性能模式”电脑(主题),工厂直接吐出一整套高性能风格组件;点“办公助手”电脑,工厂给你生成办公优化组件。客户(代码)只管用,工厂管生产!

四、适用性

  • 需要动态创建对象:例如Vue组件根据用户输入动态加载。
  • 需要解耦创建逻辑:隐藏组件或数据模型的创建细节,让代码更灵活。
  • 支持可扩展产品:新增组件或主题时,只需加新工厂,不改现有代码。
  • 统一对象家族:抽象工厂适合生成整套UI组件或数据模型,保持一致性。

五、注意事项

  1. 选择合适的工厂模式

    • 小项目用简单工厂,快速上手。
    • 中型项目用工厂方法,扩展性更好。
    • 大型项目用抽象工厂,适合复杂对象家族。
  2. TypeScript的优势

    • 用接口(interface)定义电脑和配件,确保类型安全。
    • 善用TypeScript的类型推断,减少运行时错误。
  3. ** композиция考虑**:

    • 工厂模式增加了一层间接调用,注意不要过度封装。
    • 对于简单组件,考虑直接实例化,省去工厂开销。
  4. 社区支持

    • Vue3生态(如VueUse、Pinia)中常用工厂模式思想,学习相关源码能加深理解。
    • 参考TypeScript官方文档,优化类型定义。

幽默提示:别让你的工厂变成“电脑黑店”,生产一堆没人要的怪配置电脑(不必要的复杂逻辑)!保持简单,客户才爱买!

六、总结

工厂模式就像前端开发者的“电脑组装流水线”,让对象创建变得优雅又灵活。在Vue3+TypeScript项目中,简单工厂适合快速开发,工厂方法适合扩展性需求,抽象工厂适合复杂UI或数据模型的统一管理。