PHP Prototype Design Pattern Part II: From Prototype to Production

appleReady for Production

Before a product goes into full production, manufacturers design a prototype to work out the bugs and improve the design. Once the prototype is ready, it is ready for production. Then all of the production copies are based on the prototype. (Of course, if you get the prototype wrong, all of your production elements will be wrong as well.)

One of the nice things about OOP is that abstract classes and interfaces act a lot like prototypes. They provide a basic design and allow the individual implementations to make variations. Think of an automobile that has certain key elements to it based on a prototype. If you have a Ford, Toyota, Volkswagen or Saab, you get a car based on a certain prototype, but you can have different characteristics based on the prototype such as color and a choice of leather or vinyl seat covers. (Even more choices are available with the Decorator pattern!) To get started, run the sample program (Outlaws and Lawmen of the Old West) and download the files:
PlayDownload

One of the more challenging aspects of the creating a Prototype pattern is the cloning, but as you saw in Part I of the Prototype discussion, in PHP, cloning is easy. So, now all we have to do is to take a quick look at the class diagram and then look at the code:

Figure 1: Prototype class diagram

Figure 1: Prototype class diagram

The Prototype Interface

This example uses an abstract class for an interface. In looking at the class diagram, all we really need is an abstract __clone() function, but adding some concrete and abstract getters and setters give us a bit more to work with. At the very base, the properties include:

  • A name (sobriquet)
  • A photo (poster)
  • Where they lived (location)

All of the functions (except one) could be abstract or all of them could be abstract, but since this is for illustration purposes, I put in some of both. I like using properties in abstract classes, and so this excludes using interfaces since they can only have abstract classes and CONSTANTS. However, if the properties ($sobriquet, $poster, and $location) were omitted, I could use an interface.

<?php
//IWestlaw.php
abstract class IWestLaw
{
	protected $sobriquet;
	protected $poster;
	protected $location;
 
	//Outlaw or Lawman
	abstract function setPlace($where);
	abstract function getPlace();
	abstract function __clone();
 
	//Sobriquet
	public function setSobriquet($nickname)
	{
		$this->sobriquet=$nickname;
	}
 
	public function getSobriquet()
	{
		return $this->sobriquet;
	}
 
	//Wanted Poster or Lawman Pose
	public function setPoster($ePic)
	{
		$this->poster="posters/" . $ePic . ".png";
	}
 
	public function getPic()
	{
		return $this->poster;
	}	
}
?>

Once implemented, the client can then use clones of the implementations. However, we first need to implement the concrete prototype classes that will be cloned.

The Outlaw and Lawmen Prototype Implementations

This example has two implementations of the IWestlaw abstract class. The only difference between the two is that the Outlaw class has a constant that identifies the outlaw as such, and it has a property, along with appropriate getter/setter methods, that identifies the outlaw’s criminal preferences.

<?php
//Outlaw.php
include_once('IWestLaw.php');
class Outlaw extends IWestLaw
{
	const LAWSIDE="Outlaw";
	private $crime;
 
	public function setPlace($where)
	{
		$this->location=$where;
	}
 
	public function getPlace()
	{
		return $this->location;
	}
 
	public function setCrime($doneWrong)
	{
		$this->crime=$doneWrong;
	}
 
	public function getCrime()
	{
		return $this->crime;
	}
	function __clone(){}	
 
}
?>

At the very bottom of the implementation is the __clone() implementation. Because all I’m concerned with is the capacity to clone an instance of the implementation, there’s no reason to place any content in the __clone() method. The added getter/setter for the $doneWrong (crime) property will not be part of the Lawman implementation of the IWestLaw interface (abstract class).

The Lawman prototype class is almost the same except for the value of the constant is different and there’s no method for crime preferences.

<?php
//Lawman.php
include_once('IWestLaw.php');
class Lawman extends IWestLaw
{
	const LAWSIDE="Lawman";
 
	public function setPlace($where)
	{
		$this->location=$where;
	}
 
	public function getPlace()
	{
		return $this->location;
	}
	function __clone(){}		
}
?>

As you can see, there’s not much to it. Because the abstract class has concrete methods for the name and photo properties, all that’s left for the Lawman class is to add getter/setter methods for the location and implement the __clone().

Work the Client Like a Rented Mule

In several design patterns described by the Gang of Four, you will find that the Client class is an integral part of the design pattern. Such is the case with the Prototype pattern. With all of the getter/setter methods, there’s a good deal of work for the Client class because it must specify characteristics through the setter methods and then make requests through the getters.

Requests begin with a single implementation of the concrete Outlaw and Lawman classes. Then the rest of the requests are through clones of the initial implementations. I used a table for displaying the data, and it’s really pretty simple once you take out the formatting. It’s just a lot of setting and getting of the clone.

