2009-12-14 2 views
0

У меня есть класс процесса, где, если вход содержит значение, он также сделает что-то еще.События или наследование?

Например

Person { name; age } 

ProcessPerson(person) //takes in a person 

в ProcessPerson если возраст = старше 18 лет (для взрослых), а затем отправить по электронной почте.

ProcessPerson уже существует, и базовая логика должна выполняться независимо от того, что (сохранить человека в БД).

На данный момент существует только 1 условие, в котором выполняется эта дополнительная логика, но похоже, что в будущем появятся точки, в которых будет добавлено больше.

я могу думать о 2 пути решения этого и хотел Деку сессии:

  1. Наследования -> создать производный класс под названием ProcessAdult
  2. Событие -> после сохранения человека к БД, повысить обработанное событие. Добавьте обработчик, который отправляет электронное письмо.

Я предпочитаю последний из 2. Или, возможно, есть другой чистый и расширяемый метод, о котором я не думал?

+1

На каких языках мы говорим? –

+0

@andy C#, однако им интересно, какая разница это могло бы сделать? – dbones

ответ

3

Ваш второй вариант, безусловно, намного лучше.

2

Для случая, который вы описываете, мне также нравится # 2. Звучит чище и более конкретно обращается к вашей ситуации.

1

Возможно, вы ошибаетесь, но я бы не подклассифицировал класс Process, а скорее класс Person и потребовал, чтобы дети реализовали метод PostProcess или что-то в этом роде. Это фактически позволяет вам также требовать «PreProcess», если вы думаете, что через пару лет у вас может возникнуть необходимость в этом. Затем ваш метод Process принимает Person-base, вызывает PreProcess(), вставляет в БД и затем вызывает PostProcess(). Дети должны применять этот метод, но, очевидно, ничего не должны делать.

Но, честно говоря, в зависимости от того, где это живет и количества возможных сценариев, я скорее всего сделаю это изнутри в Process() и не буду заниматься событиями или наследованием.

if(person.Age>=18){}else if(person.Pets){}... 
0

Может быть, ваше описание проще, чем ваша актуальная проблема, но то, что случилось с:

void ProcessPerson(Person const& p) { 
    // do what you always do 

    if(p.age>=18) { 
     // send mail 
    } 
    // add other "special" handling here 
} 

?

Вы бы поступили из Person, если у вас есть дополнительные данные или специальные методы или оба, но вы этого не сделаете. Затем вы можете реализовать специализацию ProcessPerson для обработки производного класса.

Если вся информация, необходимая для обработки объекта Person, доступна локально, сделайте все необходимое в этом методе.

Если вам нужны разные фрагменты информации для обработки Person, которые не имеют ничего общего друг с другом, распределите обработку. У вас может быть, например,различные обработчики для вашей базы данных и ваша почтовая система и STH как:

Person p; 
foreach(handler in handler list) { 
    handler.Process(p); 
} 

и почтовый обработчик будет посылать уведомления, обработчик баз данных будет писать в БД и т.д.

+2

Каждый раз, когда вы добавляете специальный случай, вы должны добавить другой блок if. Это увеличивает сложность метода ProcessPerson и нарушает принцип единой ответственности. Ваш ProcessPerson сохраняет пользователя в базу данных, отправляет электронное письмо и выполняет другие «специальные» обработки. Каждое из них является его собственной заботой и должно быть изолировано. –

+0

В то же время код должен куда-то идти, Единственная ответственность ЭТО - «обрабатывать человека», в том числе экономить, отправлять по электронной почте все. Это обеспечивает единый источник правды для PersonProcess. Если есть только несколько правил, тогда это уместно. В противном случае вам необходимо настроить инфраструктуру для поддержки отправки, обработки, ошибок и т. Д. Кроме того, вся логика разбросана и теперь представлена ​​кодом и метаданными. Случай событий действителен и полезен, но без существующей инфраструктуры трудно утверждать, что стоит 1 или 2 события. –

+0

@Ryan: Итак, вы предлагаете добавить событие вместо этого? Каждый раз, когда вы добавляете специальный случай, вам нужно добавить еще один обработчик событий. Я иду с Волей: ProcessPerson обрабатывает человека и делает все, что необходимо. Пока не требуется никакой дополнительной информации, которая требовала прохождения 25 аргументов, это звучит мне поддающимся управлению. – Sebastian

1

Я голосую за номер 2, но держите вещи расширяемыми, обязательно включите обработанного лица в подпись подписи.

public delegate void PersonProcessedEventHandler(Person p); 
public event PersonProcessedEventHandler PersonProcessed; 

Это предотвращает генерацию вашего события. Процессор вашего лица просто повышает вероятность того, что человек был обработан, и любой другой обработчик может сделать с этим человеком, как ему заблагорассудится.

public void EmailAdult(Person p) 
{ 
    if(p.age >= 18) 
    { 
     //send email 
    } 
} 

public void SendWaffles(Person p) 
{ 
    if(p.name = "John Skeet") 
    { 
     //send waffles 
    } 
} 

thePersonProcessor.PersonProcessed += EmailAdult; 
thePersonProcesser.PersonProcessed += SendWaffles; 
+0

в соответствии с принципами разработки .NET Framework, делегаты, используемые в событиях, должны иметь два аргумента: сначала объект типа, обычно называемый отправителем, и второй аргумент типа, наследующий от System.EventArgs, который обертывает данные, которые вы хотите передать в событии. – Marek

Смежные вопросы