デザインパターンdecoratorについて勉強した

Decoratorパターンとは

オブジェクトをデコレーションしていくようなデザインパターンです。
ケーキのデコレーションや商品のラッピングのようにあるオブジェクトを中心に同じ型の別のオブジェクトでデコレーションしていきます。

コード例

ある言葉を持つオブジェクトを、別の言葉を持つオブジェクトでデコレーションしていきます。
具体的には「カー(車)」を「スーパー」でデコレーションして「スーパーカー」にします。

Itemクラス

public abstract class Item {

	private Item item ;

	public void setItem(Item item) {
		this.item = item;
	}

	protected abstract String getMyText() ;

	@Override
	public String toString() {
		String newtext = getMyText();
		if(item!=null) {
			newtext += item.toString();
		}

		return newtext;
	}
}

このパターンのメインとなるクラスです。
このクラスを継承するサブクラスが、デコレーションされるオブジェクトとなり、またデコレーションする側のオブジェクトになります。

itemフィールドはデコレーションされるオブジェクトを保持します。

setItemメソッドはitemフィールドのセッターです。

getMyTextメソッドは自身の持つ文字列を返すように実装します。
Carクラスは「カー」を、Superクラスは「スーパー」を返します。

toStringメソッドはデコレーション後の文字列を返します。
itemがnullの場合、つまり自分がもっともデコレーションされる中心である場合は自身の持つ文字列だけが返ります。

実装

WooperLooperクラス

public class WooperLooper extends Item {

	public WooperLooper() {
	}

	public WooperLooper(Item item) {
		setItem(item);
	}

	@Override
	protected String getMyText() {
		return "ウーパールーパー";
	}
}

Itemのサブクラスの一つです。

引数なしのコンストラクタが呼ばれた場合はこのインスタンスが中心となるオブジェクトとなります。
引数ありのコンストラクタの場合は引数のitemをデコレーションする側となります。

getMyTextメソッドが返すのは「ウーパールーパー」です。

Superクラス

public class Super extends Item {

	public Super() {
	}

	public Super(Item item) {
		setItem(item);
	}

	@Override
	protected String getMyText() {
		return "スーパー";
	}
}

クラス名が少し紛らわしいですが継承元のクラスという意味ではありません。
文字列「スーパー」を持つクラスです。

内容はウーパールーパーとほとんど同じです。

Carクラス

public class Car extends Item {

	public Car() {
	}

	public Car(Item item) {
		setItem(item);
	}

	@Override
	protected String getMyText() {
		return "カー";
	}
}

Perkerクラス

public class Perker extends Item {

	public Perker() {
	}

	public Perker(Item item) {
		setItem(item);
	}

	@Override
	protected String getMyText() {
		return "パーカー";
	}
}

Mainクラス

public class Main {

	public Main() {

		System.out.println(new WooperLooper());
		System.out.println(new WooperLooper(new Super(new Car(new Perker()))));
		System.out.println(new Super(new WooperLooper()));
		System.out.println(new WooperLooper(new Car()));
	}

	public static void main(String[] args) {
		new Main();
	}
}

実行

さあ実行しましょう。

ウーパールーパー
ウーパールーパースーパーカーパーカー
スーパーウーパールーパー
ウーパールーパーカー

特徴

デコレーションする側とされる側が同じ型であるため、組み合わせは無限に存在します。

compositeパターンにも似ていますね。
compositeパターンは収納のイメージでしたが、こちらは飾りつけのようなイメージになります。
1種類しかない代わりにたくさん入るcompositeか、たくさんの種類がある代わりに1つしか入らないdecoratorです。
もちろん、両方のいいとこ取りをした、たくさんの種類があり、たくさん入るようなクラスも作ることができますね。

まとめ

ウーパールーパースーパーカーパーカーって何なんでしょうね。