Hot File

Create Override Strategy Logic - The Template Method Pattern with PHP

View: 331    Dowload: 0   Comment: 0   Post by: hanhga  
Author: none   Category: Php&mySql   Fields: Other

9 point/3 review File has been tested

The first time I looked at the Strategy pattern it was love at first sight. The pattern’s logic seemed to be a mythical panacea come true, where the use of Composition over Inheritance not only was exploited to its fullest

Introduction

The first time I looked at the Strategy pattern it was love at first sight. The pattern’s logic seemed to be a mythical panacea come true, where the use of Composition over Inheritance not only was exploited to its fullest, but the implementation was so clean and elegant that its charming influence was hard to resist. What could be more seductive than passing a few implementers of a given contract into one or more consumers allowing them to digest different algorithms at runtime through the reins of Polymorphism?

Of course, when I started coding strategies the magic of that “first date” vanished. I realized that some of my strategy classes barely carried state, or even worse, shared extensive chunks of duplicated implementations with each other, all smelly symptoms of a bad design.

In hindsight, this clever quote from C. S. Lewis, sums up a valuable lesson for me: “Experience is the most brutal of teachers.” The first tough lesson I learned from working with strategy classes is that sooner or later they tend to suffer of stateless issues rooted in the pattern’s intrinsic nature, and unfortunately they can’t be sorted out without drastic refactoring techniques.

While dealing with a few stateless issues here and there is something I can stand, even at the expense of being blamed for writing procedural code inside of class constructs, things are radically different when the same logic appears across multiple classes. This facet has nothing to do with the pattern’s essence or with some other tangled reason… it’s simply a nasty consequence of clunky design, many times caused by reluctance to walk Inheritance’s path.

This bring us back to the question whether it’s feasible to eliminate duplicated strategy logic via Inheritance rather than switching over to plain Composition. Indeed it is, and the clean up process can be conducted through an ubiquitous pattern known as Template Method design pattern.

Despite the flourishy name, the logic behind the Template Method pattern is ridiculously easy to assimilate. Simply put, there’s a base class (usually an abstract one), which declares a concrete method (a.k.a. the template) responsible for outlining the steps or hooks of a certain algorithm. Most of the time the base type provides boilerplate implementation for some of those steps and the remaining ones are delegated to subclasses. In turn, the subtypes override the unimplemented steps and provide their own implementations, this way creating distilled versions of the algorithm while shared implementation is neatly preserved inside the base class.

Beyond its simple nature, Template Method does prove that Inheritance can be a powerful approach when it comes to reusing common chunks of strategy logic. In this article I’ll be demonstrating some conrete examples to show how to use the pattern’s forces for programmatically rendering some basic jQuery-based image sliders.

Building a jQuery-Based Image Slider

Even though template methods have a prolific presence in several frameworks that provide partial implementations for a given component while letting subtypes override abstract methods according to more refined and specific needs, it’s rather difficult to find examples on the Internet that showcase how to exploit the pattern’s functionality in realistic use cases. By no means do I intend to fill this gap, as it can be filled better by someone else. My goal here is merely to illustrate how to employ the pattern in the generation of markup segments that must cling to a given sequence. A nice example of this is the rendering of a jQuery-driven image slider, whose “underlying strategy algorithm” could be, with some subtle slants of course, dissected into the following steps:

Render the target images inside a block-level element, hooked up to an “id” or “class” attribute.

Include jQuery.

Include the slider’s jQuery plug-in.

Render the JavaScript that gets the slider up and running.

With these generic steps outlined, it should be pretty easy to create a base abstract class and drop into it a template method that implements partially some of these steps while delegating the implementation of the remaining ones to a few subclasses. To keep things concise, the plug-in that I’m going to use in pursuit of my didactical cause will be the nifty Cycle.

Here’s how the aforementioned base class would look like:

<?php
namespace LibraryViewHelper;

abstract class AbstractCycleSlider
{
    protected $images = array();
    
    public function __construct(array $images) {
        if (empty($images)) {
            throw new InvalidArgumentException(
                "No images were supplied.");
        }
        foreach ($images as $image) {
            $extension = pathinfo($image, PATHINFO_EXTENSION);
            if (!in_array($extension, array("gif", "jpg", "png"))) {
                throw new OutOfRangeException(
                    "Only GIF/JPG/PNG files are allowed.");
            }
        }
        $this->images = $images;
    }
    
    // Hook method for rendering the target images
    protected function renderImages() {
        $output = '<div id="slider">';
        foreach ($this->images as $image) {
            $output .= '<img src="' . $image . '">';
        }
        $output .= "</div>";
        return $output;
    }
    
    // Hook method for including jQuery and the Cycle plug-in
    protected function renderLibraries() {
        return <<<ENDHTML
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="http://cloud.github.com/downloads/malsup/cycle/jquery.cycle.all.latest.js></script>
ENDHTML;
    }
    
    // Hook method for rendering a transition effect (overridden by
    // subclasses)
    abstract protected function renderEffect();
    
