我的问题涉及程序的一般设计。 当对象a想要向对象b发送信息时,有三种可能性:
控制在对象a和b之外,并且调用a和b的公共方法:
b.TakeInformation(a.getInformation());
在这种情况下,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
会按照自己的意愿行事,有时它会产生信息:
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()aka getInformation()来读取字符,而是它是一个调用者,每次从它调用的输入读取一个字符b.giveInformation(character)
。
假设我无法重写A类。然后想象我编写了一个B语言,它是某种语言的解析器。解析器B包含许多函数和帮助类,并在代码中的许多地方使用ReadChar。
问题的解决方案需要重写B类,以便giveInformation(character)
调用它而不是调用ReadChar()
。这将是非常痛苦和不直观的。
这个合成示例最优雅的解决方案是创建适配器,它启动A
并存储所有字符,然后启动B
并为其提供读取字符的nececarry接口。
不幸的是,当A
和B
类在两个方向上进行通信时,这不适用于其他情况。
一般人如何解决这些问题?
是否有一些编程语言具有非标准范例,此任务不会出现问题?
我想到了几种可能的解决方案或方法。它们包括线程,管道,汇编语言或滥用惰性评估,但它们似乎都不够好或者我不知道如何使用它们。我将在答案中总结我的想法。
感谢您的帮助。
答案 0 :(得分:0)
我需要的东西可以使用线程在伪代码中重写,如下所示:
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 ++和汇编语言中,一切皆有可能。如何在那里使用两个堆栈并在上下文之间手动切换?
在任何编程语言中都可以将A,B编译为两个可执行文件。 A的标准输出可以是B的B输入。并且通过使用命名管道,B的输出可以再次输入A.(但是它需要对象的序列化和反序列化。我认为这是不明智的。我还希望有一个可执行文件。)
在具有惰性评估的编程语言中,可能会以某种方式滥用此范例来解决此类任务。
E.g。在c#中,可以在课程B
中实施IEnumerator()
。当A产生新信息时,将调用MoveNext()
。控件在B
内并暂停此“线程”的错觉。可以通过致电yield return
;
这种方法的缺点是'线程'只能在其主要方法中暂停。或者,必须将相同的技巧重新应用于所有其他应该挂起该线程的方法。
也许c#中的异步方法可以某种方式用于解决此类任务。但是如何?
答案 1 :(得分:0)
你的设计答案很糟糕,比原始问题的设计更糟糕。您在B类和A类之间添加了不必要的耦合。
你看起来可能是observer pattern。在观察者模式中,类只需要通知订阅者已经执行了一个操作,而不知道订阅了哪个类以及在通知时将执行什么。