前端开发设计模式:工厂模式(Factory Pattern)【下】

承接上文:《前端开发设计模式:工厂模式(Factory Pattern)【上 】

三、常用场景

简单工厂模式

 场景特点:适用于创建对象逻辑简单,且产品类型相对较且需求相对稳定,不经常添加新的产品类型的场景。

具体应用

例1:创建不同类型的 表单/按钮 组件,组件类型固定且后续不太可能有大量新类型添加

<!-- text-input.vue  子组件 应该存在多个 -->
<template>
  <input type="text" />
</template>
<script setup lang="ts" name="TextInput"></script>
// factories.js --- 创建工厂函数
import TextInput from '@/components/text-input.vue'
import SelectInput from '@/components/select-input.vue'

const componentFactory = {
    createComponent(type){
        const components = {
            'A': TextInput,
            'B': SelectInput
            // 可扩展其他组件
        }
        if(!components[type]){
            console.error(`未找到类型为${type}的组件`)
            return null // 或返回默认组件
        }
        return components[type]
    }
}
export default componentFactory
<!-- parent.vue --- 在组件中使用工厂模式 -->
<template>
  <div>
    <!-- 动态组件渲染 -->
    <component :is="currentComponent" v-if="currentComponent"></component>
  </div>
</template>
<script setup lang="ts">
import componentFactory from "./factories.js";

const props = defineProps({
  type: {
    type: String,
    default: "",
  },
});

// 工厂函数动态获取组件
const currentComponent = computed(() => {
  return componentFactory.createComponent(props.type);
});
</script>

从这个示例中可以明确看出工厂模式的优点就是将创建与使用分离。

 

例2:根据用户的权限级别创建不同的导航菜单组件

// menu-factory.js

// 定义基础导航菜单类
class BaseNavMenu {
  constructor() {
    this.lists = [];
  }
  render() {
    return this.lists;
  }
}

// 定义普通用户导航菜单类
class NormalUserNavMenu extends BaseNavMenu {
  constructor() {
    super();
    this.lists = [
      {
        name: "首页",
        path: "/",
      },
      {
        name: "关于我们",
        path: "/about",
      },
      {
        name: "联系我们",
        path: "/contact",
      },
    ];
  }
}

// 定义管理员用户导航菜单类
class AdminUserNavMenu extends BaseNavMenu {
  constructor() {
    super();
    this.lists = [
      {
        name: "首页",
        path: "/",
      },
      {
        name: "用户管理",
        path: "/users",
      },
      {
        name: "文章管理",
        path: "/articles",
      },
      {
        name: "关于我们",
      },
    ];
  }
}

// 定义导航菜单工厂函数
function NavMenuFactory(role){
    switch (role) {
        case 1:
            return new NormalUserNavMenu();
        case 0:
            return new AdminUserNavMenu();
        default:
            throw new Error('Invalid role');
    }
}
<!-- menu.vue -->
<template>
  <div class="menu-container">
    <div
      v-for="item in menuList"
      :key="item.name"
      @click.stop="toPage(item.path)"
    >
      {{ item.name }}
    </div>
  </div>
</template>
<script lang="ts" setup>
import { ref } from "vue";
import menuFactory from "./menu-factory.js";

const props = defineProps({
  userLevel: {
    type: Number,
    required: true,
  },
});

const menuList = ref([]);

menuList.value = menuFactory(props.userLevel).render();
</script>

 

例3:游戏中创建不同的游戏角色。--- 代码差不多就不实现了。

 

工厂方法模式

将对象的创建抽成一个抽象方法,由具体子类实现这个方法,符合开闭原则。

场景特点:适用于创建对象的逻辑较为复杂,且产品类型较多,需频繁扩展的场景

具体应用

 例1:电商系统中,商品类型不断增加,比如有普通商品,促销商品,限时抢购商品等,每种商品的创建逻辑不同。

// factories.js

import EmptyComponent from "./empty-component.vue";
import NormalComponent from "./normal-component.vue";
import PromotionComponent from "./promotion-component.vue";

class Product {
  showComponents() {
    console.log("该方法必须被重写");
    return EmptyComponent;
  }
}
// 产品子类
class NormalProduct extends Product {
  showComponents() {
    return NormalComponent;
  }
}
class promotionProduct extends Product {
  showComponents() {
    return PromotionComponent;
  }
}