    // Template method for rendering the slider
    public final function render() {
        return $this->renderImages()
            . $this->renderLibraries()
            . $this->renderEffect();
    }
}

The only responsibility of the AbstractCycleSlider class is to provide implementation for some of the steps required for rendering an elemental Cycle-based slider. The whole rendering sequence is in this case defined by the render() method which effectively acts as the actual “template” for the steps in question.

The class does a decent work encapsulating common strategy logic behind its slim API, sure, but on its own it’s not very useful. But let’s no rush to pass judgment just yet, though, because the functionality the template method pattern offers rests on the benefits provided by a hierarchical structure where subtypes are responsible for providing strategy logic the base type can’t supply by default.

If you scan through AbstractCycleSlider, you’ll see here’s exactly where the renderEffect()method comes into play which should be implemented down the line by one or more subclasses, that way generating disparate –yet functional–versions of the base slider.

Refined Implementations of the Base Slider

Creating a few working Cycle-driven sliders is a pretty straightforward process that boils down to subclassing the base AbstractCycleSlider and then supplying concrete implementations for itsrenderEffect() method.

The following subclasses do precisely that:

<?php
namespace LibraryViewHelper;

class FadeSlider extends AbstractCycleSlider
{
    protected function renderEffect() {
        return <<<ENDHTML
<script>
jQuery(document).ready(function () {
    jQuery("#slider").cycle({fx: "fade"});
});
</script>
ENDHTML;
    }
}
<?php
namespace LibraryViewHelper;

class ScrollSlider extends AbstractCycleSlider
{
    protected function renderEffect() {
        return <<<ENDHTML
<script>
jQuery(document).ready(function () {
    jQuery("#slider").cycle({fx: "scrollDown"});
});
</script>
ENDHTML;
    }
}

The implementation of the renderEffect() method provided by the above subclasses is rendering some JavaScript snippets charged with generating a couple of transition effects (Fade and Scroll) bundled with the Cycle plug-in. This shows how to delegate the implementation of strategy logic defined in a template method to a few subtypes.

If you want to put the subclasses to work, arm yourself with a nice set of sample images and try out the following:

<?php
use LibraryLoaderAutoloader,
    LibraryViewHelperFadeSlider,
    LibraryViewHelperScrollSlider;
    
require_once __DIR__ . "/Library/Loader/Autoloader.php";
$autoloader = new Autoloader();
$autoloader->register();

$images = array(
    "sample_image1.jpg",
    "sample_image2.jpg",
    "sample_image3.jpg",
    "sample_image4.jpg",
    "sample_image5.jpg"
}; 

$slider = new FadeSlider($images);
echo $slider->render();

If all goes as expected, the above script should render a nifty image slider where the target images are looped by using a soft fade-in/out transition effect.

If you change your mind and want to set up a fancy scrolling slider instead, just create an instance of theScrollSlider class instead of its counterpart FadeSlider. Consuming the existing sliders, or eventually creating a few new ones, boils down to just providing custom implementations for therenderEffect() method.

The bad news, on the flip side, is that each slider class will be nothing but a subtle variation of the others, meaning that renderEffect() will always get its ecosystem polluted with duplicated code.

This doesn’t mean that using the template method design pattern is a bad thing at all. It’s just that in this case the custom implementations of it are way too similar to each other because we’re dealing with the same jQuery plug-in each time! The whole design would be a lot more efficient if we appealed to the pattern for rendering sliders based on different plugins as well.

Working with Different Plug-Ins

To recreate the above situation, say we want to render two disparate i1mage sliders: the first one would use the already familiar Cycle, and the second one would use Orbit. In that case, we should first refactor the earlier AbstractCycleSlider class to define a more granular template method:

<?php
namespace LibraryViewHelper;

abstract class AbstractSlider
{
    protected $images = array();
    
    public function __construct(array $images) {
        // the same constructor implementation
    }
    
    // Hook method for rendering the target images
    protected function renderImages() {
        $output = '<div id="slider">';
        foreach ($this->images as $image) {
            $output .= '<img src="' . $image . '">';
        }
        $output .= "</div>";
        return $output;
    }

    // Hook method for including jQuery
    protected function renderjQuery() {
        return <<<ENDHTML
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js">
</script>
ENDHTML;
    }

    // Hook method for including the slider's dependencies
    // (overridden by subclasses)
    abstract protected function renderDependencies();

    // Hook method for rendering a sliding effect (overridden by
    // subclasses)
    abstract protected function renderEffect();
    
    // Template method for rendering the slider
    public final function render() {
        return $this->renderImages()
            . $this->renderjQuery()
            . $this->renderDependencies()    
            . $this->renderEffect();
    }
}

This definitely looks better. Since the render() method now has been dissected into more atomic, finer-grained steps, it’s simple to create refined implementations of it.

The below subclass is a basic wrapper for a Cycle-based slider:

<?php
namespace LibraryViewHelper;

class Cycle extends AbstractSlider
{
    protected function renderDependencies() {
        return <<<ENDHTML
<script src="http://cloud.github.com/downloads/malsup/cycle/jquery.cycle.all.latest.js">
</script>
ENDHTML;
    }

