読者です 読者をやめる 読者になる 読者になる

新人SEの学習記録

14年度入社SEの学習記録用に始めたブログです。気づけば社会人3年目に突入。

学習記録:デザインパターン

[学習記録] デザインパターン

内容:2章 Adapterパターン

概要
  • PCのACアダプター
    • 交流100Vを直流12Vに変換
    • 直流12VのPCを交流100Vの環境にadapt(適合)させている
  • 既に提供されているものと必要な形の間のずれを埋めるようなデザインパターンAdapterパターンと呼ぶ
    • Adapterパターンには以下の2つが存在
    • クラスによるAdapterパターン(継承を利用)
    • インスタンスによるAdapterパターン(委譲を利用)
  • サンプルプログラムの説明
クラス名 役割 説明
Banner 提供されているもの 保持している文字列を中括弧/鍵括弧で囲んで出力するメソッドを持つ
Print 必要なもの 必要とするインタフェースを提供
PrintBanner 変換装置(Adapter) PrintとBanner間の変換を行う
Main - テスト実行用
クラスによるAdapterパターン(継承を利用)
  • Bannerクラス
    • 文字列を中括弧で囲むshowWithBrace()、鍵括弧で囲むshowWithBox()を定義
public class Banner {
	private String string;
	public Banner(String string) {
		this.string = string;
	}
	
	public void showWithBrace() {
		System.out.println("{" + string + "}");
	}
	
	public void showWithBox() {
		System.out.println("[" + string + "]");
	}
}
  • Printインタフェース
    • 必要なAPIであるprintInCurlyBrackets()printInSquareBrackets()を宣言
public interface Print {
	public abstract void printInCurlyBrackets();
	public abstract void printInSquareBrackets();
}
  • PrintBannerクラス
    • PrintとBannerの変換を行うためにBannerクラスを継承
    • Printインタフェースを実装し、APIの中でBannerクラスのメソッドを呼んでいる
public class PrintBanner extends Banner implements Print {
	public PrintBanner(String string) {
		super(string);
	}

	@Override
	public void printInCurlyBrackets() {
		showWithBrace();
	}

	@Override
	public void printInSquareBrackets() {
		showWithBox();
	}
}
  • Mainクラス
public class Main {

	public static void main(String[] args) {
		Print print = new PrintBanner("hoge");
		print.printInCurlyBrackets();
		print.printInSquareBrackets();
	}
}
インスタンスによるAdapterパターン(委譲を利用)
  • Printがインタフェースではなくクラスだと仮定
public abstract class Print {
	public abstract void printInCurlyBrackets();
	public abstract void printInSquareBrackets();
}
  • PrintBannerクラス
    • PrintとBannerの両方を継承することは不可能
    • Bannerクラスのインスタンスを保持し、フィールド経由でBannerクラスのメソッドを呼び出し
public class PrintBanner extends Print {
	private Banner banner;
	public PrintBanner(String string) {
		this.banner = new Banner(string);
	}

	@Override
	public void printInCurlyBrackets() {
		banner.showWithBrace();
	}

	@Override
	public void printInSquareBrackets() {
		banner.showWithBox();
	}
}
補足
  • どんなときに使うの?
    • 必要なメソッドがあるなら、それをプログラミングすれば良い
    • しかし、既に存在するクラスがあり、それが十分にテストされているものならば再利用したい
    • 既存のクラスに一皮かぶせて必要なクラスを作り出すのがAdapterパターン
    • 古いバージョンとの互換性を保つためのAdapterを作ることでメンテナンスが楽に
  • 既存のクラスを弄るのではダメなのか?
    • 既存のクラスをもう一度テストする必要がある
    • 既存クラスのソースがない場合でもAdapterパターンなら問題なし
関連パターン
  • Bridgeパターン(9章)
    • 機能と実装の階層を結びつける
  • Decoratorパターン(12章)
    • インタフェースを変えずに機能を追加する