class ProductFactory {
  createProduct() {
    throw new Error("抽象类不能实例化,该方法必须重写");
  }
}
class NormalProductFactory extends ProductFactory {
  createProduct() {
    return new NormalProduct();
  }
}
class PromotionProductFactory extends ProductFactory {
  createProduct() {
    return new promotionProduct();
  }
}

export { NormalProductFactory, PromotionProductFactory };
<!-- detail.vue -->
<template>
  <div class="detail-container">
    <component :is="currentComponents"></component>
  </div>
</template>
<script lang="ts" setup>
import { NormalProductFactory, PromotionProductFactory } from "./factories.js";
const props = defineProps({
  detail: {
    type: Object,
    default: () => {},
    required: true,
  },
});
const currentComponents = computed(() => {
  let _facotry;
 // 这里可以用简单工厂模式的思想,写个方法
if (props.detail.productType === "promotion") { _facotry = new PromotionProductFactory(); } else { _facotry = new NormalProductFactory(); } const _computer = _facotry.createComputer(); return _computer.showComponents(); }); </script>

 

例2:日志系统中,创建不同类型的日志记录器。--- 代码差不多就不实现了。

 

抽象工厂模式

抽象工厂模式提供了一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。它可以创建多个不同类型的产品族,符合开闭原则,但代码复杂度较高。

 场景特点:适用于需要创建一组相关的对象,且这些对象之间存在一定的依赖关系或约束条件的场景。

具体应用:
例1:创建不同风格的 UI 组件
。比如根据不同的主题创建一组相关的UI组件。

// ui-theme-factory.js
// 产品族 class Button { render() { throw new Error("该方法必须被重写!"); } } class LightButton extends Button { render() { console.log("LightButton"); } } class DarkButton extends Button { render() { console.log("DarkButton"); } }
// 产品族 class Input { render() {
throw new Error("该方法必须被重写!"); } } class LightInput extends Input { render() { console.log("LightInput"); } } class DarkInput extends Input { render() { console.log("DarkInput"); } } class ThemeFactory { createButton() { throw new Error("该方法必须被重写!"); } createInput() { throw new Error("该方法必须被重写!"); } } class LightThemeFactory extends ThemeFactory { createButton() { return new LightButton(); } createInput() { return new LightInput(); } } class DarkThemeFactory extends ThemeFactory { createButton() { return new DarkButton(); } createInput() { return new DarkInput(); } } const lightFactory = new LightThemeFactory(); const lightButton = lightFactory.createButton(); const lightInput = lightFactory.createInput(); lightButton.render(); // LightButton lightInput.render(); // LightInput

 

例2:游戏中创建不同风格的游戏场景。比如沙漠场景、森林场景等。每个场景都有一组相关的游戏元素,如地形、怪物、道具等。

 代码逻辑差不多,就不实现了。

 

四、如何选择

从上文中可以得出以下结论:

 1、从适用场景考虑

简单工厂模式:产品种类较少,且不经常扩展

工厂方法模式:产品种类较多,需要频繁扩展

抽象工厂模式:需要同时创建多个关联产品

 

2、从产品类型和关联关系考虑

简单工厂模式:创建单一类型的对象,产品之间没有复杂的关联关系,只是根据不同的参数创建不同具体实现的对象。

工厂方法模式:侧重于创建单一类型的对象,方便扩展新的产品类型,产品之间相对独立,没有紧密的依赖关系。

抽象工厂模式:创建一组相关的对象,这些对象构成一个产品族,它们之间存在内在的关联和依赖关系。需要保证在同一产品族中的对象是相互兼容的。

 

3、从代码复杂度和维护成本考虑

简单工厂模式:代码结构简单,实现成本低,但当产品类型增多时,工厂类会变得臃肿,不符合开闭原则,维护成本会逐渐增加。

工厂方法模式:代码复杂度适中,通过将创建逻辑分散到具体的工厂子类中,提高了代码的可维护性和可扩展性,新增产品时对现有代码的影响较小。

抽象工厂模式:代码复杂度较高,需要定义多个抽象类和具体类,但它提供了更高层次的抽象和封装,能够很好地处理复杂的产品族创建问题,在复杂项目中可以有效降低整体的维护成本。

 

posted on 2025-03-18 13:53  bala001  阅读(16)  评论(0)    收藏  举报

导航