- создаём оружие, которое будет меч
с определённым типом, уроном и дистанцией - создаём персонажа и передаём ему созданный меч
const sword = new Weapon('sword',15,2);
const character = new Character('Warrior',sword);
В классе оружие Weapon мы добавляем новый метод attack
class Weapon {
type: string;
damage: number; // 0 - 100;
range: number; // 0 - 100;
contructor(type: string, damage: number, range: number) {
this.type = type;
this.damage = damage;
this.range = range;
}
новый метод attack просто имитация
выводит что-то в консольлог
attack(){
console.log('Удар мечом с уроном '+ this.damage);
}
}
в классе персонаж Character
мы делегируем метод из класса оружие Weapon
class Character {
name: string;
weapon: Weapon;
contructor(name: string, weapon: Weapon) {
this.name = name;
this.weapon= weapon;
}
принимает оружие
changeWeapon(newWeapon:Weapon) {
this.weapon = newWeapon;
}
делегируем метод из класса оружие Weapon
attack(){
this.weapon.attack();
}
}
вызываем метод attack
у оружия Weapon через персонажа Character
const sword = new Weapon('sword',15,2);
const character = new Character('Warrior',sword);
character.attack();
создаём новое оружие арбалет crossbow
меняем это оружие у нашего персонажа
получаем результат два раза с разным уроном
- Удар мечом с уроном 15
- Удар мечом с уроном 40
const sword = new Weapon('sword',15,2);
const character = new Character('Warrior',sword);
character.attack();
const crossbow = new Weapon('crossbow',40,100);
character.changeWeapon(crossbow);
Происходит нарушение принципа
для того чтобы добавить какой то функционал мы идем и изменяем существующий код
мы получаем результат не за счёт добавления новой сущности, а за счёт изменения старой.
class Weapon {
type: string;
damage: number; // 0 - 100;
range: number; // 0 - 100;
contructor(type: string, damage: number, range: number) {
this.type = type;
this.damage = damage;
this.range = range;
}
attack(){
if(this.type === 'sword') {
console.log('Удар мечом с уроном'+ this.damage');
}
if(this.type === 'crossbow') {
console.log('Выстрел из арбалета с уроном '+ this.damage');
}
}
}
выносим метод attack в интерфейс Attacker
чтобы мы могли его переиспользовать в каком-то другом классе
interface Attacker {
attack: () => void;
}
class Weapon implements Attacker{
type: string;
damage: number; // 0 - 100;
range: number; // 0 - 100;
contructor(type: string, damage: number, range: number) {
this.type = type;
this.damage = damage;
this.range = range;
}
attack(){}
}
- создаём конкретный класс Sword которое наследуется от класса оружие Weapon
- создаём конкретный класс Crossbow которое наследуется от класса оружие Weapon
class Sword extends Weapon {
attack(){
console.log('Удар мечом с уроном '+ this.damage');
}
}
class Crossbow extends Weapon {
attack(){
console.log('Выстрел из арбалета с уроном '+ this.damage');
}
}
В классе оружие Weapon
можем избавится от поля тип type:string
class Weapon {
type: string;
damage: number; // 0 - 100;
range: number; // 0 - 100;
contructor(type: string, damage: number, range: number) {
this.type = type;
this.damage = damage;
this.range = range;
}
}
Теперь чтобы добавить новый вид вооружения
- Нам достаточно создать класс
- Наследовать класс от базового класса оружие Weapon
const sword = new Sword(15,2);
const character = new Character('Warrior',sword);
character.attack();
const crossbow = new Weapon(40,100);
character.changeWeapon(crossbow);
character.attack();
Когда продумываете схему ваших сущностей
стоит подумать о том заранее, что вам придётся добавлять какой-то новый функционал и сразу это делать так, чтобы не костылили с куча условий, а делали это путем расширения
Если мы хотим добавить класс нож Knife
то нам не надо тестировать
классы меч Sword и арбалет Character
class Knife extends Weapon {
attack(){
console.log('Удар ножом с уроном '+ this.damage');
}
}