posts | commentsAdd to Google
02
Aug

Publish subscribe model

commentsNo comments

What is it?

The Publish/Subscribe model allows you to build loosely coupled applications in which an event is ‘fired’ and subscribing functions ‘respond’. This can be very powerful, if implemented correctly, and provides your application with more scalability.

Ok,, so what does that all mean?

Just imagine this. Your the supervisor on a construction site and you need to tell several of your guys to do something. You could run over to each individual guy and give them instructions individually, or you could use a megaphone and give them instructions all at once. You begin by defining who needs to listen and then give instructions. The guys who need the instructions listen, and the guys who don’t need the instructions just keep doing what they are doing.

So how does that look in an application?

I’ll give a couple examples in Javascript and PHP. There are many Javascript frameworks out there that do many different things. The only one that I have seen so far that has a publish subscribe model built in is dojo. In the project I’m currently working on I was working with prototype which unfortunately does not have a publish subscribe model built in, so I wrote up a quick rudimentary publish subscribe class:

Dispatch = Class.create({
 
	initialize : function()
	{
		this.List = [];
		this.CurrentMessage = "";
		this.CurrentIndex = 0;
		this.Timer;
	},
 
	subscribe : function(message, callback)
	{
		if (typeof(callback) != "function")
		{
			alert("Callback is not a function");
			return;
		}
 
		var subscribed = false;
		var l = this.List.length;
		for (this.CurrentIndex=0; this.CurrentIndex<l; this.CurrentIndex++)
		{
			if (this.List[this.CurrentIndex].msg == message && this.List[this.CurrentIndex].clbk == callback)
			{
				subscribed = true;
			}
		}
 
		if (subscribed == false)
		{
			this.List.push({msg : message, clbk : callback});
		}
		this.CurrentIndex=0;
	},
 
	unsubscribe : function(callback)
	{
		for (this.CurrentIndex=0; this.CurrentIndex<this.List.length; this.CurrentIndex++)
		{
			if (this.List[this.CurrentIndex].clbk == callback)
			{
				this.List.splice(this.CurrentIndex,1);
			}
		}
		this.CurrentIndex=0;
	},
 
	post : function(message, params)
	{
		var l = this.List.length;
 
			for (this.CurrentIndex=0; this.CurrentIndex<l; this.CurrentIndex++)
			{
				if (this.List[this.CurrentIndex].msg == message)
				{
					this.List[this.CurrentIndex].clbk(params);
				}
			}
 
		this.CurrentIndex = 0;
	}
 
});

Here’s a quick test page to see how it works:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
 
<script type="text/javascript" src="js/prototype.js"></script>
<script type="text/javascript" src="js/dispatch.js"></script>
<script type="text/javascript">
var dispatch = new Dispatch();
 
function subscribe()
{
	dispatch.subscribe('test', message);
}
 
function post()
{
	dispatch.post('test', 'fdsa');
}
 
 
function unsubscribe()
{
	dispatch.unsubscribe(message);
}
 
function message(a)
{
	alert('function1 says ' + a);
}
</script>
 
</head>
<body>
<form id="test">
<input type="button" value="subscribe" onclick="subscribe()" />
<input type="button" value="post" onclick="post()" />
<input type="button" value="unsubscribe" onclick="unsubscribe()" />
</form>
</body>
</html>

When a function is subscribed to an event, it waits to see when the event is fired and when the event fires, it sends out a command that the subscribed function is listening for and data that the subscribed function may need. This allows your code to be more modular since the firing function does not need to know who is subscribed to it and doesn’t need to be changed accordingly.

Pear PHP has a great class (Event Dispatcher) that does practically the same thing (If you don’t know what Pear PHP is, please get to know it!!).

$dispatcher->addObserver("myfunction", "MessageName");
 
function myfunction(&$notification)
{
	$data = $notification->getNotificationObject();
 
	echo $data;
}
 
$string_to_send = "some data";
$dispatcher->post($string_to_send, "MessageName");

The syntax is pretty simple and you can see more examples in the Pear documentation. Basically the dispatcher object subscribes the function you specify to the command you specify. The function is passed the notification object which allows you to get the object or variable that is sent to it when the dispatcher ‘posts’ the command.

Conclusion

The publish/subscribe model can be a very powerful foundation for building small to medium/large applications on. There is no silver bullet methodology, but this can be very useful.

Bookmark and Share

Saturday, August 2nd, 2008 at 1:46 pm and is filed under Javascript, PHP, Programming Methodologies. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

Leave a reply