Although the term is like a wild card used in fields other than software engineering, “Plug-in” is also the name of a design pattern which permits you to extend the functionality of a system (an application, a library, or a full-blown MVC framework) by means of a clever use of Composition and generic interfaces. These can be native, or in the form of abstract classes.
Like any other pattern, “Plug-in” is language-agnostic. This implies that it can be implemented in any programming language, including PHP. In keeping with this concept, in the introductory part of this series I went through the development of a rather primitive PHP application. Its main area of responsibility was to display, through a single client rendering class, different types of HTML objects, such as divs and paragraphs.
Thanks to the use of the “Plug-in” pattern, though, injecting each object into the internals of the pertinent client class and then rendering it on screen was as simple as replacing one Lego block with another. Not too bad, huh?
If you ask me what’s so special about this class, I have to say… nothing, except for a subtle detail worth noting: due the flexibility of the “Plug-in” pattern, the class will be passed to the client renderer and displayed on the browser without having to alter a single portion of the source classes developed so far.
So, do you want to see how this entirely new class will be built and “plugged in” to the existing infrastructure of this sample rendering application? Then don’t hesitate anymore; begin reading!
Review: a basic implementation of the “Plug-in” pattern
Before I show you the definition of the alert box class mentioned in the introduction, and how it will be afterward plugged in to the corresponding client rendering class, it’d be useful to review the example developed in the previous part of the series, It basically demonstrated the functionality of the “Plug-in” pattern when used with two different HTML objects.
Having said that, here’s the common interface implemented by the originating classes of these objects:
Since the “Renderable()” interface only declares a single “render()” method, look at the following classes. The first one is an abstract parent that defines the structure and behavior of generic HTML elements, while the other two are implementers of the interface, charged with rendering divs and paragraphs respectively:
abstract class AbstractHtmlElement
class Div extends AbstractHtmlElement implements RenderRenderable
class Paragraph extends AbstractHtmlElement implements RenderRenderable
By now you’ve grasped the logic driving the earlier HTML classes, so I suggest you pay attention to the implementation of the following one. It is a composite capable of displaying on screen any “renderable” object previously added through its “addElement()” method.
The client class looks like this:
While at first glance it seems that the above “Renderer” class does nothing particularly interesting, except render some inputted elements, this is a misconception, trust me. Even at a basic level, this class gets the pieces required by the “Plug-in” pattern working together. On the one hand, it uses Composition to inject the elements in question, while on the other hand it takes advantage of an interface (a simple contract, in this case) to make sure that those elements are really “renderable.”
If this concept sounds somewhat confusing to you, take a look at the following code snippet, which shows how to display on the browser the markup corresponding to the “Div” and “Paragraph” class just defined:
use HtmlDiv as Div,
// create some HTML elements
// create the renderer and add the previous elements to it
/* displays the following
<div id="one_id" class="one_class">This is the sample content for the div element.</div>
For the sake of brevity, in this case I omitted the definition of the autoloader, as this was covered in detail in the previous part of the series. This shouldn’t be an obstacle, though, to understanding how the previous script works. All that it does is input a div and a paragraph object into the client renderer class and display the resulting HTML on screen.
Beyond the simplicity of this example, the beauty of it is that the client renderer accepts any type of object, as long as it’s an implementer of the “Renderable” interface. But what does this buy us? Well, if I ever wanted to write a separate class that renders a type of content that isn't HTML and plug it into the renderer, the process would be dead simple.
blog comments powered by Disqus