289 lines
7.2 KiB
C#
289 lines
7.2 KiB
C#
|
/*
|
|||
|
* ПАТТЕРНЫ ПОВЕДЕНИЯ
|
|||
|
*
|
|||
|
* Глава_7_3: Цепочка обязанностей
|
|||
|
*
|
|||
|
* - позволяет избежать привязки отправителя запроса к его получателю,
|
|||
|
* давая шанс обработать запрос нескольким объектам
|
|||
|
*
|
|||
|
* - позволяет пробрасывать действия от одной компоненты к другой
|
|||
|
*/
|
|||
|
|
|||
|
class Roshan
|
|||
|
{
|
|||
|
public Roshan(int hp = 30) => Hp = hp;
|
|||
|
public int Hp { get; init; }
|
|||
|
}
|
|||
|
|
|||
|
interface IHero
|
|||
|
{
|
|||
|
int Hp { get; set; }
|
|||
|
Hero Next { get; set; }
|
|||
|
void MustWin(Roshan enemy);
|
|||
|
}
|
|||
|
|
|||
|
class Hero : IHero
|
|||
|
{
|
|||
|
public int Hp { get; set; }
|
|||
|
public Hero Next { get; set; }
|
|||
|
public string Name => GetType().Name;
|
|||
|
public Hero(int hp, Hero hero) { }
|
|||
|
public void MustWin(Roshan enemy)
|
|||
|
{
|
|||
|
if (Hp > enemy.Hp) { Console.WriteLine($"{Name} smog"); }
|
|||
|
else
|
|||
|
{
|
|||
|
if(Next != null)
|
|||
|
{
|
|||
|
Console.WriteLine($"{Name} ne smog. Poprobyet {Next.GetType().Name}");
|
|||
|
Next.MustWin(enemy);
|
|||
|
return;
|
|||
|
}
|
|||
|
Console.WriteLine($"{Name} ne smog. Brag pobedil.");
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
class Ursa : Hero
|
|||
|
{
|
|||
|
public Ursa(int hp = 50, Hero hero = null) : base(hp, hero) { }
|
|||
|
}
|
|||
|
|
|||
|
class Timbersaw : Hero
|
|||
|
{
|
|||
|
public Timbersaw(int hp = 70, Hero hero = null) : base(hp, hero) { }
|
|||
|
}
|
|||
|
|
|||
|
class Axe : Hero
|
|||
|
{
|
|||
|
public Axe(int hp = 110, Hero hero = null) : base(hp, hero) { }
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Пример №2
|
|||
|
/// </summary>
|
|||
|
public class Heros
|
|||
|
{
|
|||
|
public string Name;
|
|||
|
public int Attack { get; set; }
|
|||
|
public int Armor { get; set; }
|
|||
|
|
|||
|
public Heros(string name, int attak, int armor)
|
|||
|
{
|
|||
|
Name = name;
|
|||
|
Attack = attak;
|
|||
|
Armor = armor;
|
|||
|
}
|
|||
|
|
|||
|
public override string ToString() => $"{Name}: [{Attack}, {Armor}]\n";
|
|||
|
}
|
|||
|
|
|||
|
public class Effect
|
|||
|
{
|
|||
|
protected Heros heros;
|
|||
|
protected Effect next;
|
|||
|
|
|||
|
public Effect(Heros heros) => this.heros = heros;
|
|||
|
public void Add(Effect effect)
|
|||
|
{
|
|||
|
if (next != null) next.Add(effect);
|
|||
|
else next = effect;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Выполнение действия
|
|||
|
/// </summary>
|
|||
|
public virtual void Handle() => next?.Handle();
|
|||
|
}
|
|||
|
|
|||
|
public class DoubleDamageRune : Effect
|
|||
|
{
|
|||
|
public DoubleDamageRune(Heros heros)
|
|||
|
: base(heros) { }
|
|||
|
|
|||
|
public override void Handle()
|
|||
|
{
|
|||
|
Console.WriteLine($"{heros.Name} активировал руну двойного урона");
|
|||
|
heros.Attack *= 2;
|
|||
|
base.Handle();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public class Halberd : Effect
|
|||
|
{
|
|||
|
public Halberd(Heros heros)
|
|||
|
: base(heros) { }
|
|||
|
|
|||
|
public override void Handle()
|
|||
|
{
|
|||
|
Console.WriteLine("Существо лишено сил, от чего оно не может атаковать");
|
|||
|
heros.Attack = 0;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// К какому игровому персонажу какой эффект нужно применить
|
|||
|
/// * Самый сложный пример - с брокером событий
|
|||
|
/// </summary>
|
|||
|
public class Query
|
|||
|
{
|
|||
|
public string HeroName { get; set; }
|
|||
|
public GameEffect TypeEffect { get; set; }
|
|||
|
public Characteristic Args { get; set; }
|
|||
|
|
|||
|
public Query(string heroName, GameEffect typeEffect, Characteristic values)
|
|||
|
{
|
|||
|
HeroName = heroName;
|
|||
|
TypeEffect = typeEffect;
|
|||
|
Args = values;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public enum GameEffect
|
|||
|
{
|
|||
|
DubleDamageRunes = 1,
|
|||
|
ArmorBonus = 2,
|
|||
|
HalbertEffects = 3,
|
|||
|
ArcaneRune = 4
|
|||
|
}
|
|||
|
|
|||
|
public struct Characteristic
|
|||
|
{
|
|||
|
public int Attack { get; set; }
|
|||
|
public int Armor { get; set; }
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Брокер который отвечает за эффекты применяемые к персонажу
|
|||
|
/// </summary>
|
|||
|
public class Game
|
|||
|
{
|
|||
|
public event EventHandler<Query> Queries;
|
|||
|
public void CallQuery(object s, Query q) => Queries?.Invoke(s, q);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// В какой игре к какому персонажу применить какую характеристику
|
|||
|
/// </summary>
|
|||
|
public class Effects : IDisposable
|
|||
|
{
|
|||
|
protected Heross heross;
|
|||
|
protected Game game;
|
|||
|
public Effects(Heross heross, Game game)
|
|||
|
{
|
|||
|
this.heross = heross;
|
|||
|
this.game = game;
|
|||
|
game.Queries += Handlle;
|
|||
|
}
|
|||
|
|
|||
|
public virtual void Handlle(object sender, Query e) => Console.WriteLine("Basic Effect");
|
|||
|
public void Dispose() => game.Queries -= Handlle;
|
|||
|
}
|
|||
|
|
|||
|
public class DoubleDamageRunes : Effects
|
|||
|
{
|
|||
|
public DoubleDamageRunes(Heross heross, Game game) : base(heross, game) { }
|
|||
|
public override void Handlle(object sender, Query e)
|
|||
|
{
|
|||
|
if(e.HeroName == heross.Name
|
|||
|
&& e.TypeEffect == (GameEffect.DubleDamageRunes | GameEffect.HalbertEffects))
|
|||
|
{
|
|||
|
e.Args = new Characteristic
|
|||
|
{
|
|||
|
Armor = e.Args.Armor,
|
|||
|
Attack = 2 * e.Args.Attack
|
|||
|
};
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public class Halberds : Effects
|
|||
|
{
|
|||
|
public Halberds(Heross heross, Game game) : base(heross, game) { }
|
|||
|
public override void Handlle(object sender, Query e)
|
|||
|
{
|
|||
|
if (e.HeroName == heross.Name
|
|||
|
&& e.TypeEffect == GameEffect.HalbertEffects)
|
|||
|
{
|
|||
|
e.Args = new Characteristic
|
|||
|
{
|
|||
|
Armor = 1000,
|
|||
|
Attack = 0
|
|||
|
};
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public class Heross
|
|||
|
{
|
|||
|
private readonly Game game;
|
|||
|
public string Name;
|
|||
|
Characteristic characteristic;
|
|||
|
public int Attack
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
Query query = new (Name, GameEffect.DubleDamageRunes | GameEffect.ArmorBonus, characteristic);
|
|||
|
game.CallQuery(this, query);
|
|||
|
return query.Args.Attack;
|
|||
|
}
|
|||
|
}
|
|||
|
public int Armor
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
Query query = new (Name, GameEffect.DubleDamageRunes | GameEffect.ArmorBonus, characteristic);
|
|||
|
game.CallQuery(this, query);
|
|||
|
return query.Args.Armor;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public Heross(string name, int attack, int armor, Game game)
|
|||
|
{
|
|||
|
Console.WriteLine($"Создан герой {name}");
|
|||
|
Name = name;
|
|||
|
characteristic.Attack = attack;
|
|||
|
characteristic.Armor = armor;
|
|||
|
this.game = game;
|
|||
|
}
|
|||
|
|
|||
|
public override string ToString() => $"{Name} : [{Attack}, {Armor}]\n";
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
class Program
|
|||
|
{
|
|||
|
public static void Main(string[] args)
|
|||
|
{
|
|||
|
var enemy = new Roshan(109);
|
|||
|
|
|||
|
var ursa = new Ursa();
|
|||
|
var timber = new Timbersaw();
|
|||
|
var axe = new Axe();
|
|||
|
|
|||
|
ursa.Next = timber;
|
|||
|
timber.Next = axe;
|
|||
|
|
|||
|
ursa.MustWin(enemy);
|
|||
|
|
|||
|
var heros = new Heros("Queen Of Pain", armor: 4, attak: 80);
|
|||
|
Console.WriteLine(heros);
|
|||
|
|
|||
|
var game = new Effect(heros);
|
|||
|
game.Add(new DoubleDamageRune(heros)); game.Handle();
|
|||
|
Console.WriteLine(heros);
|
|||
|
|
|||
|
game.Add(new Halberd(heros)); game.Handle(); Console.WriteLine(heros);
|
|||
|
|
|||
|
var dota = new Game();
|
|||
|
var heross = new Heross("Queen Of Pain", attack: 80, armor: 4, dota);
|
|||
|
Console.WriteLine(heross);
|
|||
|
var dd = new DoubleDamageRunes(heross, dota);
|
|||
|
Console.WriteLine(heross);
|
|||
|
dd.Dispose(); Console.WriteLine(heross);
|
|||
|
var hb = new Halberds(heross, dota);
|
|||
|
Console.WriteLine(heross);
|
|||
|
hb.Dispose(); Console.WriteLine(heross);
|
|||
|
}
|
|||
|
}
|