デコレータパターン

Mary-Kate Olsen
Mary-Kate Olsenオリジナル
2024-11-05 03:40:02231ブラウズ

デコレータパターンとは何ですか?

デコレーター パターンは、追加の動作をオブジェクトに動的に付加する構造設計パターンです。デコレータは、サブクラス化 (継承) ではなく合成によって柔軟な拡張理由を提供します。

いつ使用しますか?

実行時に小さな動作を追加してオブジェクトを構築したい場合は、Decorator パターンを使用します。

UML図

Decorator Pattern

デコレータ クラスは合成と継承を使用するため、その意図を理解することが重要です。
Decorator パターンでは、コンポーネントとデコレータの両方に同じ型を使用します。 Decorator は Component オブジェクトを合成して動作を取得します。つまり、Component オブジェクトに定義されているフィールドまたはメソッドを取得します。 Decorator は Component を継承 (拡張) するため、Decorator オブジェクトを Component オブジェクトとして宣言できます。

デコレータ パターンは、オープン-クローズの原則、つまり、拡張のために開き、変更のために閉じられることを実現します。コンポーネントやデコレータを追加するのは簡単です。たとえば、別の具体的なデコレータを追加したい場合は、それを表すクラスを作成し、Decorator クラスを拡張するだけです。

アイスクリームショップ用のシステムを開発していると想像してください。店内には様々なアイスクリームやトッピングが揃っています。システムは、アイスクリームの説明 (トッピングを含む) と価格を表示する必要があります。

Decorator Pattern

  • コンポーネント (アイスクリーム) とデコレータ (トッピング) には共通のインターフェイス IceCream クラスがあり、両方とも IceCream オブジェクトとして宣言されます。
  • それぞれの具体的なアイスクリームの価格は異なるため、原価計算方法は上書きされます。
  • Topping クラスは、具体的なトッピングのインターフェイスを提供し、IceCream への参照を保持します。
  • システムに別のトッピング、たとえばキャラメルソースが必要な場合は、Topping クラスを拡張する CaramelSource クラスを作成するだけです。

Javaでの実装

IceCream クラス:

// Component class
public abstract class IceCream {

    public String description = "Unknown ice cream";

    public String getDescription() {
        return description;
    }

    public abstract double cost();
}

チョコレートアイスクリームクラス:

// Concrete component class
public class ChocolateIceCream extends IceCream {

    public ChocolateIceCream() {
        description = "ChocolateIceCream";
    }

    @Override
    public double cost() {
        return 1.99;
    }
}

トップクラス:

// Base decorator class
public abstract class Topping extends IceCream {

    public IceCream iceCream;

    // All subclasses (concrete decorator classes) need to implement getDescription method,
    // by declaring this method as abstract, we enforce all subclasses to implement this method
    public abstract String getDescription();
}

MapleNuts クラス:

// Concrete decorator class
public class MapleNuts extends Topping {

    public MapleNuts(IceCream iceCream) {
        this.iceCream = iceCream;
    }

    @Override
    public String getDescription() {
        return iceCream.getDescription() + ", MapleNuts";
    }

    @Override
    public double cost() {
        return iceCream.cost() + .30;
    }
}

PeanutButterShell クラス:

// Concrete decorator class
public class PeanutButterShell extends Topping {

    public PeanutButterShell(IceCream iceCream) {
        this.iceCream = iceCream;
    }

    @Override
    public String getDescription() {
        return iceCream.getDescription() + ", PeanutButterShell";
    }

    @Override
    public double cost() {
        return iceCream.cost() + .30;
    }
}

クライアントクラス:

public class Client {

    public static void main(String[] args) {
        IceCream iceCream = new ChocolateIceCream();
        System.out.println(iceCream.getDescription() + ", $" + iceCream.cost());

        iceCream = new MapleNuts(iceCream);
        System.out.println(iceCream.getDescription() + ", $" + iceCream.cost());

        iceCream = new PeanutButterShell(iceCream);
        System.out.println(iceCream.getDescription() + ", $" + iceCream.cost());
    }
}

出力:

ChocolateIceCream, .99
ChocolateIceCream, MapleNuts, .29
ChocolateIceCream, MapleNuts, PeanutButterShell, .59

ここですべてのデザインパターンの実装を確認できます。
GitHub リポジトリ


追記
技術ブログを書くのは初めてです。文章を改善するためのアドバイスや、わかりにくい点がある場合は、コメントを残してください。
読んでいただきありがとうございます:)

以上がデコレータパターンの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。