Используйте шаблон посетителя, чтобы обработать другое, если
Интересно, есть ли способ справиться с простым условием с помощью шаблона посетителя или нет?
Например, если у нас есть приведенный ниже код, как мы можем применить к нему шаблон посетителя?
public class Elseif
{
private int total;
public int Condition(int x)
{
if(x==1)
{
total = 100;
}
else if(x==2)
{
total = 200;
}
return total;
}
}
другими словами, как вы хотите написать перегрузку для интерфейса IVisitor?
public interface IVisitor
{
int Visitor(int x);
}
3 ответа
Шаблон посетителя предназначен для различения различных типов, особенно если у вас есть объект (абстрактного) суперкласса, и вы хотите делать особые вещи в зависимости от конкретного типа. Это означает, что вы можете (и должны) использовать его вместо if-then-else с приведением тестов.
Шаблон посетителя не предназначен для различения ценностей.
Может быть, вы ищете шаблон цепочки ответственности?
Допустим, вы должны рассчитать бонус, и вы используете что-то вроде этого
public double GetBonusRate(int workingDays, int numberOfSales)
{
if(numberOfSales > 20)
{
return 1.5;
}
if(workingDays >= 20 && numberOfSales > 10)
{
return 1.2;
}
if(numberOfSales > 5)
{
return 1.0;
}
if(workingDays > 10)
{
return 0.1;
}
return 0;
}
Вы ожидаете, что число условий будет расти, и вы понимаете, что добавление нового условия в неправильном месте вызовет ошибку.
Цепочка ответственности дает вам другой подход.
var chain = new PerfectBonusRate();
chain.RegisterNext(new GoodBonusRate())
.RegisterNext(new StandartBonusRate())
.RegisterNext(new LazyBonusRate())
.RegisterNext(new NoBonusRate());
var bonusRate = chain.GetBonusRate(10, 20);
Реализация
abstract class ChainElement
{
ChainElement _next;
public ChainElement RegisterNext(ChainElement next)
{
_next = next;
return next;
}
public double GetBonusRate(int workingDays, int numberOfSales)
{
if(IsMatched(workingDays, numberOfSales))
{
return GetBonusValue();
}
return _next.GetBonusRate(workingDays, numberOfSales);
}
protected abstract bool IsMatched(int workingDays, int numberOfSales);
protected abstract int GetBonusValue();
}
class PerfectBonusRate : ChainElement
{
protected override bool IsMatched(int workingDays, int numberOfSales)
{
return numberOfSales > 20;
}
protected override double GetBonusValue()
{
return 1.5;
}
}
class GoodBonusRate : ChainElement
{
protected override bool IsMatched(int workingDays, int numberOfSales)
{
return workingDays >= 20 && numberOfSales > 10;
}
protected override double GetBonusValue()
{
return 1.2;
}
}
//and the same for StandartBonusRate, LazyBonusRate...
class NoBonusRate : ChainElement
{
protected override bool IsMatched(int workingDays, int numberOfSales)
{
return true;
}
protected override double GetBonusValue()
{
return 0.0;
}
}
Шаблоны, используемые для решения некоторых конкретных задач. Шаблон посетителя решает следующую проблему - добавление новых возможностей в (составную) структуру объектов без изменения этих объектов. Итак, позвольте мне перефразировать ваш вопрос - как я могу добавить новые возможности в структуру объектов, не имея структуры объектов и добавляемых возможностей. Это похоже на забивание гвоздя скрипкой.
Помните - сначала идет проблема. Затем идет образец, который решает эту проблему. Не наоборот.
ОБНОВЛЕНИЕ так, какая проблема у вас кода? Он не следует принципу разделения команд и запросов. Тот же метод выполняет действие (изменение итога) и возвращает итоговую сумму вызывающей стороне. Я разделил команду и запрос, чтобы сделать ваш код более понятным:
public int Total { get; set; }
public void DoSomething(int x)
{
if(x == 1)
{
Total = 100;
return;
}
if(x == 2)
{
Total = 200;
return;
}
}