<?php
//Client.php
function __autoload($class_name) 
{
    include $class_name . '.php';
}
class Client
{
    private $sheriff;
    private $desperado;
    public function __construct()
    {
	 $this->sheriff=new Lawman();
	 $this->desperado=new Outlaw();
	 echo '<!DOCTYPE html><html><head>';
	 echo "<link rel='stylesheet' type='text/css' href='ok.css'>";
	 echo "<h1> Outlaws and Lawmen of the Old West</h1>";
 
	 $laura = clone $this->desperado;
	 $laura->setPoster("LauraBullion");
	 $laura->setSobriquet("Laura Bullion<br />");
	 $laura->setPlace("Texas");
	 $laura->setCrime("Train Robbery");
	 echo "<table><tr><td>";
	 echo "<img src={$laura->getPic()}><br />";
	 echo $laura->getSobriquet();
	 echo  $laura->getPlace() . ": " . $laura::LAWSIDE . " <br />";
	 echo $laura->getCrime();
	 echo "</td><td>";
 
	 $bob = clone $this->desperado;
	 $bob->setPoster("younger");
	 $bob->setSobriquet("Bob Younger<br />");
	 $bob->setPlace("Missouri");
	 $bob->setCrime("Bank Robbery");
	 echo "<td>";
	 echo "<img src={$bob->getPic()}><br />";
	 echo $bob->getSobriquet();
	 echo $bob->getPlace() . ": " . $bob::LAWSIDE . " <br />";
	 echo $bob->getCrime();
	 echo "</td><td>";
 
	 $pearl = clone $this->desperado;
	 $pearl->setPoster("PearlHart");
	 $pearl->setSobriquet("Pearl Hart<br />");
	 $pearl->setPlace("Arizona");
	 $pearl->setCrime("Stage Robbery");
	 echo "<td>";
	 echo "<img src={$pearl->getPic()}><br />";
	 echo $pearl->getSobriquet();
	 echo  $pearl->getPlace() . ": " . $pearl::LAWSIDE . " <br />";
	 echo $pearl->getCrime();
	 echo "</td></tr>";
 
	 $wyatt = clone $this->sheriff;
	 $wyatt->setPoster("wyatt");
	 $wyatt->setSobriquet("Wyatt Earp<br />");
	 $wyatt->setPlace("Arizona");
	 echo "<td>";
	 echo "<img src={$wyatt->getPic()}><br />";
	 echo $wyatt->getSobriquet();
	 echo  $wyatt->getPlace() . ": " . $wyatt::LAWSIDE . " <br />";
	 echo "</td><td>";
	 $bill = clone $this->sheriff;
	 $bill->setPoster("wildbill");
	 $bill->setSobriquet("Wild Bill Hickcock<br />");
	 $bill->setPlace("Dakota Ter.");
	 echo "<td>";
	 echo "<img src={$bill->getPic()}><br />";
	 echo $bill->getSobriquet();
	 echo  $bill->getPlace() . ": " . $bill::LAWSIDE . " <br />";
	 echo "</td></tr></table>";
	 echo "</body></html>";
    }
}
$worker=new Client();
?>

I used a simple CSS for the display, and I got the color scheme from Kuler (search ‘OK Corral’). The hex values at the top of the CSS listing below are the color values from Kuler

@charset "UTF-8";
/*C9B39B,370300,6A685B,EBDBC2,A0866F*/
body
{
    background-color: #EBDBC2;
    font-family: verdana, helvetical, arial, sans-serif;
    color:#370300;
}
 
h1
{
    font-family: big caslon, copperplate, baskerville, serif;
    color: #C9B39B;
    background-color: #370300;
    text-align: center;
}

The Bigger the Better

Like virtually all design patterns, the bigger and more complex your program, the more value you will see in patterns. The Prototype pattern is a good example of where bigger programs can benefit from using it. The purpose of the Prototype is to cut down on resources used in a program by employing clones instead of new instances. As noted in Part I, the savings can be found in not duplicating the constructor function in the concrete prototype, and while this may not be much in a simple program, as it grows in size, the value increases.

In addition to saving resources, the Prototype pattern makes it very easy to update and change as well as add new concrete prototypes. For example, if you want, you can change this example to add separate classes for male and female outlaws and law-persons. Of course the first thing you want to do with this pattern is to add your favorite old west outlaw or lawman!

Share

Copyright © 2013 William Sanders. All Rights Reserved.

0 Responses to “PHP Prototype Design Pattern Part II: From Prototype to Production”


  • No Comments

Leave a Reply