Share This Article
The observer pattern is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods.
It’s often used in GUI applications to notify views about model changes so they can be updated.
In this article, you will learn how to implement the observer pattern in Ruby using the Observable module.
Observer Pattern Implementation
Suppose you have a class that represents a blog post.
class Post
attr_reader :title, :body, :comments
def initialize(title, body)
@title = title
@body = body
@comments = []
end
def add_comment(comment)
comments << comment
end
end
You also have a class that represents a comment on a blog post.
class Comment
attr_reader :body
def initialize(body)
@body = body
end
end
You want to be able to notify observers whenever a new comment is added to a post, so you need to implement the observer pattern.
The first thing you need to do is to include the Observable
module in your Post
class like this:
class Post
include Observable
attr_reader :title, :body, :comments
def initialize(title, body)
@title = title
@body = body
@comments = []
end
def add_comment(comment)
changed
comments << comment
notify_observers(self)
end
end
Now you can create an observer like this:
class CommentObserver
def update(changed_post)
puts "Post #{changed_post.title} has new comments!"
end
end
And then register it with the post like this:
post = Post.new("Observer Pattern", "test")
comment_observer = CommentObserver.new
post.add_observer(comment_observer)
The add_observer
method expects an object that responds to the update
method.
Lastly, you can add a new comment to the post, and the observer will be notified:
post.add_comment(Comment.new("test"))
# Post Observer Pattern has new comments!
In a real application, you would probably want to do something more useful than just printing a message to the console.
For example, you could add a new comment to a view, and the view would automatically update itself.
Unregistering Observers
When you no longer need an observer, you should unregister it from the subject.
You can do that like this:
post.delete_observer(comment_observer)
It’s also a good idea to unregister observers before the subject is garbage collected.
You can use the Observable# finalize
hook for that:
class Post
def finalize
@observers.each do |observer|
delete_observer(observer)
end
end
end
This will unregister all observers when the post is garbage collected.
Summary
In this article, you have learned how to implement the observer pattern in Ruby using the Observable
module.
You have also learned how to register and unregister observers and use the Observable# finalize
hook to unregister observers when the subject is garbage collected.