In this particular example, pippo’s code works very well. However, in larger (more real-life) problems, a static class won’t work. Reason: inheritance.
Showing a job can be done to many different outputs (HTML/XML/PDF) but all outputs have things in common, like some sort of header, the showing of the job number, or some footer. But you don’t want this to be visible to the outside world. Normally, you solve this by writing a base class that implements all important parts, and a single method that calls all other methods in the right order. Subclasses (special viewers) override only those methods that need it. For example:
class JobPrinter
{
function JobPrinter(&$job)
{
$this->job =& $job;
}
function show()
{
$this->showHeader();
$this->showJobNumber();
$this->showProjectManager();
$this->showOffice();
}
function showHeader()
{
}
function showJobNumber()
{
echo $this->job->getJobNumber();
}
function showProjectManager()
{
echo $this->job->getProjectManager();
}
function showOffice()
{
echo $this->job->getOffice();
}
function showFooter()
{
}
}
function HtmlJobPrinter extends JobPrinter
{
function showHeader()
{
echo "<p>\
";
}
function showJobNumber()
{
parent::showJobNumber();
echo "<br />\
";
}
function showProjectManager()
{
parent::showProjectManager();
echo "<br />\
";
}
function showOffice()
{
parent::showOffice();
echo "<br />\
";
}
function showFooter()
{
echo "</p>\
";
}
}
The various show…-methods (except for show() itself) are protected methods. Subclasses may call and/or override them, but for classes using a job printer, they should be invisible. So code using the HtmlJobPrinter above would only do this:
$printer =& new HtmlJobPrinter($job);
$printer->show();
In the above example, a class with only static methods certainly won’t work.
There is another issue with the current design of jobs and printing them. To me it makes sense that a job knows how to print itself in some way. You might want to print specific information not available through get-methods for example. A Job instance is the only object that knows everything about a specific job, so I think it would be logical that the class Job has a method show(). (Note: this is just a minor issue, so don’t think too much about it.) But how can class Job have a method show, if it doesn’t know which kind of output it should produce? The solution here is to move the method ‘show()’ from class JobPrinter to class Job, like this:
class Job
{
function show(&$printer)
{
$printer->showHeader();
$printer->showJobNumber($this->jobNumber);
$printer->showProjectManager($this->projectManager);
$printer->showOffice($this->office);
$printer->showFooter();
}
}
This solution has some advantages:
- A job knows how to show itself. As I said: to me that makes more sense than the other way around. But this is just a personal taste.
- A printer can be reused to show other jobs. Previously a printer was instantiated specifically for one job, which seems (to me again) a bit strange. Now you can instantiate a printer once, and use it again and again for different jobs.
On the other hand, there are is a disadvantage a well:
- All methods in the JobPrinter classes that used to be protected are now public, so the nice encapsulation is gone. (No more: ‘$printer->show()’);
So which design is better? I don’t know. It’s a matter of taste, and of what makes more sense to you as a designer. But note that going from one solution to the other can easily be done without changing to much of the code. So if you’re not happy with some solution after all, you can always modify the code to use another. The steps taken are not that hard.
Vincent