views:

2261

answers:

13

I'm looking to implement the Observer pattern in VB.NET or C# or some other first-class .NET language. I've heard that delegates can be used for this, but can't figure out why they would be preferred over plain old interfaces implemented on observers. So,

  • Why should I use delegates instead of defining my own interfaces and passing around references to objects implementing them?
  • Why might I want to avoid using delegates, and go with good ol'-fashioned interfaces?
+2  A: 

A delegate is, in effect, passing around a reference to a method, not an object... An Interface is a reference to a subset of the methods implemented by an object...

If, in some component of your application, you need access to more than one method of an object, then define an interface representing that subset of the objects' methods, and assign and implement that interface on all classes you might need to pass to this component... Then pass the instances of these classes by that interface instead of by their concrete class..

If, otoh, in some method, or component, all you need is one of several methods, which can be in any number of different classes, but all have the same signature, then you need to use a delegate.

Charles Bretana
+1  A: 

I've heard some "events evangelists" talk about this and they say that as more decoupled events are, the better it is.

Preferably, the event source should never know about the event listeners and the event listener should never care about who originated the event. This is not how things are today because in the event listener you normally receive the source object of the event.

With this said, delegates are the perfect tool for this job. They allow decoupling between event source and event observer because the event source doesn't need to keep a list of all observer objects. It only keeps a list of "function pointers" (delegates) of the observers. Because of this, I think this is a great advantage over Interfaces.

bruno conde
+1  A: 

Look at it the other way. What advantage would using a custom interface have over using the standard way that is supported by the language in both syntax and library?

Granted, there are cases where it a custom-tailored solution might have advantages, and in such cases you should use it. In all other cases, use the most canonical solution available. It's less work, more intuitive (because it's what users expect), has more support from tools (including the IDE) and chances are, the compiler treats them differently, resulting in more efficient code.

Don't reinvent the wheel (unless the current version is broken).

Konrad Rudolph
The "observer interface" method has a couple of advantages I can see:-1- given a weak reference to an observer, one can execute its "observe" method on it; there is no means in .net 2.x to keep a delegate without keeping a strong reference (or "reconstitute" a weak reference into a delegate).-2- With an observer/interface pattern, one can ask observers whether they're still "interested", and remove them if they're not. When using delegates, such removal is much harder and requires much more coordination between the event publisher and subscriber.
supercat
@supercat: your point 1 only partially true – you can implement your own delegate-like classes for use with weak references – this is especially important with events and supported by the `custom event` sytax. I’m not sure about your second point – isn’t that something that the observer can decide anyway, once it gets called? I don’t see the problem.
Konrad Rudolph
+3  A: 

There are two places that you could use delegates in the Observer pattern. Since I am not sure which one you are referring to, I will try to answer both.

The first is to use delegates in the subject instead of a list of IObservers. This approach seems a lot cleaner at handling multicasting since you basically have

private delegate void UpdateHandler(string message);
private UpdateHandler Update;

public void Register(IObserver observer)
{
    Update+=observer.Update;
}

public void Unregister(IObserver observer)
{
    Update-=observer.Update;
}

public void Notify(string message)
{
    Update(message);
}

instead of

public Subject()
{
    observers = new List<IObserver>();
}

public void Register(IObserver observer)
{
    observers.Add(observer);
}

public void Unregister(IObserver observer)
{
    observers.Remove(observer);
}

public void Notify(string message)
{
    // call update method for every observer
    foreach (IObserver observer in observers)
    {
     observer.Update(message);
    }
}

Unless you need to do something special and require a reference to the entire IObserver object, I would think the delegates would be cleaner.

The second case is to use pass delegates instead of IObervers for example

public delegate void UpdateHandler(string message);
private UpdateHandler Update;

public void Register(UpdateHandler observerRoutine)
{
    Update+=observerRoutine;
}

public void Unregister(UpdateHandler observerRoutine)
{
    Update-=observerRoutine;
}

public void Notify(string message)
{
    Update(message);
}

With this, Observers don't need to implement an interface. You could even pass in a lambda expression. This changes in the level of control is pretty much the difference. Whether this is good or bad is up to you.

Jacob Adams
A: 

Consider to use delegate if you end up with less code or code that is easier to read:

void Listen() {
  button.Click += delegate { Console.WriteLine("Hello World"); }
}

vs.

class ButtonObserver : IButtonObserver {
  void OnClick() {
    Console.WriteLine("Hello World");
  }
}

void Listen() {
  button.AddObserver(new ButtonObserver());
}

The same applies the other way:

void Listen() {
  entity.AddObserver(new MyObserver());
}

Is much better than this event spaghetti:

void Listen() {
  bool isValidated = false;
  entity.BeforeSave += delegate { isValidated = myObject.Validate(); }
  entity.AfterSave += delegate { myObject.Invalidate(isValidated); }
  entity.ReticulateSpline += delegate { myObject.Foo(); }
  entity.InvalidateRecitulation += delegate { myObject.Bar(); }
}
Hallgrim
Why should the latter be better? You have to custom-tailor `MyObserver` so you usually write no less code.
Konrad Rudolph
+7  A: 

Well technically, you don't have to use delegates (except when using event handlers, then it's required). You can get by without them. Really, they are just another tool in the tool box.

The first thing that comes to mind about using them is Inversion Of Control. Any time you want to control how a function behaves from outside of it, the easiest way to do it is to place a delegate as a parameter, and have it execute the delegate.

