Re: Template Method vs Strategy (was: Exceptional C++ Item 23)
In article <pan.2006.05.16.09.07.06.406081@blueyonder.co.uk>,
seanf <clcppm-poster@this.is.invalid> wrote:
The item was originally gotw 15 back in the day, but the
archived discussion does not help me.
At question 3, this item advocates splitting the public nonvirtual
template method and the derivation interface into separate classes,
on the grounds that exposing a generic algorithm to clients and
using specialization from the derived class are two different
responsibilities.
I take the point about compilation dependencies, but otherwise I'm
finding that I prefer the original class better. Removed from the
template method class, the derivation class's members start to look
pretty unrelated.
When would you consider splitting a template method class like this
in the real world? Would there have to be special circumstances, or
is this an acceptable idiom to use generally?
Template Method and Strategy have the same goal of implementing a high
level algorithm independent of low level details. TM is easy to build,
and light on CPU and Memory, but is inflexible. Once you have created
a TM object, it's low level details cannot be changed. Strategy is
more flexible, but is harder to build and take a bit more CPU and
Memory.
Example: Template Method.
public abstract class FileTransferProtocol {
public void transfer(File f) {
while ((Packet p = f.read()) != null)
sendPacket(p)
}
public abstract void sendPacket(Packet p);
}
public class XModemFileTransferProtocol extends FileTransferProtocol {
public void sendPacket(Packet p) {
// XModem way of sending a packet
}
}
public class ZModemFileTransferProtocol extends FileTransferProtocol {
pupblic void sendPacket(Packet p) {
//ZModem way of sending a packet
}
}
Now you can use this just by saying:
FileTranferProtocol ftp = new XModemFileTransferProtocol();
ftp.transfer(myFile);
Easy and cheap. However, the ftp object cannot be changed to transfer
using ZModem. Once created it is bound to be an
XModemFileTransferProtocol. Clearly this doesn't mean you can't
reassign the ftp variable, you can. But the created instance cannot be
changed to be a YModemFileTransferProtocol.
Strategy:
public class FileTransfer {
private Protocol protocol;
public FileTransfer(Protocol p) {
protocol = p;
}
public void transfer(File f) {
while ((Packet p = f.read()) != null)
protocol.sendPacket(p)
}
}
interface Protocol {
public void sendPacket(Packet p);
}
public class XModemProtocol implements Protocol {
public void sendPacket(Packet p) {
// XModem way of sending a packet
}
}
public class ZModemProtocol implements Protocol {
pupblic void sendPacket(Packet p) {
//ZModem way of sending a packet
}
}
Building this is a bit more complicated:
FileTransfer ft = new FileTransfer(new XModemProtocol);
ft.transfer(myFile);
However, you could add methods to FileTransfer that would allow you to
change the Protocol, even in the midst of a transfer.
So, Template Method simpler and cheaper than strategy; but Strategy is
a bit more flexible than Template Method. The choice is a cost/benefit
tradeoff between these issues.
--
Robert C. Martin (Uncle Bob) | email: unclebob@objectmentor.com
Object Mentor Inc. | blog: www.butunclebob.com
The Agile Transition Experts | web: www.objectmentor.com
800-338-6716 |
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]