TypeScript設(shè)計(jì)模式-適配器模式|橋接模式|建造者模式

適配器模式

// 適配器模式

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) {
    // 根據(jù)type 生成哪一個(gè)播放類
    if (type === "vlc") {
      this.player = new VlcPlayer();
    } else if (type === "mp4") {
      this.player = new Mp4Player();
    } else {
      this.player = new Mp4Player(); // 默認(rèn)使用mp4player
    }
  }
  play(type: string, fileName: string) {
    // 因?yàn)樘囟ǖ牟シ蓬愑刑囟ǖ牟シ欧椒?,所以還需要再根據(jù)type調(diào)用特定的播放類
    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("播放器內(nèi)置支持mp3, " + fileName + "已開始播放.");
      return true;
    } else if (type === "vlc" || type === "mp4") {
      let ma = new MediaAdapter(type);
      ma.play(type, fileName);
      return true;
    } else {
      console.log("不支持當(dāng)前格式");
      return false;
    }
  }
}

測試文件:

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);
});

橋接模式

// 橋接模式

interface DrawApi {
  draw(radius: number, x: number, y: number): string;
}

export class RedCircle implements DrawApi {
  draw(radius: number, x: number, y: number) {
    console.log(radius, x, y);

    return "red circle";
  }
}

export class GreenCircle implements DrawApi {
  draw(radius: number, x: number, y: number) {
    console.log(radius, x, y);
    return "green circle";
  }
}

abstract class Shape {
  protected drawApi: DrawApi;
  protected constructor(drawApi: DrawApi) {
    this.drawApi = drawApi;
  }
  abstract draw(): string;
}

export class Circle extends Shape {
  private _x: number;
  private _y: number;
  private _radius: number;

  constructor(x: number, y: number, radius: number, drawApi: DrawApi) {
    super(drawApi);
    this._x = x;
    this._y = y;
    this._radius = radius;
  }
  draw() {
    return this.drawApi.draw(this._radius, this._x, this._y);
  }
}

測試文件:

import { Circle, RedCircle, GreenCircle } from "../src/Bridge";

test("circle shape", () => {
  let redCircle = new Circle(1, 1, 1, new RedCircle());
  let greenCircle = new Circle(2, 2, 2, new GreenCircle());
  expect(redCircle.draw()).toContain("red");
  expect(greenCircle.draw()).toContain("green");
});

建造者模式

// 建造者模式

// 從一個(gè)個(gè)簡單的類組合成一個(gè)大的類。

// 食品包裝接口
interface Packing {
  pack(): string;
}

// 紙質(zhì)包裝類,專門用來包裹漢堡
class Wrapper implements Packing {
  pack() {
    return "Wrapper";
  }
}

// 瓶子包裝類,專門用來裝飲料
class Bottle implements Packing {
  pack() {
    return "Bottle";
  }
}

// 食物接口
interface Item {
  name(): string;
  packing(): Packing;
  price(): number;
}

// 基類的好處,就是把公共的邏輯提取到基類中
// 漢堡基類
abstract class Burger implements Item {
  name() {
    return "Burger";
  }
  packing(): Packing {
    return new Wrapper();
  }
  abstract price(): number;
}

// 飲料基類
abstract class ColdDrink implements Item {
  name() {
    return "ColdDrink";
  }
  packing(): Packing {
    return new Bottle();
  }
  abstract price(): number;
}

// 素食漢堡
class VegBurger extends Burger {
  name() {
    return "VegBurger";
  }
  price() {
    return 25;
  }
}

// 雞肉漢堡
class ChickenBurger extends Burger {
  name() {
    return "ChickenBurger";
  }
  price() {
    return 50;
  }
}

class Coke extends ColdDrink {
  name() {
    return "Coke";
  }
  price() {
    return 30;
  }
}

// 百事可樂
class Pepsi extends ColdDrink {
  name() {
    return "Pepsi";
  }
  price() {
    return 35;
  }
}

// 套餐
class Meal {
  private _items: Item[] = [];
  addItem(item: Item) {
    this._items.push(item);
  }
  getCost() {
    let cost = 0;
    for (let item of this._items) {
      cost += item.price();
    }
    return cost;
  }
  showItems() {
    for (let item of this._items) {
      console.log(`Item : ${item.name()}`);
      console.log(`Packing : ${item.packing().pack()}`);
      console.log(`Item : ${item.price()}`);
    }
  }
}

class MealBuilder {
  // 準(zhǔn)備素食套餐
  prepareVegMeal() {
    let meal = new Meal();
    meal.addItem(new VegBurger());
    meal.addItem(new Coke());
    return meal;
  }
  // 準(zhǔn)備非素食套餐
  prepareNoteVegMeal() {
    let meal = new Meal();
    meal.addItem(new ChickenBurger());
    meal.addItem(new Pepsi());
    return meal;
  }
}

export { Meal, MealBuilder, VegBurger, ChickenBurger, Coke, Pepsi };

測試文件:

import {
  Meal,
  MealBuilder,
  ChickenBurger,
  VegBurger,
  Coke,
  Pepsi
} from "../src/Builder";

test("mealBuilder get a Meal", () => {
  let mealBuilder = new MealBuilder();
  let m1 = mealBuilder.prepareVegMeal();
  let m2 = mealBuilder.prepareNoteVegMeal();
  expect(m1 instanceof Meal).toBe(true);
  expect(m2 instanceof Meal).toBe(true);

  expect(m1.getCost() === new VegBurger().price() + new Coke().price()).toBe(
    true
  );
  expect(
    m2.getCost() === new ChickenBurger().price() + new Pepsi().price()
  ).toBe(true);
});

github

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 設(shè)計(jì)模式概述 在學(xué)習(xí)面向?qū)ο笃叽笤O(shè)計(jì)原則時(shí)需要注意以下幾點(diǎn):a) 高內(nèi)聚、低耦合和單一職能的“沖突”實(shí)際上,這兩者...
    彥幀閱讀 3,873評論 0 14
  • 前言:設(shè)計(jì)模式之結(jié)構(gòu)型模式軟件模式與具體的應(yīng)用領(lǐng)域無關(guān),也就是說無論你從事的是移動應(yīng)用開發(fā)、桌面應(yīng)用開發(fā)、Web ...
    markfork閱讀 2,564評論 4 13
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,765評論 25 709
  • 用兩張圖告訴你,為什么你的 App 會卡頓? - Android - 掘金 Cover 有什么料? 從這篇文章中你...
    hw1212閱讀 13,913評論 2 59
  • “#本文參加“青春”大賽,本人保證本文為本人原創(chuàng),如有問題與主辦方無關(guān),自愿放棄評優(yōu)評獎資格” 贛南師范大學(xué) 胡夢...
    DreamzhiG閱讀 177評論 0 4

友情鏈接更多精彩內(nèi)容