Как создать фабричный объект, не нарушая OCP в Typescript - PullRequest
0 голосов
/ 30 марта 2019

Я только что узнал о фабричном шаблоне и хочу реализовать его в Typescript.

Я проверяю многие сайты, например this , и замечаю, что все примеры нарушают OCP, поскольку им приходится использовать множество операторов if для поиска подходящего конструктора подкласса.

Я также нашел похожий вопрос о том, как это сделать в Java. Но я не знаю, может ли это быть реализовано в машинописи.

1 Ответ

0 голосов
/ 30 марта 2019

Я не знаю, является ли это хорошей практикой, но вы можете избежать многих операторов if путем поиска класса с помощью произвольного доступа вместо последовательного.

Вы можете попробовать способ, подобный этому:

enum Behaviour {
  Friendly = 0,
  Agressive
}

export abstract class BaseCharacter{

  protected strength: number;

  public canFightWith(character: BaseCharacter): Boolean{
    return this.getBehaviour() !== character.getBehaviour();
  }

  public getStrength():number{
    return this.strength;
  }

  public abstract getBehaviour():Behaviour;

}

export class Vilain extends BaseCharacter{

  private reduction;

  public Vilain(strength:number, reduction:number){
    this.strength = strength;
    this.reduction = reduction;
  }

  public getStrength():number{
    return super.getStrength()*this.reduction;
  }

  public getBehaviour(): Behaviour {
    return Behaviour.Agressive;
  }
}

export class Hero extends BaseCharacter{

  public Hero(strength:number){
    this.strength = strength
  }

  public getBehaviour(): Behaviour {
    return Behaviour.Friendly;
  }
}

export class StaticFactory{

  // in this example Hero and Vilain will extend BaseCharacter

  static definitions = {
    'hero':Hero,
    'vilain':Vilain
  }

  static instanciateCharacter(subClass: string, ...args):BaseCharacter {
    if(subClass in StaticFactory.definitions)
      return new StaticFactory.definitions[subClass](...args);
  }

}

export class Battle{

  public constructor(private first: BaseCharacter, private second: BaseCharacter){
      if(!this.first.canFightWith(second))
        throw new Error("These 2 characters fight for the same cause !");
  }

  public getWinner():BaseCharacter{
    if (this.first.getStrength() === this.second.getStrength())
      return !(Math.trunc(Math.random()*2))?this.first:this.second;

    return this.first.getStrength() > this.second.getStrength()?this.first:this.second;

  }

}
...