两个类之间的双向通信最佳模式是什么?

5
我有一些需要互相通信的类。问题在于,如果让其中一个包含另一个(子父关系),那么事情就变得棘手了。你要么需要将父实例传递到子对象中(那么如果你正在使用依赖注入,哪个应该先创建呢?),要么可以使用委托/事件。但我想强制执行这样一个事实:父对象必须能够处理子对象引发的事件。我不太确定如何做到这一点。我也不希望事件有多个订阅者。
父子关系对于双向通信来说感觉不太对。不幸的是,并不总是有一个对象始终启动,而另一个对象则作出响应。任何一个都可以启动,而另一个应该作出响应。
是否有其他模式我没有注意到?
更新: 抱歉这很难解释。我忘记添加一个细节,即当一个类向另一个类发送消息时,它并不期望立即接收响应。响应以异步方式到达,这就是为什么您需要父实例来调用正确的方法或委托/事件。抱歉下面的示例是伪代码。希望这足以传达思想。我应该看中介者模式吗?
public class Foo
    {
        public void SendMessageAToBar()
        {
            MessageA msg = new MessageA();
            Bar.ReceiveMessageAFromFoo(msg);
        }

        public void ReceiveMessageARespFromBar(MessageAResp msgResp)
        {
            //Got a response do something
        }

        public void ReceiveMessageBFromBar(MessageB msg)
        {
            //Do something msg
            MessageBResp msgBResp = new MessageBResp();
            Bar.ReceiveMessageBRespFromFoo()
        }
    }

    public class Bar
    {


        public void ReceiveMessageAFromFoo(MessageA msg)
        {
            //DO something.
            MessageAResp resp = new MessageAResp();
            Foo.ReceiveMessageARespFromBar(resp);
        }

        public void SendMessageBToFoo()
        {
            MessageB msg = new MessageB();
            Foo.ReceiveMessageBFromBar(msg);
        }

        public void ReceiveMessageBRespFromFoo(MessageBResp msgResp)
        {
            //Got a response do something
        }
    }

孩子有什么不同之处,意味着你不想在这里使用事件? - Tim Robinson
你能添加一个子元素和父元素的代码示例吗? - jgauffin
也许如果您描述一下您所指的'父对象'和'子对象'是哪些具体实例,会更有帮助。如果子对象持有对父对象的引用并不总是坏事。例如类似TreeView、XmlNode等情况,同时使用Observer模式也是一个很好的选择。不太确定为什么您说“我也不想有多个事件订阅者”。能否再解释一下呢? - Unmesh Kondolikar
@Unmesh。如果我使用委托,那么我可以有多个“订阅者”。我只想在委托中有一个单一的方法指针。即父级的方法指针。我希望在设计中强制执行这一点,以便下一个人不会有数百万个类在监听。 - uriDium
5个回答

2

由于您的问���有点抽象,因此很难提供一个好的答案。 但是,中介者模式怎么样?


我刚刚偶然发现了中介者模式。我现在正在研究它。 :) - uriDium

1

也许你应该使用引导程序:

class Main
{
    void Main(...)
    {
        A a = new A();
        B b = new B();

        a.MessagePosted += (sender, messageArgs) => b.ReadMessage(messageArgs.Message);
        b.MessagePosted += (sender, messageArgs) => a.ReadMessage(messageArgs.Message);
    }
}

现在,A和B都毫不知情。


1
创建一个包含通信细节的中间对象,并将其注入到A和B中吗?

这似乎类似于中介者模式。我还没有看完它。等看完后再告诉你。 - uriDium
是的,谢谢你指出来。http://en.wikipedia.org/wiki/Mediator_pattern 相当描述了你的情况。 - Grozz
那么,“中介者”和“引导程序”基本上是一样的吗? - Chad
我不这么认为。因为同事或参与者的构造函数接受一个中介器,API是自描述的并强制执行该模式。引导程序并没有真正强制执行任何内容,将来有人更改代码可能需要出于某种原因对引导程序进行更改,但他们可能没有意识到这一点。例如新的参与者。但是使用中介器很明显。在我看来。 - uriDium

0

这是一个例子,也可以使用接口来完成。

public abstract class Attachable
{
    public void Attach(Attachable attachable)
    {
        Attached = attachable;
        attachable.Attach(this);
    }

    public Attachable Attached { get; private set; }
    public abstract void DoSomethingUseful(object argument);
}


public class A : Attachable
{
    #region Overrides of Attachable

    public override void DoSomethingUseful(object argument)
    {
        // do something useful
    }

    #endregion
}

public class B : Attachable
{
    #region Overrides of Attachable

    public override void DoSomethingUseful(object argument)
    {
        // do something useful

    }

    #endregion
}

// Usage
A a = new A();
B b = new B();
a.Attach(b);

请查看我的更新(用法)。每个人都可以调用另一个的DoSomethingUseful(您可以根据自己的目的进行更改),并且它们可以进行通信。 - Aliostad

0

你可能想要查看Udi Dahan关于领域事件模式的代码示例。它与Chad发布的代码片段有着相同的基本原则。Martin Fowler也写了一些关于该模式的文章,并提供了更多有关该主题的信息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接