戦略モデル

21472 ワード

オートマトンの作成
抽象クラスRobotを継承するAtomクラスとTaekwonVクラスがある.
abstract class Robot {
  constructor(private name: string) {}

  getName() {
    return this.name;
  }

  abstract attack(): void;
  abstract move(): void;
}

class TaekwonV extends Robot {
  attack() {
    console.log("I have Missile and can attack with it.");
  }

  move() {
    console.log("I can only walk.");
  }
}

class Atom extends Robot {
  attack() {
    console.log("I have strong punch and can attack with it.");
  }

  move() {
    console.log("I can fly.");
  }
}

const TAEKWON_V: Robot = new TaekwonV("TaekwonV");
const ATOM: Robot = new Atom("Atom");

console.log(`My name is ${TAEKWON_V.getName()}`);
TAEKWON_V.move();
TAEKWON_V.attack();

console.log(`My name is ${ATOM.getName()}`);
ATOM.move();
ATOM.attack();
に質問
既存のロボットの攻撃と移動方法を変更します.
Atomを歩かせたいなら、moveの方法を修正しなければなりません.これは、既存のコードを変更して新しい機能に変更するため、OCPとは逆です.また,2つのサブクラスのmoveメソッドは重複している.
新しいロボットへの攻撃/移動方法の追加/変更
抽象クラスで子クラスをカプセル化しているので、新しいロボットを追加しやすい.しかし、新しいロボットに既存の攻撃や移動方法を追加または変更しようとすると、上記の問題が発生します.
解決策
問題を解決するには、何が変わっているのかを見つけなければならない.変更が見つかったら、クラスにカプセル化します.現在の問題はロボットの移動方式と攻撃方式の変化である.すなわち,新しい方式の移動や攻撃機能を提供する場合,コードを変更する必要はなく,既存の方式を変更する必要もない.
攻撃インタフェースと移動インタフェース(カプセル化)をそれぞれ作成し、実際に実装されたクラスを作成します.Robotクラスには、変化を処理するための2つのインタフェースが含まれています.
interface MovingStrategy {
  move(): void;
}

class FlyingStrategy implements MovingStrategy {
  move() {
    console.log("I can fly.");
  }
}

class WalkingStrategy implements MovingStrategy {
  move() {
    console.log("I can walk.");
  }
}

interface AttackStrategy {
  attack(): void;
}

class MissileStrategy implements AttackStrategy {
  attack() {
    console.log("I have Missile and can attack with it.");
  }
}

class PunchStrategy implements AttackStrategy {
  attack() {
    console.log("I have strong punch and can attack with it.");
  }
}

abstract class Robot {
  private attackStrategy: AttackStrategy;
  private movingStrategy: MovingStrategy;

  constructor(private name: string) {}

  getName() {
    return this.name;
  }

  attack() {
    this.attackStrategy.attack();
  }

  move() {
    this.movingStrategy.move();
  }

  setMovingStrategy(movingStrategy: MovingStrategy) {
    this.movingStrategy = movingStrategy;
  }

  setAttackStrategy(attackStrategy: AttackStrategy) {
    this.attackStrategy = attackStrategy;
  }
}

class TaekwonV extends Robot {}

class Atom extends Robot {}

const TAEKWON_V: Robot = new TaekwonV("TaekwonV");
const ATOM: Robot = new Atom("Atom");

TAEKWON_V.setMovingStrategy(new WalkingStrategy());
TAEKWON_V.setAttackStrategy(new MissileStrategy());

ATOM.setMovingStrategy(new FlyingStrategy());
ATOM.setAttackStrategy(new PunchStrategy());

console.log(`My name is ${TAEKWON_V.getName()}`);
TAEKWON_V.move();
TAEKWON_V.attack();

console.log(`My name is ${ATOM.getName()}`);
ATOM.move();
ATOM.attack();
しま模様
Strategy Patternは簡単に戦略を変えることができます.戦略は,ある目的を達成するための行動方式,ビジネスルール,問題解決のアルゴリズムなどといえる.
特にストライプパターンはゲームプログラミングに役立ちます.