Как избавиться от этого дублирования кода при сохранении элегантных событий? - PullRequest
4 голосов
/ 28 сентября 2011

Хорошо, допустим, у меня есть два класса, класс A и класс B. Им обоим нужно выполнить общую операцию, но не имеет смысла, чтобы они оба были производными от одного и того же объекта, поэтому вместо этого мы приступим к составлению. По сути, «имеет» имеет смысл, когда «есть» не имеет.

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

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

Ну, мы могли бы сделать что-то подобное в каждом из двух классов:

public event EventHandler CommonEvent
{
    add { theCommonObject.CommonEvent += value; }
    remove { theCommonObject.CommonEvent -= value; }
}

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

Тем не менее, в обоих классах есть повторяющийся код, и не только это, но это решение не всегда будет работать!

Например, что если theCommonObject создается локально в одном методе, и его область действия находится только в этом методе.

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

Пример кода, который в этом случае должен дублироваться в каждом классе:

public event EventHandler SomeCommonEvent;

private void SomeMethod()
{
    theCommonObject = new theCommonObject();

    theCommonObject.DoSomething();

    theCommonObject.SomeCommonEvent += thisClass_SomeCommonEvent;
}

private void thisClass_SomeCommonEvent(object sender, EventArgs e)
{
    var handler = SomeCommonEvent;

    if (handler != null)
    {
        handler(this, e);
    }
}

Как вы можете видеть, в обоих случаях есть дублирующийся код, но во втором - даже больше, потому что объект является локальным для метода, а не для переменной-члена.

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

Ответы [ 2 ]

2 голосов
/ 28 сентября 2011

Вы говорите, что у вас есть отношения "есть". Исходя из этого и исходя из предложенного вами решения, которое дублирует код, я предполагаю, что ваш класс A выглядит примерно так:

public class A
{
    private SomeCommonObject theCommonObject;
    public event EventHandler CommonEvent
    {
        add { theCommonObject.CommonEvent += value; }
        remove { theCommonObject.CommonEvent -= value; }
    }

    public A()
    {
        theCommonObject = new SomeCommonObject();
    }
}

Где проблема? theCommonObject никогда не может быть "локально создан в одном методе, и его область действия находится только в этом одном методе."

Да, add и remove обычно не используются. И что? Клиенты класса никогда не видят add и remove. Они по-прежнему подписываются на событие, используя традиционный синтаксис +=. Синтаксис add и remove не является проблемой для клиентов. И вы, разработчик, который создает класс, должны знать об этих вещах.

0 голосов
/ 28 сентября 2011

Вы можете использовать статический помощник для получения кода один раз, но это также «плохо»

Проблема в том, что реализация может быть написана один раз с производной, вы решили не выводить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...