Всякий раз, когда вы работаете с объектной моделью и обнаруживаете, что пишете тонну операторов switch
, это обычно означает, что вы поместили спецификатор класса c logi c в неправильное место. Вы должны поставить его вместе с самим классом, а не с классом, который его потребляет.
Другими словами, ваш регистратор должен не знать, как регистрировать каждый тип события. Это был бы кошмар обслуживания. Вместо этого он должен знать, как регистрировать общий объект (например, строку), и каждое событие само должно знать, как создать этот общий объект с помощью общего метода, о котором знает регистратор. Это единственное, что нужно знать.
Вот простой пример. В этом случае регистратор принимает любой тип LoggableEvent
и вызывает его метод Serialize()
, чтобы выяснить, как он добавляется в общий журнал. Само событие отвечает за знание того, как сериализовать себя.
abstract class LoggableEventBase
{
public string ActionName { get; }
public string ActionOrigin { get; }
public LoggableEventBase(string actionName, string actionOrigin)
{
ActionName = actionName;
ActionOrigin = actionOrigin;
}
public virtual string Serialize()
{
return string.Format("{0} {1}", ActionName, ActionOrigin);
}
}
class CreateOrderEvent : LoggableEventBase
{
protected readonly List<Item> _items;
protected readonly int _orderId;
public CreateOrderEvent(string origin, int orderID, List<Item> items) : base("CreateOrder", origin)
{
_orderId = orderID;
_items = items;
}
public override string Serialize()
{
return base.Serialize() + string.Format(" {0} {1}", _orderId, string.Join(",", _items.Select(item => item.SKU)));
}
}
Теперь фактические логи логирования c довольно просты - никаких операторов switch
или чего-либо еще, что должно знать, что это за событие :
class Logger : ILogger
{
public void Log(LoggableEventBase eventToLog)
{
Write(eventToLog.Serialize());
}
protected virtual void Write(string message)
{
//Write the message to a log file
}
}
Чтобы добавить дополнительные типы событий, вам просто нужно определить новый класс (и переопределить Serialize()
). Вам никогда не придется go назад и изменять класс Logger
. Это более соответствует принципу Open-Closed , чем ваше существующее решение.