0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

TypeScriptでclass名の文字列から動的にclassのインスタンスを生成する

Posted at

クローラーの開発をしていて、Site1Crawler,Site2Crawlerといった形で数字の違うクローラーを作成、class名から動的に別々のクローラーのインスタンスを生成したかったのでその方法です。

ディレクトリは適当でいいのですが、今回4つのファイルを作成します。

  • Crawler.ts
    • 量産されたclassをまとめて書いておくファイル
  • BaseCrawler.ts
    • 継承される元となるclass。インターフェースとして書いてもいいが今回はclassで作成する
  • Site1Crawler.ts(Site2Crawler.tsなどこのファイルを量産していく)
    • BaseCrawlerを継承した動的に呼び出されるclass
  • CrawlerFactory.ts
    • 動的に呼び出す部分を記載するFactory class

まず最初に継承元となるBaseCrawlerのclassを作成します。

BaseCrawler.ts
export default class BaseCrawler
{
  public siteId: number = 0;

  constructor() {
    this.init();
  }

  public init()
  {
  }

  public crawling()
  {
    console.log(url);
  }
}

次に量産するSite1Crawlerのclassを作成します。

Site1Crawler.ts
import BaseCrawler from "./BaseCrawler";

export default class Site1Crawler extends BaseCrawler
{
  init(): void {
    super.init();
    this.siteId = 1;
  }

  crawling(): void {
    super.crawling();
    console.log("site1 crawler crawling");
  }
}

量産されたclassをまとめて記載しておくファイルを作成します。

Crawler.ts
import Site1Crawler from "./Site1Crawler";

const Crawler: any = {
  Site1Crawler,
  (...量産していったらここにどんどん追加していく)
}

export default Crawler;

Factoryクラスの作成

CrawlerFactory.ts
import Crawler from "./Crawler";
import BaseCrawler from "./BaseCrawler";

export default class CrawlerFactory extends BaseCrawler{
  constructor(className: string)
  {
    super();
    if (Crawler[className] === undefined || Crawler[className] === null) {
      throw new Error(`Class type of \'${className}\' is not in the store`);
    }
    return new Crawler[className]();
  }
}

これで完了です。
呼び出す際には、

index.ts
import CrawlerFactory from "./CrawlerFactory";
import BaseCrawler from "./BaseCrawler";

const main = () {
  //class名の文字列で呼び出す
  const className = 'Site1Crawler';
  const crawler: BaseCrawler = new CrawlerFactory(className);
  crawler.crawling();

  //loopさせて動的に呼び出して実行させる
  //クローラーを10個作って順番に実行させたい場合
  for (let i = 0; i < 10; i++) {
    const className = `Site${i}Crawler`;
    const crawler: BaseCrawler = new CrawlerFactory(className);
    crawler.crawling();
  }
}

のように記載可能です。
evalとかの方法もあると思いますが、この方法が一番しっくりきたので。


参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?