Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Design patterns 程序设计:调用方/被调用方dilema,同步/手动切换上下文_Design Patterns_Asynchronous_Coroutine_Paradigms - Fatal编程技术网

Design patterns 程序设计:调用方/被调用方dilema,同步/手动切换上下文

Design patterns 程序设计:调用方/被调用方dilema,同步/手动切换上下文,design-patterns,asynchronous,coroutine,paradigms,Design Patterns,Asynchronous,Coroutine,Paradigms,我的问题是关于程序的总体设计。 当对象a想要向对象b发送信息时,有三种可能性: 控件位于对象a和b之外,调用a和b的公共方法: b.TakeInformation(a.getInformation()); 控件位于b的内部: 在这种情况下,b做它想做的事情,有时要求a提供信息: class A { public Information getInformatino() { // code omitted } // code omitted } class B { //

我的问题是关于程序的总体设计。 当对象a想要向对象b发送信息时,有三种可能性:

  • 控件位于对象a和b之外,调用a和b的公共方法:

    b.TakeInformation(a.getInformation());
    
  • 控件位于b的内部:
  • 在这种情况下,
    b
    做它想做的事情,有时要求
    a
    提供信息:

    class A {
      public Information getInformatino() {
        // code omitted
      }
      // code omitted
    }
    class B {
      // code omitted
      void foo() {
        while (bar()) {
          information = a.getInformation();
          DoSomeWork(information);
        }
      }
    }
    
  • 控件位于
    a
    的内部:
  • 在这种情况下,
    a
    做它想做的事情,有时它会给b它正在生成的信息:

    class A {
      // code omitted
      void foo() {
        while (bar()) {
          information = produceInformation()
          b.TakeInformation(information)
        }
      }
    }
    class B {
      // code omitted
      public void TakeInformation(information) {
        // code omitted
      }
    }
    
    我最感兴趣的是第四种可能性,
    a
    b
    都是呼叫者,而它们都不是被呼叫者

    在这种情况下,最简单的答案是:重写其中一个类,使其被调用

    这让我不满意。例如,让我们假设有一种奇怪的流,它不允许我通过调用ReadChar()A.k.A.getInformation()方法来读取字符,但它是一个调用者,每次从输入读取字符时,它都调用
    b.giveInformation(character)

    假设我不能重写类A,然后想象我编写了一个类B,它是某种语言的解析器。解析器B由许多函数和帮助类组成,并在代码的许多地方使用ReadChar

    该问题的解决方案需要重写类B,以便由
    giveInformation(character)
    调用它,而不是调用
    ReadChar()
    。这将是非常痛苦和不直观的

    对于这个合成示例,最优雅的解决方案是创建适配器,该适配器启动
    A
    并存储所有字符,然后启动
    B
    ,并为其提供必要的字符读取接口

    不幸的是,当类
    A
    anb
    B
    双向通信时,这不适用于其他场景

    一般来说,如何解决这些任务

    是否有一些具有非标准范例的编程语言可以解决这个问题

    我想到了几种可能的解决方案或方法。它们由线程、管道、汇编语言或惰性计算的滥用组成,但它们似乎都不够好,或者我不知道如何使用它们。我将在回答中总结我的想法


    感谢您的帮助。

    我需要的内容可以使用以下线程用伪代码重写:

    class A {
      // code omitted
      void foo() {
        while (bar()) {
          information = produceInformation()
          wake thread b, send it information
          suspend this thread until result is received
          result = received result
          DoSomeWorkWithResult(result);
        }
      }
    }
    
    class B {
      // code omitted
      void foo() {
        while (bar()) {
          suspend this thread until information is received
          information = received information
          result = DoSomeWork(information);
          wake thread a, send it the result
        }
      }
    }
    
    然而,我正在解决的任务的性质不是平行的。实际上,没有任何代码行可以同时执行。只有被切换的上下文没有并行运行。所以我怀疑使用线程是必要的。(我也不确定线程的开销会是多少。)

    我可能会用线程编写代码,即使没有并行性。然而,我通常对如何解决此类通信的可能方法感兴趣。我确信它是可解的——至少在某些编程语言中是如此

    在C++和汇编语言中,P>当然是一切可能的。如何使用两个堆栈并在上下文之间手动切换

    在任何编程语言中,A、B都可以编译成两个可执行文件。A的标准输出可以是B的输入。通过使用命名管道,B的输出可以再次成为A的输入。(然而,它需要对象的序列化和反序列化。我认为这是不必要的。我也更喜欢一个可执行文件。)

    在具有惰性计算的编程语言中,这种范式可能被滥用以解决此类任务

    例如,在c中,可以在类
    B
    中实现
    IEnumerator()
    。当A将生成新信息时,将调用
    MoveNext()
    。控件位于
    B
    内部并挂起此“线程”的错觉可以通过调用
    yield return
    来确保

    这种方法的缺点是“线程”只能在其主方法中挂起。或者,同样的技巧必须重新应用于所有其他应该挂起线程的方法


    也许c#中的异步方法可以某种方式用于解决此类任务。但是怎么做呢?

    你回答的设计很糟糕,比原来问题中的设计更糟糕。您在类B和类A之间添加了不必要的耦合

    你看起来可能是这样的。在观察者模式中,类只需要通知订阅者一个操作已经执行,而不知道订阅了哪个类以及在收到通知时将执行什么