TypeScript
Violate ISP
// this violates the interface segregation principle
// because it is being used by multiple classes that does not requires all of it
interface Entity {
name: string;
attackDamage: number;
health: number;
move(): void | null;
attack(targetEntity: Entity | undefined): void | null;
takeDamage(amount: number): void | null;
}
// passes the interface segregation principle
class Character implements Entity {
name: string;
attackDamage: number;
health: number;
constructor(name: string, attackDamage: number, health: number) {
this.name = name;
this.attackDamage = attackDamage;
this.health = health;
}
move(): void {
console.log(`${this.name} moved`);
}
attack(targetEntity: Entity | undefined): void {
console.log(
`${this.name} attacked ${targetEntity.name} for ${this.attackDamage} damage`
);
targetEntity.takeDamage(this.attackDamage);
}
takeDamage(amount: number | undefined): void {
this.health -= amount;
console.log(`${this.name} has ${this.health} health remaining`);
}
}
class Wall implements Entity {
name: string;
// violates the interface segregation principle
attackDamage: number;
health: number;
constructor(name: string, health: number) {
this.name = name;
this.attackDamage = 0;
this.health = health;
}
// violates the interface segregation principle
move(): null {
return null;
}
// violates the interface segregation principle
attack(): null {
return null;
}
takeDamage(amount: number): void {
this.health -= amount;
console.log(`${this.name} has ${this.health} health remaining`);
}
}
class Turret implements Entity {
name: string;
attackDamage: number;
// violates the interface segregation principle
health: number;
constructor(name: string, attackDamage: number) {
this.name = name;
this.attackDamage = attackDamage;
this.health = 0;
}
// violates the interface segregation principle
move(): null {
return null;
}
attack(targetEntity: Entity): void {
console.log(
`${this.name} attacked ${targetEntity.name} for ${this.attackDamage} damage`
);
targetEntity.takeDamage(this.attackDamage);
}
// violates the interface segregation principle
takeDamage(): null {
return null;
}
}
const turret = new Turret("turret", 5);
const character = new Character("Character", 3, 100);
const wall = new Wall("Wall", 200);
turret.attack(character);
character.move();
character.attack(wall);
Pass ISP
interface Entity {
name: string;
}
interface Mover {
move(): void;
}
interface Attacker {
attackDamage: number;
attack(targetEntity: any): void;
}
interface HasHealth {
health: number;
takeDamage(amount: number): void;
}
class Character implements Entity, Mover, Attacker, HasHealth {
name: string;
attackDamage: number;
health: number;
constructor(name: string, attackDamage: number, health: number) {
this.name = name;
this.attackDamage = attackDamage;
this.health = health;
}
move(): void {
console.log(`${this.name} moved`);
}
attack(targetEntity: any): void {
console.log(
`${this.name} attacked ${targetEntity.name} for ${this.attackDamage} damage`
);
targetEntity.takeDamage(this.attackDamage);
}
takeDamage(amount: number): void {
this.health -= amount;
console.log(`${this.name} has ${this.health} health remaining`);
}
}
class Wall implements Entity, HasHealth {
name: string;
health: number;
constructor(name: string, health: number) {
this.name = name;
this.health = health;
}
takeDamage(amount: number): void {
this.health -= amount;
console.log(`${this.name} has ${this.health} health remaining`);
}
}
class Turret implements Entity, Attacker {
name: string;
attackDamage: number;
constructor(name: string, attackDamage: number) {
this.name = name;
this.attackDamage = attackDamage;
}
attack(targetEntity: any): void {
console.log(
`${this.name} attacked ${targetEntity.name} for ${this.attackDamage} damage`
);
targetEntity.takeDamage(this.attackDamage);
}
}
const turret = new Turret("Turret", 5);
const character = new Character("Character", 3, 100);
const wall = new Wall("Wall", 200);
turret.attack(character);
character.move();
character.attack(wall);