digitalmars.D.learn - Signals far from Slots
- Jim Hewes (56/56) May 04 2014 Is there a good way to connect signals and slots when the objects are
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (38/94) May 05 2014 As far as I understand, you have to expose a function on BarContainer
- Jim Hewes (22/22) May 08 2014 Thanks Ali,
Is there a good way to connect signals and slots when the objects are far apart? All tutorials for signals and slots show the objects being readily accessible by the main() function. But what if they're not? Is there an elegant design? For example, here's a typical minimal demo: --------------------------------------------------------- class Foo { void Listen() { writeln("Foo: I hear you!"); } } class Bar { mixin Signal!() barSignal; void SaySomething() { emit(); } } int main(string[] argv) { Foo f = new Foo(); Bar b = new Bar(); b.barSignal.connect(&f.Listen); b.SaySomething(); return 0; } --------------------------------------------------------------- The main() function is a kind of controller that connects up the components. But let's say main() doesn't have access to Bar because it's behind a layer: ------------------------------------------------------------------ class BarContainer { this() { b = new Bar(); } void SetBarSignalHandler(b.barSignal.slot_t dg) { b.barSignal.connect(dg); } private Bar b; }; int main(string[] argv) { Foo f = new Foo(); BarContainer bc = new BarContainer(); bc.SetBarSignalHandler(&f.Listen); return 0; } ------------------------------------------------------------------ This can get worse if there is also a FooContainer and objects get further away. My first thought is to pass the delegates through the layers, as in the SetBarSignalHandler() function in BarContainer. But this seems kind of ugly as all the layers need to know about the connection between the signaling object and the observer object. It would be nice if they didn't have to. Do you know any any cleaner way? Jim
May 04 2014
On 05/04/2014 10:57 AM, Jim Hewes wrote:Is there a good way to connect signals and slots when the objects are far apart? All tutorials for signals and slots show the objects being readily accessible by the main() function. But what if they're not? Is there an elegant design? For example, here's a typical minimal demo: --------------------------------------------------------- class Foo { void Listen() { writeln("Foo: I hear you!"); } } class Bar { mixin Signal!() barSignal; void SaySomething() { emit(); } } int main(string[] argv) { Foo f = new Foo(); Bar b = new Bar(); b.barSignal.connect(&f.Listen); b.SaySomething(); return 0; } --------------------------------------------------------------- The main() function is a kind of controller that connects up the components. But let's say main() doesn't have access to Bar because it's behind a layer: ------------------------------------------------------------------ class BarContainer { this() { b = new Bar(); } void SetBarSignalHandler(b.barSignal.slot_t dg) { b.barSignal.connect(dg); } private Bar b; }; int main(string[] argv) { Foo f = new Foo(); BarContainer bc = new BarContainer(); bc.SetBarSignalHandler(&f.Listen); return 0; } ------------------------------------------------------------------ This can get worse if there is also a FooContainer and objects get further away. My first thought is to pass the delegates through the layers, as in the SetBarSignalHandler() function in BarContainer. But this seems kind of ugly as all the layers need to know about the connection between the signaling object and the observer object. It would be nice if they didn't have to. Do you know any any cleaner way? JimAs far as I understand, you have to expose a function on BarContainer similar to SaySomething() (I named it SaySomething() as well :) ): import std.stdio; import std.signals; class Foo { void Listen() { writeln("Foo: I hear you!"); } } class Bar { mixin Signal!() barSignal; void SaySomething() { emit(); } } class BarContainer { this() { b = new Bar(); } void SetBarSignalHandler(b.barSignal.slot_t dg) { b.barSignal.connect(dg); } void SaySomething() // <== ADDED { b.emit(); } private Bar b; } int main(string[] argv) { Foo f = new Foo(); BarContainer bc = new BarContainer(); bc.SetBarSignalHandler(&f.Listen); bc.SaySomething(); // <== ADDED return 0; } Ali
May 05 2014
Thanks Ali, In the second part of that example I was hoping it was understood that Bar generates it's own signal. Sorry, I guess I wasn't clear; I was just trying to reduce code. I think maybe I'm really looking for a way that BarContainer doesn't have to know that Bar and Foo are connected. One way I used to do this was to have a central EventManager object that all other objects knew about and it would be the traffic cop for events. So you have the traditional Java type of Observer implementation and then listeners register with the EventManager saying that they are interested in a type of event while signalers send all their events to the EventManager. Since signals and slots are intended to have some advantage over the Java way, I wondered if there was a better way to handle the setting up of the connection. (Signals and slots decreases coupling of objects, but then some controller object needs to know about them enough to connect them.) Sorry, maybe this is the wrong place to ask such questions. I know there are plenty of forums for specific languages and APIs. But I don't know of any that just deal with general design, which is what I'd like to get better at. BTW, thanks for your D tutorial! It's a big help to me. Jim
May 08 2014