デザインパターンとは、システム設計におけるクラスやインターフェースの関係に名前をつけたものです。 GoFの23のパターンが有名です。デザインパターンというのは、どんなパターンなのか、パターンの目的は何かということを覚えることが非常に重要なのですが、これを実際に適用しようとした場合に、いつ適用していいかが見えてこないとお話になりません。

そこで、自分の勉強も兼ねつつ、パターンの実践時における使用場所や、パターンを適用するきっかけを見つけられるようにメモしておきます。

6回目は、機能拡張を統一的な方法で、自由に行うことができるDecoratorパターンです。

Decoratorパターン

Decoratorパターンは、既存のクラスに機能を付け加えたい場合、 既存機能に、少しだけ修飾を加えたい場合に使われるパターンです。

Decoratorのクラス図

Javaのクラスライブラリの例として、java.ioパッケージが最初に思い浮かびます。Javaには入出力(I/O)機能として、java.ioパッケージが用意されています。ファイルから一行ずつ読み取り、行番号をつけてファイルに書き込むという処理があるとします。

import java.io.*;
public class LineNumberAllocator {
  public void allocateLineNumber(String inFile, String outFile) 
      throws IOException {
    LineNumberReader in = new LineNumberReader(new FileReader(inFile));
    PrintWriter out = 
      new PrintWriter(new BufferedWriter(new FileWriter(outFile)));
 
    String line = null;
    while ( (line = in.readLine()) != null ) {
      out.println(in.getLineNumber() + ":" + line);
    }
    out.close();
    in.close();
  } 
}

4,5行目がDecoratorパターンが使われている部分です。FileReaderクラスの機能に行番号をつけるために、デコレートしているのが5行目です。FileWriterクラスのFile書き込み処理をバッファリングして、行ごとに書き出すためにデコレートしているのが6行目になります。

Decoratorパターンは、機能の拡張を、「元となるオブジェクト + 自クラスの機能」という方法で、実装しています。上記Javaでの例(太文字)の部分からなんとなく、雰囲気はつかめるかと思います。(newでオブジェクトを作り、機能拡張するクラスに渡している部分です。)

パターンの適用タイミング

Decoratorパターンは、すでにあるクラスに対して機能拡張を行うことを目的としています。オブジェクト指向に開放・閉鎖原則(Open・Closed Principle)というのがあります。

クラスの拡張には開いていて、クラスの修正には閉じている。つまり機能追加を自由にできるが、既存のクラスには修正を必要としないというのがこの原則の意味するところです。Decoratorパターンは、まさにこの原則に則っています。

既存のクラスに機能を拡張したい場合オブジェクトに修飾する形で、機能を付け加えたい場合に使えるパターンです。

実装サンプルと参考文献

Decoratorパターンの実装方法をもっと詳しく知りたい場合は、下記のサイトにアクセスするのをお勧めします。もしくは、参考書籍を載せておきますので、そちらをお買い求めください。(^^;


  • 独習シリーズのデザインパターン編。デザインパターンを一人でも学べます。

  • Sun Microsystemのお墨付き。GoF以外のパターンも学べます。

  • UMLを使って、オブジェクト指向のいいとこ取りができます。

  • デザインパターンだけではなく、ソフトウェア設計の原則やプラクティスまで学びたい人におすすめ