views:

21

answers:

1

The setup: I have a singleton data access manager object, call it Manager. I also have some view controllers, call them Apples and Oranges. Both Apples and Oranges use Manager for some shared data model/access functionality.

I would like Manager to call either of them back in certain cases according to something like this:

if (someCondition)
    [self.applesDelegate callSomething];
else if (otherCondition)
    [self.orangesDelegate callSomething];

I see three ways of implementing this, none of which I am happy with.

1) do exactly as I did above, give Manager some properties like applesDelegate and orangesDelegate, and have relevant view controllers register themselves for that. But that would be bad because Manager would have domain knowledge, and I don't want to have that. Manager shouldn't know anything about Apple or Orange objects.

2) have a dynamic delegates map. Manager would have some NSMutableDictionary for delegates, and Apples and Oranges would do something like

[manager.delegateMap setObject:self forKey:@"applesDelegate"];

And Manager, when it would need to call the delegates, would do something like

if (someCondition) {
    [[delegatemap objectForKey:@"applesDelegate"] callSomeMethod];
}

This sounds workable but strange. And I'm not sure how it would work with the common dealloc requirement of setting the delegate to nil when you don't have a delegate property but this kind of indirection.

3) give up on the idea of delegates altogether and use notifications instead. Manager would just generate notifications and Apples and Oranges would listen to those. This loses a lot of compile-time checks though, this is why I'm still thinking about delegates that have a bit tighter coupling.

Which of the three would you recommend here? Or perhaps something different?

+1  A: 

In some cases a chain-of-responsibility pattern is useful. Each delegate is able to determine whether it can do the task. So it just

       if ( ! apple.doItIfYouCan(condition, methodName) )
       else ( orange.doItIfYouCan(condition, methodName)

I rarely feel comfortable with this diffusion of responsibility across the delegates.

So I would normally look for something like your option 2. In effect you're building a dispatch table. It at all possible I would try to recast the conditions into something that can be looked-up in a table. So in effect we take some information and get back an object and a method

        whatToDo = lookup(condition definition)

        whatToDo[who].what

(apologies for the lack of syntax, I don't speak your language, I'm hoping that the concepts translate - I could do this in JavaScript, or with function pointers in C, or reflection in Java.)

djna
Thanks. This lookup/dispatch table is what I had in mind. The only reason why I'm hesitant to implement this is right away that Objective-C has clear rules about how a delegate should release its "children" once it goes away, and it's less clear to me how this would work in this lookup table situation. (I know you said you don't speak that language, I'm hoping perhaps someone else can chime in.)
Jaanus