委譲とカプセル化

ひとりごとですのでトラックバックは無しで。
お題は既に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;
...