委譲とカプセル化
ひとりごとですのでトラックバックは無しで。
お題は既にIWriterとその実装クラスがあってTPrinterでそれが丸利用できるとしたら(らしいです)。
... type TPrinter = class(TDevice, IWriter) private FWriter: TWriter; property AsWriter: TWriter read FWriter implements IWriter; ... end; ... procedure OutputToPrinter(Printer: TPrinter) Writer: IWriter; begin Writer := Printer; Writer.Write( ... ) end; ... procedure OutputToAnyDevice(Device: TDevice) Writer: IWriter; begin Writer := Device as IWriter; Writer.Write( ... ) end; ...
AはBだがCとしても使えるってやつで、委譲・委任というよりむしろ「集約」か。UML用語の集約はhas-aの一種なのですけれど、ここではCOM用語でありDelphi用語でもある集約。
しかし、かさタヌキはモンスターだがアイテムとしても使える、とか、このオブジェクトはIFolderManagerだがIActionManagerとしても使える、などオブジェクトとしての寿命が一致しているならともかく、もし一台のプリンタに出力先がふたつあったらとか、出力と無関係にプリンタは存在できるだろうなどと余計なことを考えてしまいますので、この例に限って言えば素直にこっちかな。
... type TPrinter = class(TDevice) private type TPrinterWriter = class(TWriter) ... end; public function CreateWriter: IWriter; override; ... end; ... procedure OutputToPrinter(Printer: TPrinter) Writer: IWriter; begin Writer := Printer.CreateWriter; Writer.Write(...) end; ... procedure OutputToAnyDevice(Device: TDevice) Writer: IWriter; begin Writer := Device.CreateWriter; Writer.Write( ... ) end; ...