perlmeditation
dws
A [Refactoring] for Perl.
<p align=center><i>You need to subclass a class that contains factory methods,
<br>
and also the class that the factory methods return.</i></p>
<p>
Change
<code> sub factory {
my $self = shift;
...
my $newInstance = new Bar(...);
...
return $newInstance;
}
</code>
to
<code> sub factory {
my $self = shift;
...
my newInstance = $self->factoryClass()->new(...);
...
return newInstance;
}
sub factoryClass {
"Bar"
}
</code>
<h3>Motivation</h3>
Factory methods return instances of some class known to the factory method.
Typically the class name is hard-coded.
If the class that holds the factory method is subclassed, the factory method is inherited, but will continue to return instances of the same hard-coded class.
This isn't always desirable. A set of cooperating base classes, one of which uses a factory method to create instances of the other, may both need to be subclassed. If a factory method uses a hard-coded class name, that factory method must be copied into a subclass and modified.
If the factory method performs other work (e.g., bookkeeping to account for the newly created instance), this can result in redundant code in the class hierarchy.
<p>
The solution is to "soft code" the class name that the factory method will create new instances of, by creating a new method that returns the class name, and using the new method in place of the hard-coded class name. The factory method can then be inherited by subclasses, which merely need to override the method that returns the class name.
<h3>Mechanics</h3>
<ul>
<li>Identify a factory method that hard-codes a class name.
<li>Create a new method that returns the class name.
<li>In the factory class, replace the hard-coded class name with an invocation of the new method.
<li>Test.
</ul>
<h3>Discussion</h3>
I first ran into the need for this when attempting to subclass pieces of GIFGraph, and finding myself initially thwarted by hard-coded class names in its factory methods. (I had to refactor methods to create some factory methods, but that's a separate story.)
<p>
This refactoring is hardly original thinking. It's been done in the Smalltalk world for years. If you know of an existing writeup of this refactoring for Perl, please provide a reference.
<p>