    protected function renderEffect() {
        return <<<ENDHTML
<script>
jQuery(document).ready(function () {
    jQuery("#slider").cycle({fx: "fade"});
});
</script>
ENDHTML;
    }
}

And this one brings to life an Orbit-based slider:

<?php
namespace LibraryViewHelper;

class Orbit extends AbstractSlider
{
    protected function renderDependencies() {
        return <<<ENDHTML
<link rel="stylesheet" href="/public/css/orbit.css">
<script src="/public/js/orbit.min.js">
</script>
ENDHTML;
    }

    protected function renderEffect() {
        return <<<ENDHTML
<script>
jQuery(document).ready(function () {
    jQuery("#slider").orbit();
});
</script>
ENDHTML;
    }
}

Now with these subtypes providing custom implementations for the renderDependencies() andrenderEffect() methods, each plug-in can be independently rendered to the browser via a script like this:

<?php
$orbit = new Orbit($images);
echo $orbit->render();

$cycle = new Cycle($images);
echo $cycle->render();

I’m not necessarily an active proponent of this approach for adding a layer of behavior to your HTML documents, although it is neat and unobtrusive, because the process is a lot more cumbersome than just parsing a few templates hooked up to a view class or something like that. Still, it shows in a nutshell what’s actually under the hood of the Template Method pattern and how to exploit its niceties in the implementation of a few customizable view helpers.

 

Create Override Strategy Logic - The Template Method Pattern with PHP

Create Override Strategy Logic - The Template Method Pattern with PHP Posted on 13-04-2016  The first time I looked at the Strategy pattern it was love at first sight. The pattern’s logic seemed to be a mythical panacea come true, where the use of Composition over Inheritance not only was exploited to its fullest 3/10 331

Comment:

To comment you must be logged in members.

Files with category

  • How to Picking the Brains of Your Customers with Microsoft’s Text Analytics

    View: 2948    Download: 0   Comment: 0   Author: none  

    How to Picking the Brains of Your Customers with Microsoft’s Text Analytics

    Category: Php&mySql
    Fields: Other

    5/1 review
    With the explosion of machine learning services in recent years, it has become easier than ever for developers to create “smart apps”. In this article, I’ll introduce you to Microsoft’s offering for providing machine-learning capabilities to apps.

  • How to MySqli Tutorial PHP MySqli Extension

    View: 246    Download: 0   Comment: 0   Author: none  

    How to MySqli Tutorial PHP MySqli Extension

    Category: Php&mySql
    Fields: Other

    0/0 review
    PHP provides three api to connect mysql Database.

  • Make Laravel Artisan Commands

    View: 222    Download: 0   Comment: 0   Author: none  

    Make Laravel Artisan Commands

    Category: Php&mySql
    Fields: Other

    0/0 review
    Artisan is the command line tool used in Laravel framework. It offers a bunch of useful command that can help you develop application quickly. Apart from Artisan available commands, you can create your own custom commands to improve your workflow.

  • Check if a Number is a Power of 2

    View: 202    Download: 0   Comment: 0   Author: none  

    Check if a Number is a Power of 2

    Category: Php&mySql
    Fields: Other

    2.25/2 review
    How to check if a number is a power of 2. To understand this question, let’s take some example.

  • Concatenate columns in MySql

    View: 261    Download: 0   Comment: 0   Author: none  

    Concatenate columns in MySql

    Category: Php&mySql
    Fields: Other

    0/1 review
    Artisan is the command line tool used in Laravel framework. It offers a bunch of useful command that can help you develop application quickly. Apart from Artisan available commands, you can create your own custom commands to improve your workflow

  • How to Query NULL Value in MySql

    View: 193    Download: 0   Comment: 0   Author: none  

    How to Query NULL Value in MySql

    Category: Php&mySql
    Fields: Other

    5/1 review
    Misunderstanding NULL is common mistake beginners do while writing MySql query. While quering in MySql they compare column name with NULL. In MySql NULL is nothing or in simple word it isUnknown Value so if you use comparison operator for NULL values...

  • How to Abstract Class in PHP

    View: 226    Download: 0   Comment: 0   Author: none  

    How to Abstract Class in PHP

    Category: Php&mySql
    Fields: Other

    0/0 review
    What is an abstract class in PHP and when to use an abstract class in your application. In this tutorial, we’ll learn about abstract class and their implementation.

  • Use Enums in Rails for Mapped Values

    View: 221    Download: 0   Comment: 0   Author: none  

    Use Enums in Rails for Mapped Values

    Category: Php&mySql
    Fields: Other

    5/1 review
    When I worked in a call center, we used to mark cases with different statuses. This allowed upper management to get a handle on where cases stood, what the bottlenecks were and flow of calls. Thankfully it has been a long time since I worked in a...

 
Newsletter Email

File suggestion for you

File top downloads

logo codetitle
Codetitle.com - library source code to share, download the file to the community
Copyright © 2015. All rights reserved. codetitle.com Develope by Vinagon .Ltd