【问题标题】:C# Observer pattern: Still tightly connected?C# 观察者模式:仍然紧密连接?
【发布时间】:2011-04-19 17:39:10
【问题描述】:

好的,所以我在这里停留在观察者模式,我阅读的几乎所有教程都告诉主题类订阅观察者。

但是考虑到封装,这怎么不紧密耦合?他们仍然相互依赖,不是吗?

我的意思是,主体类必须知道观察者对象才能将他添加到要通知的对象列表中。

因此创建了一个依赖项,对吗?

我犯了什么错误?

谢谢!

谢谢大家的回复,

现在我有一些新问题。如果我理解正确的话,最好的方法就是使用接口。所以我会这样做;)

但是,为什么总是在谈论代表和事件?事件是代表的一种形式。那么为什么他们不只是说事件呢?

【问题讨论】:

  • 在已发布 8 个回答后更改问题或提出新问题不是一个好主意。很难以这种方式进行讨论。回答您的问题:这不是真的,事件不是代表。传递给事件的事件处理程序是委托,它们在事件触发时被调用。您可以使用接口或事件来实现观察者模式。

标签: c# design-patterns observer-pattern


【解决方案1】:

当您说“知道”时,您是对的,发布者必须了解观察者才能向其发布信息。

但是,它不需要“知道”它,因为它是硬编码的:

  • 观察者总是这个特定的类
  • 总会有这些特定的观察者可用

在其基本形式中,事件是发布者/观察者在起作用,因此您可以通过事件轻松地做到这一点:

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;
}

只要从发布者处引发此事件,就会通知观察者。意识到挂钩事件的行为是“告诉”那个类关于观察者,但发布者没有任何关于发布者的硬编码信息,除了有人在听。

另一种方式是使用接口:

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();
}

同样,发布者将“知道”观察者,因为它有一个对它的引用,但它没有关于哪个类或有多少实例的硬编码信息。

只是一个警告:上面的代码有很大的缺陷,至少你应该确保观察者在你完成后从发布者“脱钩”,否则你会在系统中出现泄漏。如果您不明白我的意思,请发表评论,我将在示例中进行编辑。

【讨论】:

  • 你所说的 unhooks 是什么意思,在语法上 -= 对吗?否则同一个对象会被钩住两次,代码会运行两次。我说的对吗?
  • 是的,您需要执行与挂钩事件时相同的操作,只需使用减号 -=,否则将留下来自发布者的对您对象的引用。
【解决方案2】:

Observable 类可以接受observe 方法中的接口。该接口在定义主题类的库中定义,然后由订阅者实现。这样,类就只知道他们应该知道的内容。

【讨论】:

    【解决方案3】:

    C# 中的可观察对象是声明一个或多个事件的对象。一个或多个观察类可能会或可能不会在运行时订阅这些事件。可观察的部分不知道也不关心。

    被观察类不必维护要通知的对象列表。它只需要触发一个事件,否则完全不知道谁在听。

    因此,观察类与观察类之间没有任何依赖关系。只有观察者必须知道它可以观察到的事件。

    托马斯

    【讨论】:

      【解决方案4】:

      我真的不明白你。但是如果你担心 C#/.NET 中的观察者模式。然后微软的开发人员已经以events 的形式解决了你所有的问题。

      【讨论】:

        【解决方案5】:

        我想你读错了,是的,主题确实订阅了观察者但它没有启动订阅,即MySubjectClass.Observers += MyObserverClass;

        通过使用接口来定义 Subject 和 Observer 之间的契约,您可以让 Observer 成为实现该接口的任何类。

        所以你可以看到这不是紧密耦合的,即 Subject 没有实例化具体的 Observer 类。

        【讨论】:

          【解决方案6】:

          observer 对象和 observed 对象都知道它们正在与 IObservableIObserver 交互> 对象。 这些对象的确切类型与他们无关 - 他们只关心他们是否实现了 IObserverIObservable 接口。

          【讨论】:

            【解决方案7】:

            你问“我犯了什么错误?” . 我认为您的以下行是您出错​​的地方:

            我的意思是,主体类必须知道观察者对象才能将他添加到要通知的对象列表中。

            【讨论】:

              猜你喜欢
              • 2021-11-22
              • 2013-02-12
              • 2016-02-20
              • 2023-04-10
              • 1970-01-01
              • 2012-02-15
              • 2013-12-30
              • 2011-05-15
              • 1970-01-01
              相关资源
              最近更新 更多