TypeScript重寫設計模式庫的搭建

王為民發表於2019-02-25

說明: 這篇文章並不是教大家如何用和如何寫設計模式,而是給大家一個參考:如何搭建一個練習的ts版設計模式庫

TypeScript版設計模式

js 的設計模式是經常使用的,但是最近在轉 ts,所以就打算用 ts 重寫 js 的設計模式. 說是重寫其實也是模仿.

主要技術點: webpack + typescrpt + jest + ts-jest

使用 jest 測試的原因是使用和配置相對簡單,並且支援 ts 檔案(不需要編譯成 js 檔案後測試),也是 react 的推薦測試框架(畢竟 facebook 自己產品).

好了開始我們的旅程.

建立 package.json 檔案及配置

npm init
複製程式碼

如下:

{
  "name": "ts-design-pattern",
  "version": "1.0.0",
  "description": "ts design pattern",
  "main": "index.js",
  "scripts": {},
  "keywords": ["ts", "design", "pattern"],
  "author": "wwmin",
  "license": "ISC",
  "devDependencies": {}
}
複製程式碼

更多配置請檢視npm init

安裝依賴

cnpm i typescript jest ts-jest @types/jest --save-dev
複製程式碼

並設定 script 後 package.json 檔案如下:

{
  "name": "ts-design-pattern",
  "version": "1.0.0",
  "description": "ts design pattern",
  "main": "index.js",
  "scripts": {
    "test": "jest"
  },
  "keywords": ["ts", "design", "pattern"],
  "author": "wwmin",
  "license": "ISC",
  "devDependencies": {
    "@types/jest": "^23.3.10",
    "jest": "^23.6.0",
    "ts-jest": "^23.10.5",
    "typescript": "^3.2.1"
  }
}
複製程式碼

配置 typescript

tsc --init
複製程式碼

後生成 tsconfig.json 檔案內容如下

{
  "compilerOptions": {
    "target": "es2015",
    "module": "commonjs",
    "strict": true,
    "noImplicitAny": true
  }
}
複製程式碼

更多配置請檢視tsconfig.json

配置 jest

npx ts-jest config:init
複製程式碼

後生成 jest.test.js 檔案內容如下

module.exports = {
  preset: `ts-jest`,
  testEnvironment: `node`,
};
複製程式碼

更多配置請檢視ts-jest

建立資料夾及檔案

|   .gitignore
|   jest.config.js
|   package.json
|   README.md
|   tsconfig.json
|
+---src
|       Adapter.ts
|
---test
        Adapter.test.ts
複製程式碼

整體資料夾結構大致就是這樣,
這裡也把.gitignore 內容放上,方便大家參考

.DS_Store
node_modules/
/dist/
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.map
複製程式碼

src 下和 test 的檔案是完成的程式碼

建立第一個設計模式 adapter

在 src 下新建 Adapter.ts

程式碼如下:

interface MediaPlayer {
  play(type: string, fileName: string): void;
}

interface AdvanceMediaPlayer {
  playVlc?(fileName: string): void;
  playMp4?(fileName: string): void;
}

class VlcPlayer implements AdvanceMediaPlayer {
  playVlc(fileName: string) {
    console.log("playing vlc file......." + fileName);
  }
}

class Mp4Player implements AdvanceMediaPlayer {
  playMp4(fileName: string) {
    console.log("playing mp4 file......." + fileName);
  }
}

class MediaAdapter implements MediaPlayer {
  player: AdvanceMediaPlayer;
  constructor(type: string) {
    // 根據type 生成哪一個播放類
    if (type === "vlc") {
      this.player = new VlcPlayer();
    } else if (type === "mp4") {
      this.player = new Mp4Player();
    } else {
      this.player = new Mp4Player(); // 預設使用mp4player
    }
  }
  play(type: string, fileName: string) {
    // 因為特定的播放類有特定的播放方法,所以還需要再根據type呼叫特定的播放類
    if (type === "vlc") {
      if (this.player.playVlc) this.player.playVlc(fileName);
    } else if (type === "mp4") {
      if (this.player.playMp4) this.player.playMp4(fileName);
    } else {
      return null;
    }
  }
}

export class AudioPlayer implements MediaPlayer {
  play(type: "mp3" | "mp4" | "vlc", fileName: string): boolean {
    if (type === "mp3") {
      console.log("播放器內建支援mp3, " + fileName + "已開始播放.");
      return true;
    } else if (type === "vlc" || type === "mp4") {
      let ma = new MediaAdapter(type);
      ma.play(type, fileName);
      return true;
    } else {
      console.log("不支援當前格式");
      return false;
    }
  }
}
複製程式碼

然後建立測試檔案 在 test 資料夾下新建 Adapter.test.ts
內容如下:

import { AudioPlayer } from "../src/Adapter";
test("playing to be true", () => {
  let player = new AudioPlayer();
  expect(player.play("mp3", "aa.mp3")).toBe(true);
  expect(player.play("mp4", "bb.mp4")).toBe(true);
  expect(player.play("vlc", "cc.vlc")).toBe(true);
});
複製程式碼

關於 jest 的使用請參考 jest

完成程式碼後開始測試

npm run test 或 npm test
複製程式碼

內容如下

 PASS  test/Adapter.test.ts
  √ playing to be true (18ms)

  console.log src/Adapter.ts:49
    播放器內建支援mp3, aa.mp3已開始播放.

  console.log src/Adapter.ts:18
    playing mp4 file.......bb.mp4

  console.log src/Adapter.ts:12
    playing vlc file.......cc.vlc

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.002s, estimated 2s
Ran all test suites.
複製程式碼

可以看到綠色的 passed 字樣,如果測試沒有通過則會有紅色的錯誤提示.

好了,這就完成了 ts 版的設計模式庫的搭建,後面我也會繼續將設計模式慢慢補充完整,
程式碼可以參考我的github https://github.com/wwmin/ts-design-pattern

相關文章