Skip to content

Instantly share code, notes, and snippets.

@fujimisakari
Last active March 3, 2023 11:30
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fujimisakari/c1c1b9b10f101a2b2c62425e2cc4f820 to your computer and use it in GitHub Desktop.
Save fujimisakari/c1c1b9b10f101a2b2c62425e2cc4f820 to your computer and use it in GitHub Desktop.
Decoratorパターン

Decoratorパターン

HeadFirstデザインパターン Index

パターンについて

新しい振舞いを提供するために、オブジェクトをラップします。
オブジェクト毎に機能を追加したいときや機能を動的に付け外ししたいとき、同じインターフェース
を持つオブジェクトで被せるようにすることで、既存クラスに手を加えずに機能追加ができます。

HeadFirstデザインパターンでの定義

オブジェクトに付加的な責務を動的に付与します。 デコレータは、サブクラス化の代替となる柔軟な機能拡張手段を提供します。

パターン構造

decorator_pattern

構成要素
Component : 拡張される機能を定義した抽象クラス(abstractかinterfaceを利用する)
ConcreteComponent : Componentクラスで定義した機能を基本実装する、装飾される具象クラス。
Decorator : Componentを継承して装飾される具象クラスと型の一致を実現するためクラス。振舞いを取得するために継承してるわけではない
ConcreteDecoratorA, B : 具象クラスに機能の拡張(飾り付け)を行う具象クラス。

サンプル

コーヒーにトッピングを入れて注文した場合

飲み物(Component)

public abstract class Beverage {
	String description = "不明な飲み物";

	String getDescription() {
		return description;
	}

	public abstract double cost();
}

コーヒー_ダークロースト(ConcreteComponent)

public class DarkRoast extends Beverage {

	public DarkRoast() {
		description = "ダークロースト";
	}

	public double cost() {
		return 340;
    }
}

デコレータ(Decorator)

public abstract class CondimentDecorator extends Beverage {
	// Beverage.getDescriptionがabstractになってないので再定義
	abstract String getDescription();
}

トッピング_ホイップ(ConcreteDecoratorA)

public class Whip extends CondimentDecorator {

	Beverage beverage;

	public Whip(Beverage beverage) {
		this.beverage = beverage;
	}

	public double cost() {
		return beverage.cost() + 30;
	}

	public String getDescription() {
		return beverage.getDescription() + "、ホイップ入り";
    }
}

トッピング_ミルク(ConcreteDecoratorB)

public class Milk extends CondimentDecorator {

	Beverage beverage;

	public Milk(Beverage beverage) {
		this.beverage = beverage;
	}

	public double cost() {
		return beverage.cost() + 30;
	}

	public String getDescription() {
		return beverage.getDescription() + "、ミルク入り";
    }
}

実行コード

public class Client {
	public static void main(String[] args) {
		Beverage darkRoast = new DarkRoast();
		darkRoast = new Milk(darkRoast);
		darkRoast = new Whip(darkRoast);
		System.out.println("商品名: " + darkRoast.getDescription());
		System.out.println("値段: " + darkRoast.cost());
    }
}

// 実行結果
// 商品名: ダークロースト、ホイップ入り、ミルク入り
// 値段: 400
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment