設計模式在 TypeScript 中的應用 – 策略模式

三毛發表於2019-02-16

定義

定義一系列的演算法,把它們一個個封裝起來,並且使它們可以相互替換。

實現

思路:建立表示各種策略的物件,和一個行為隨著策略物件改變而改變的 context 物件。

一個簡單的加減乘例子:

interface Compute<T> {
  computeF (num1: T, num2: T): T
}

// 建立策略物件
class ComputeAdd implements Compute<number> {
  public computeF (
    num1: number,
    num2: number
  ): number {
    return num1 + num2
  }
}

class ComputeSub implements Compute<number> {
  public computeF (
    num1: number,
    num2: number
  ): number {
    return num1 - num2
  }
}

class ComputeMul implements Compute<String> {
  public computeF (
    num1: String,
    num2: String
  ): String {
    return `${num1} + ${num2}`
  }
}

// 建立行為類
class Context {
  public compute: Compute<any>

  public constructor (compute: Compute<any>) {
    this.compute = compute
  }

  public excuteCompute (
    num1: number,
    num2: number
  ): number {
    return this.compute.computeF(num1, num2)
  }
}

let context1 = new Context(new ComputeAdd())
                   .excuteCompute(1, 2)
let context2 = new Context(new ComputeSub())
                   .excuteCompute(1, 2)
let content3 = new Context(new ComputeMul())
                   .excuteCompute(1, 2)

console.log(context1, context2, content3) // 3, -1, 1 + 2

複雜一點的例子(打怪):

// 武器介面
interface Weapon {
  useWeapon (): void
}

// 技能介面
interface Skill {
  useSkill (): void
}

// 武器類
class Gun implements Weapon {
  public useWeapon () {
    console.log( `Weapon: Gun`)
  }
}

class Stick implements Weapon {
  public useWeapon () {
    console.log(`Weapon: Stick`)
  }
}

// 技能類
class Magic implements Skill {
  public useSkill () {
    console.log(`Skill: Magic`)
  }
}

class Kongfu implements Skill {
  public useSkill () {
    console.log(`Skill: Chinese Kongfu`)
  }
}

// 抽象類,用於給其他類繼承
abstract class Way {
  // 武器
  public weapon: Weapon
  
  // 技能
  public skill: Skill

 // 設定武器
  public setWeapon (weapon: Weapon): void {
    this.weapon = weapon
  }
  
  // 設定技能
  public setSkill (skill: Skill): void {
    this.skill = skill
  }

  public getWeaponAndSkill (): void {
    this.weapon.useWeapon()
    this.skill.useSkill()
  }

  // 抽象方法
  public abstract saySome (): void
}

class SimpleWay extends Way {
  public constructor () {
    super()
    this.weapon = new Gun()
    this.skill = new Magic()
  }

  public saySome () {
    console.log(`屠龍寶刀,點選就送`)
  }
}

const way = new SimpleWay()
way.saySome()

console.log(`=======`)

way.getWeaponAndSkill()

console.log(`=======`)

way.setWeapon(new Stick)
way.setSkill(new Kongfu)
way.getWeaponAndSkill()

相關文章