前端-工厂模式

86 阅读1分钟

所有的实例都从工厂产生,不用自己new 。

简易的工厂模式
class Product {
  name: string;
  constructor(name: string) {
    this.name = name;
  }

  fn1() {
    console.log("fn1", this.name);
  }

  fn2() {
    console.log("fn2");
  }
}

// 工厂
class Creator {
  create(name: string): Product {
    return new Product(name);
  }
}

const creator = new Creator();

const p1 = creator.create("p1");
const p2 = creator.create("p2");

p1.fn1();
p2.fn1();

标准的工厂模式

标准的工厂模式
interface IProduct {
  name: string;
  fn1: () => void;
  fn2: () => void;
}

class Product1 implements IProduct {
  name: string;
  constructor(name: string) {
    this.name = name;
  }

  fn1() {
    console.log("fn1", this.name);
  }

  fn2() {
    console.log("fn2");
  }
}

class Product2 implements IProduct {
  name: string;
  constructor(name: string) {
    this.name = name;
  }

  fn1() {
    console.log("fn1", this.name);
  }

  fn2() {
    console.log("fn2");
  }
}

class Creator {
  //依赖导致原则IProduct
  create(type: string, name: string): IProduct {
    if (type === "p1") {
      return new Product1(name);
    } else if (type === "p2") {
      return new Product2(name);
    }
    throw new Error("Invalid type");
  }
}

const creator = new Creator();
const p1 = creator.create("p1", "p1");
const p11 = creator.create("p1", "p1_1");
const p2 = creator.create("p2", "p2");
const p21 = creator.create("p2", "p2_1");

p1.fn1();
p11.fn1();
p2.fn1();
p21.fn1();

使用场景1:JQuery

不使用工厂模式
const $div = new JQuery("div");
const $p = new JQuery("p");

VS 

使用工厂模式
const $div = $("div");
const $p = $("p");、

declare interface Window {
  $: (select: string) => JQuery;
}
class JQuery {
  select: string;
  length: number;
  constructor(select: string) {
    const domList = Array.prototype.slice.call(document.querySelector(select));
    for (let i = 0; i < domList.length; i++) {
      // @ts-ignore
      this[i] = domList[i];
    }
    this.select = select;
    this.length = domList.length;
  }
  append(elem: HTMLElement): JQuery {
    // append操作 ....
    return this;
  }

  addClass(clazz: string): JQuery {
    // addClass操作 ....
    return this;
  }
}

// 不使用工厂模式
// const $div = new JQuery("div");
// const $p = new JQuery("p");

//使用工厂模式
function $(selector: string) {
  return new JQuery(selector); // 逻辑封装
}
window.$ = function (selector: string) {
  return new JQuery(selector); // 逻辑封装
};
const $div = $("div");
const $p = $("p");


/**
伪代码,演示 jquery 实例的结构
伪数组,Array.prototype.slice.call或者Array.from可以将伪数组转化为真的数组
const jquery = {
    selector: 'div',
    length: 3,
    '0': div1,
    '1': div2,
    '2': div3
}
 */

使用场景2:React

JSX编译的产物, _jsx 、_jsxs都是工厂函数,生成VNode。 image.png

使用场景3:Vue

vue3模板编译的产物,_createElementBlock、_createElementVNode都是工厂函数,生成VNode image.png