How To Implement The Observer Pattern In #CSharp
November 22, 2023
• 2,646 views
Previously we looked at how to implement the observer pattern in C# where we used events and event handlers. However, there are situations where developers forget to unhook their events and it leads to problems. In this video, we'll explore yet another way that we can implement the observer pattern in CSharp!
Have you subscribed to my weekly newsletter yet? A 5-minute read every weekend, right to your inbox, so you can start your weekend learning off strong:
https://subscribe.devleader.ca
Chec...
View Transcript
in this video we're going to explore the Observer pattern in C and if you've been watching my videos you might be saying Nick well we just looked at this the other day You released a video on this exact same topic and you're right except there's a slight difference in the approach we're going to look at today I'll link the previous video right here for you to watch and then you can come right back and watch this one in that implementation we looked at the Observer pattern using events and event handlers in C if you're not careful with events and event handlers and the way that you subscribe and unsubscribe you can run into memory leads so today we're going to look at a different approach and if you stay right to the end of this video we'll look at even another approach after that now
before I jump into visual studio just a quick reminder to check out my Weekly Newsletter it's totally free I cover software engineering topics in general as well as C andn Net related content I try to include an exclusive article every week and early access to my YouTube videos so you can watch videos just like this ahead of time okay okay over to visual studio to check out the code all right on my screen I have the ingredients for the Observer pattern along on with a little sample program right at the top of the file here so the pieces that we need for the observable pattern are the Observer and the observable so for context the observable as the name suggests is the thing that we can observe it's going to be the class that's responsible for having notifications or events or some other type of
signaling that our Observer down here is able to listen to or watch for these two roles when combined together make the Observer pattern so we're going to start by looking at the observable now the observable class that we have here is going to have a list of potential observers that are listening to it and I might be using the words listening or watching interchangeably but the point here is that The Observers that this has a collection of are the ones that are able to be notified about information from the observable so in the Constructor we're going to go ahead and create the list of potential observers and then we have two methods to add observers and remove observers so if you think about the previous example when we were looking at event handlers this is very much like adding a new event handler to the
event and this would be like removing an event handler if you're thinking about the syntax this is almost like that plus equal syntax when you're adding an event handler and this is like the minus equals now this fire event method is what's going to allow a caller of this observable to trigger notifications to The Observers when we were looking at events and event handlers this is where we would invoke the event inside of the body here but but instead what we're able to do is Loop over all of The Observers and then say for each Observer handle that event and in this case it's just a string message and to clarify there's no reason that this has to be a string I'm just using a string for demonstration purposes in your use case you might want to have your own custom type you might want
to use integers whatever it happens to be you're able to use as the type here and so that's a pretty straightforward implementation of an observable so let's go check out what the Observer look looks like well even easier The Observer simply has this handle event signature and it's going to take the same type that we need to pass in and then in this case I just have an implementation that is going to write out to the console now the reason that I have this implementing an interface is because you may want to have different implementations of observers so if we scroll back up you'll notice that when we add observers and this collection that we have in here they're using this ey Observer type and if I expand that you'll see that it just has this method signature handle event so the point that I
want to call out here is that our observable implementation does not care about the implementation of ey Observer it simply needs to meet this API which is just having a method called handle EV ENT and that means if I scroll back down a little bit lower and we look at the Observer implementation not only could I register multiple instances of this same type but in fact if I wanted different implementations of what an observer could do I would Implement new types and register those as well now one of the benefits that I like about this approach over the events and event handlers even though events and event handlers have this really nice syntax and the thought about events and event handlers seems to really make sense with observables I truly like that we're essentially just adding object references into this collection here to me it
feels a lot more explicit than when we're done observing we would go ahead and remove the Observer and we don't have this accidental situation where we're forgetting to do a minus equal on an event to remove the event handler just when our Observer goes out of scope and just to explain what I mean by this when we're talking about the implementation that's using events and event handlers what we're able to do is take the observable and then have observers hook up to the event of the observable now what we're not doing is having some type of collection of these objects maintained by the observable or anything else else as part of that pattern you'd have to go Implement that separately but what's happening is that the event itself is able to keep track of all these event handlers that you might be adding on and
the nice part is that that's handled behind the scenes but the dangerous part is that that's handled behind the scenes so you might think that you're not using these objects anymore these observers that you hooked up and you're not seeing them because you don't have any references in your code but if you're not using weak references is for the event handlers what's happening is that this observable is still holding a reference to this Observer it's a pretty weird side effect of how events and event handlers work in C but it's strictly because there is a reference to the thing that has the event handler now with this syntax that we're looking at in this implementation we are tracking the object references of the Observer so to me it just feels a lot more explicit that the whole object is being tracked on the surface it
only seems like a slight difference between the two but I feel like this is a little bit more explicit and because of that I feel like there's a little bit less room for error and I'll keep it short I'm not going to run this one cuz it just prints hello world and how many times could you possibly see that but at the beginning of this video I did mention there's yet another way that we can implement this so when that video is ready you can go ahead and watch it right here thanks and we'll see you next time
Frequently Asked Questions
What is the main difference between the Observer pattern implementation in this video and the previous one?
In this video, we're exploring a different approach to the Observer pattern that doesn't rely on events and event handlers. This method allows us to manage observers more explicitly by maintaining a collection of observer references, which helps avoid memory leaks that can occur with the event-based approach.
Why is it important to unsubscribe observers in the Observer pattern?
It's crucial to unsubscribe observers to prevent memory leaks. In the event-based approach, if you forget to remove an event handler, the observable will still hold a reference to the observer, preventing it from being garbage collected. By explicitly managing observer references in this implementation, we can avoid that issue.
Can I use types other than strings for the notifications in the Observer pattern?
Absolutely! While I used strings for demonstration purposes in this video, you can use any type that suits your needs, whether it's integers, custom types, or anything else. The key is that the observer's handle event method should match the type you choose.
These FAQs were generated by AI from the video transcript.