Задать вопрос

Как заменить switch case паттерном стратегия?

Просматривал тут вакансии, в одной из них была довольно интересная формулировка примерно такого плана:
"Мы ожидаем, что программист будет понимать и активно использовать паттерны проектирования, но без фанатизма. Например, не будет каждый switch case переписывать в стратегию. "
Как я понимаю, имелся ввиду одноименный паттерн. Вот мне стало интересно, как им можно заменить switch case. Ветвление ведь для выбора стратегии все равно понадобится. Например
switch (x)
{
     case 1:
        obj.strategy = new Strategy1();
    break;

     case 2:
        obj.strategy = new Strategy2();
    break;
}


Буду признателен за примеры кода.
  • Вопрос задан
  • 6232 просмотра
Подписаться 3 Простой 1 комментарий
Решения вопроса 1
lexxpavlov
@lexxpavlov
Программист, преподаватель
Switch
public enum DamageType { Melee, Range, Magic }
public class Monster
{
    public double Health { get; private set; }
    public double MeleeDamage { get; private set; }
    public double RangeDamage { get; private set; }
    public double MagicDamage { get; private set; }
    public DamageType FavoriteDamageType { get; private set; }

    public Monster(double health, double meleeDamage, double rangeDamage, double magicDamage, DamageType favoriteDamageType)
    {
        Health = health;
        MeleeDamage = meleeDamage;
        RangeDamage = rangeDamage;
        MagicDamage = magicDamage;
        FavoriteDamageType = favoriteDamageType;
    }

    public void AttackTo(Monster monster, DamageType damageType)
    {
        switch (damageType) // используется switch
        {
            case MonsterType.Melee: monster.Health -= MeleeDamage; break;
            case MonsterType.Range: monster.Health -= RangeDamage; break;
            case MonsterType.Magic: monster.Health -= MagicDamage; break;
        }
    }

    public void AttackTo(Monster monster)
    {
        AttackTo(monster, FavoriteDamageType);
    }
}


То же самое, но со стратегией
public class Monster
{
    public double Health { get; set; }
    public double MeleeDamage { get; private set; }
    public double RangeDamage { get; private set; }
    public double MagicDamage { get; private set; }
    public IDamageStrategy FavoriteDamageStrategy { get; private set; }

    public Monster(double health, double meleeDamage, double rangeDamage, double magicDamage, IDamageStrategy favoriteDamageStrategy)
    {
        Health = health;
        MeleeDamage = meleeDamage;
        RangeDamage = rangeDamage;
        MagicDamage = magicDamage;
        FavoriteDamageStrategy = favoriteDamageStrategy;
    }

    public void AttackTo(Monster monster, IDamageStrategy damageStrategy)
    {
        damageStrategy.Attack(this, monster); // не используется switch
    }

    public void AttackTo(Monster monster)
    {
        AttackTo(monster, FavoriteDamageStrategy);
    }
}


public interface IDamageStrategy
{
    void Attack(Monster attacker, Monster defender);
}
public class MeleeDamageStrategy : IDamageStrategy 
{
    public void Attack(Monster attacker, Monster defender)
    {
        defender.Health -= attacker.MeleeDamage;
    }
}
public class RangeDamageStrategy : IDamageStrategy 
{
    public void Attack(Monster attacker, Monster defender)
    {
        defender.Health -= attacker.RangeDamage;
    }
}
public class MagicDamageStrategy : IDamageStrategy 
{
    public void Attack(Monster attacker, Monster defender)
    {
        defender.Health -= attacker.MagicDamage;
    }
}

Отличие класса Monster только в коде первого метода AttackTo. Ну и свойства FavoriteDamageType или FavoriteDamageStrategy.

Стратегия может быть полезна, если код атаки, в зависимости от типа, сильно отличается, используя внешние данные (не из класса монстра), например, день или ночь, ясно/дождь и пр. Использование стратегии переносит часть кода из класса монстра (и так сложного класса) в несколько простых классов.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
qonand
@qonand
Software Engineer
Для выбора стратегии switch не используется. Объект необходимой стратегии просто передается в класс. Пример можно посмотреть например здесь
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы