Шаблон C # Observer: Все еще тесно связаны? - PullRequest
1 голос
/ 01 октября 2010

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

Но с учетом инкапсуляции, как это не связывают?Они все еще зависят друг от друга, не так ли?

Что я хочу сказать, так это то, что Класс-субъект должен знать объект-наблюдатель, чтобы добавить его в список объектов для уведомления.

Следовательно, создается зависимость, верно?

В чем ошибка, которую я совершаю?

Спасибо!

Спасибо всем за ответы,

Теперь у меня естьнесколько новых вопросов.Если я правильно понимаю, лучший способ справиться с этим с интерфейсами.Поэтому я сделаю это;)

Но, почему всегда говорят о делегатах и ​​событиях?События являются формой делегатов.Так почему же они просто не говорят события?

Ответы [ 7 ]

4 голосов
/ 01 октября 2010

Когда вы говорите «знать», вы правы, что издатель должен знать о наблюдателе, чтобы публиковать информацию для него.

Однако ему не нужно «знать» об этом вощущение, что это жестко закодировано, что:

  • Наблюдатель всегда будет этим конкретным классом
  • Всегда будут доступны эти конкретные наблюдатели

В своей основной форме события являются издателем / наблюдателем в игре, поэтому вы можете легко сделать это только с событиями:

public class Observer
{
}

public class Publisher
{
    public event EventHandler SomethingHappened;
}

Затем вы заставите наблюдателя обработать это событие:

public class Observer
{
    public Observer(Publisher pub)
    {
        pub.SomethingHappened += Publisher_SomethingHappened;
    }

    private void Publisher_SomethingHappened(object sender, EventArgs e)
    {
    }
}

public class Publisher
{
    public event EventHandler SomethingHappened;
}

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

Aдругим способом было бы использовать интерфейсы:

public class Observer : IObserver
{
    public Observer(Publisher pub)
    {
        pub.Observers.Add(this);
    }

    void IObserver.SomethingHappened()
    {
    }
}

public class Publisher
{
    public List<IObserver> Observers { get; private set; }
}

public interface IObserver
{
    void SomethingHappened();
}

Опять же, издатель будет «знать» о наблюдателе в том смысле, что у него есть ссылка на него, но опять же у него нет жестко закодированной информации о том, какой класс или какбудет много случаев.

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

2 голосов
/ 01 октября 2010

Класс Observable может принимать интерфейсы в методе наблюдения.Этот интерфейс определяется в библиотеке, в которой определяется предметный класс, а затем реализуется подписчиком.Таким образом, классы знают только то, что они должны знать.

1 голос
/ 01 октября 2010

Наблюдаемый объект в C # - это объект, который объявляет одно или несколько событий.Один или несколько наблюдающих классов могут подписаться или не подписаться на эти события во время выполнения.Наблюдаемая часть не знает и не заботится.

Наблюдаемый класс не должен вести список объектов, которые должны быть уведомлены.Он просто должен инициировать событие, а в остальном он абсолютно не зависит от того, кто слушает.

Так что нет никакой зависимости от наблюдаемого класса от наблюдающего.Только наблюдающий должен знать о событиях, которые он может наблюдать.

Томас

0 голосов
/ 01 октября 2010

Вы спрашиваете: «Что за ошибка я совершаю?» . В следующей строке я думаю, что вы ошиблись:

То, что я имею в виду, это то, что Класс-субъект должен знать объект-наблюдатель, чтобы добавить его в список объектов для уведомления.

0 голосов
/ 01 октября 2010

Все объекты наблюдатель и объект наблюдаемый знают, что они взаимодействуют с IObservable и IObserver соответственно. Точный тип этих объектов для них не имеет значения - их заботит только то, что они реализуют интерфейсы IObserver и IObservable .

0 голосов
/ 01 октября 2010

Я думаю, что вы прочитали это немного неправильно, да, субъект подписывает наблюдателя, но не инициирует подписку, т. Е. MySubjectClass.Observers += MyObserverClass;

Используя интерфейс для определения договора между субъектоми Observer, вы позволяете Observer быть любым классом, который реализует интерфейс.

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

0 голосов
/ 01 октября 2010

Я не очень тебя понимаю.Но если вас беспокоит шаблон Observer в C # /. NET.Тогда разработчики в Microsoft уже решили все ваши проблемы в виде событий .

...