Kevin
I've used variations of the Strategy pattern that worked quite well with delegates for the strategy. Or a publisher/subscriber model where I provide a subscriber class that implements 90+% of the typical subscriber functionality as a wrapper around a callback to handle the other 10-%.
Toby
+14  A: 

You're an O/S, and I'm an application. I want to tell you to call one of my methods when you detect something happening. To do that, I pass you a delegate to the method of mine which I want you to call. I don't call that method of mine myself, because I want you to call it when you detect the something. You don't call my method directly because you don't know (at your compile-time) that the method exists (I wasn't even written when you were built); instead, you call whichever method is specified by the delegate which you receive at run-time.

ChrisW
@ChrisW- yeah I am now somewhat getting u, but can u pls provide soem code related example, that will be better for me to understand
Cloud2010
@Cloud2010 For example, see all the places where delegates and/or events are used in the >NET framework: for example, the [Control.Click Event](http://msdn.microsoft.com/en-us/library/system.windows.forms.control.click.aspx) or the [List<T>.ForEach Method](http://msdn.microsoft.com/en-us/library/bwabdf9z.aspx).
ChrisW
@Cloud2010: Here's an example of the `atexit` function (and reference to `on_exit` )which executes when the process exits. The function `bye` (in the example) is called by the OS when it detects the process is exiting. http://www.gnu.org/s/libc/manual/html_node/Cleanups-on-Exit.html
FrustratedWithFormsDesigner
+2  A: 

I'm repeating an answer I gave to this question.

I've always like the Radio Station metaphor.

When a radio station wants to broadcast something, it just sends it out. It doesn't need to know if there is actually anybody out there listening. Your radio is able to register itself with the radio station (by tuning in with the dial), and all radio station broadcasts (events in our little metaphor) are received by the radio who translates them into sound.

Without this registration (or event) mechanism. The radio station would have to contact each and every radio in turn and ask if it wanted the broadcast, if your radio said yes, then send the signal to it directly.

Your code may follow a very similar paradigm, where one class performs an action, but that class may not know, or may not want to know who will care about, or act on that action taking place. So it provides a way for any object to register or unregister itself for notification that the action has taken place.

Matthew Vines
This is more of an analogy for *events*, not *delegates* in general.
Adam Robinson
I guess I am taking a leap or two, but a delegate is just a reference to a method. The OP asked why you would want a reference to a method. I responded with a metaphor of a classic use of delegates (ie. events).
Matthew Vines
+19  A: 

When you can directly call a method, you don't need a delegate.

A delegate is useful when the code calling the method doesn't know/care what the method it's calling is -- for example, you might invoke a long-running task and pass it a delegate to a callback method that the task can use to send notifications about its status.

Here is a (very silly) code sample:

enum TaskStatus
{
   Started,
   StillProcessing,
   Finished
}

delegate void CallbackDelegate(Task t, TaskStatus status);

class Task
{
    public void Start(CallbackDelegate callback)
    {
        callback(this, TaskStatus.Started);

        // calculate PI to 1 billion digits
        for (...)
        {
            callback(this, TaskStatus.StillProcessing);
        }

        callback(this, TaskStatus.Finished);
    }
}

class Program
{
    static void Main(string[] args)
    {
        Task t = new Task();
        t.Start(new CallbackDelegate(MyCallbackMethod));
    }

    static void MyCallbackMethod(Task t, TaskStatus status)
    {
        Console.WriteLine("The task status is {0}", status);
    }
}

As you can see, the Task class doesn't know or care that -- in this case -- the delegate is to a method that prints the status of the task to the console. The method could equally well send the status over a network connection to another computer. Etc.

Ben M
+2  A: 

Delegates are strong typing for function/method interfaces.

If your language takes the position that there should be strong typing, and that it has first-class functions (both of which C# does), then it would be inconsistent to not have delegates.

Consider any method that takes a delegate. If you didn't have a delegate, how would you pass something to it? And how would the the callee have any guarantees about its type?

Ken
+5  A: 

You're not thinking like a programmer.

The question is, Why would you call a function directly when you could call a delegate?

A famous aphorism of David Wheeler goes: All problems in computer science can be solved by another level of indirection.

I'm being a bit tongue-in-cheek. Obviously, you will call functions directly most of the time, especially within a module. But delegates are useful when a function needs to be invoked in a context where the containing object is not available (or relevant), such as event callbacks.

harpo
http://en.wikipedia.org/wiki/Indirection says, this is often deliberately mis-quoted with "abstraction layer" substituted for "level of indirection". Kevlin Henney's corollary to this is, "...except for the problem of too many layers of indirection."
ChrisW
A: 

Actually there was an interesting back-and-forth between Sun and Microsoft about delegates. While Sun made a fairly strong stance against delegates, I feel that Microsoft made an even stronger point for using delegates. Here are the posts:

http://java.sun.com/docs/white/delegates.html

http://msdn.microsoft.com/en-us/vjsharp/bb188664.aspx

I think you'll find these interesting reading...

code4life
Wow, those links are from the history books. I do find most of the points raised on both sides quite trivial, and due simply to the acrimony between the two sides over Microsoft's then changes to the language. It basically distills down to whether saving one line of code (the method signature) is worth the addition of delegates. In my view there's no compelling reason to have them there.
CurtainDog
A: 

i think it is more related to syntatic sugar and a way to organize your code, a good use would be to handle several methods related to a common context which ones belong to a object or a static class.

it is not that you are forced to use them, you can programme sth with and without them, but maybe using them or not might affect how organized, readable and why not cool the code would be, maybe bum some lines in your code.

Every example given here is a good one where you could implement them, as someone said it, is just another feature in the language you can play with.

greetings

jgemedina