JavaRush /Java Blog /Random-JA /Java デコレータ パターン

Java デコレータ パターン

Random-JA グループに公開済み
著書に『ヘッドファースト。Eric Freeman と Elizabeth Robson による「Design Patterns」では、これを次のように定義しています。 Decorator パターンは、オブジェクトに新しい機能を動的に提供し、機能を拡張するためのサブクラス化の代替手段です。 例を使用して、この定義をさらに詳しく見てみましょう。さらに別の現代宗教を創設し、それに対応するサービスを人々に提供する計画を立てているとします。なぜなら 現代のトレンドは菜食主義、エコロジー、人間開発を追求しており、何らかの理由で人々は「伝統的な」宗教(または最終的には無神論)に満足せず、その場合、あなたは主流に従って、別のニューエイジ宗教(既存の宗教を統合したもの)を作成します。宗教、それぞれから好きなものを取り出してください)。最初に、次のサービスを提供します。 1. 占い 2. 星占いの家。すべては次のようになります: もちろん、価格と説明を含むサービスインターフェイスがあります:)
public interface Service {
    public double getPrice();
    public String getLabel();
}
とサービス
public class Divination implements Service {
    private String label;
    private double price;

    public Divination(String label, double price) {
        this.label = label;
        this.price = price;
    }

    public double getPrice() {
        return this.price;
    }

    public String getLabel() {
        return this.label;
    }
}
public class Horoscope implements Service {
    private String label;
    private double price;

    public Horoscope(String label, double price) {
        this.label = label;
        this.price = price;
    }

    public double getPrice() {
        return this.price;
    }

    public String getLabel() {
        return this.label;
    }
}
さて、それに応じて、2つの注文が表示されました(タロットカードによる占いとクライアントからの個人的な星占い)。
public static void main(String[] args) {
    double cost;
    // Гадание на Таро
    Service taro = new Divination("Таро", 1000);
    // И персональный гороскоп
    Service personalHoroscope = new Horoscope("Персональный гороскоп", 9000);
    cost = taro.getPrice() + personalHoroscope.getPrice();

    System.out.println(cost);
}
そしてプログラムの結果:
10000.0
すべてがうまくいくでしょうが、あなたのような人はすでに何百人、何千人もいます。私たちは人々の霊性を開発し続ける必要があります。そうしないと、彼らはもはや興味を持ちません。そこで、現行サービスに追加のオプションをオプションとして提供した。たとえば、占いサービス (タロットまたはコーヒーかす) を選択する場合、追加オプションとして、チャクラまたはオーラの特性を注文できます (それぞれに独自の費用がかかります)。すべてがすでに正しく構成され、計算されている既存のサービス クラスを変更しないようにするには、どうすればこれを実装できるでしょうか。現在の占いに追加のクラス「占い + チャクラ」または「占い + オーラ」を作成できます。
public class Divination implements Service {
    // Здесь своя стоимость и другие методы
}
public class DivinationWithChakras implements Service {
    // Здесь своя стоимость и другие методы
}
public class DivinationWithAura implements Service {
    // Здесь своя стоимость и другие методы
}
または、単にサブクラス化を使用します。親クラスを子クラスに拡張する
public class DivinationWithAura extends Divination {
    public DivinationWithAura(String label, double price) {
        super(label, price);
    }
    // Здесь своя стоимость и другие методы
}
public class DivinationWithChakras extends Divination {
    public DivinationWithChakras(String label, double price) {
        super(label, price);
    }
    // Здесь своя стоимость и другие методы
}
しかし、欠点はすぐに目に見えて、全世界の精神性が発展し、新しい追加のオプション、つまり新しいクラスができるかもしれません。そして、まだ現在のものを組み合わせる必要がある場合、クラスは急速に成長するでしょう、少なくとも私たちはもう持っていません占いのクラスは、2 つのオプションを一緒に行うだけで十分です。別々に行う必要はありません。
public class DivinationWithChakrasAndAura implements Service {
    // Здесь своя стоимость и другие методы
}
ここで、Java の非常に「節約」な Decorator パターンを使用できます。これを行うには、追加オプションのクラスを作成します。このクラスも Service を実装しますが、Service も含みます。したがって、占いを注文する必要がある場合、2 つのオプションを組み合わせた場合でも、次のようになります。 インターフェイスは最初からそのままです。
public interface Service {
    public double getPrice();
    public String getLabel();
}
以前と同じ 2 クラスのサービス:
public class Divination implements Service {
    private String label;
    private double price;

    public Divination(String label, double price) {
        this.label = label;
        this.price = price;
    }

    public double getPrice() {
        return this.price;
    }

    public String getLabel() {
        return this.label;
    }
}
public class Horoscope implements Service {
    private String label;
    private double price;

    public Horoscope(String label, double price) {
        this.label = label;
        this.price = price;
    }

    public double getPrice() {
        return this.price;
    }

    public String getLabel() {
        return this.label;
    }
}
追加オプションのデコレータ
public class OptionDecorator implements Service {
    private Service service;
    private String label;
    private double price;

    public OptionDecorator(Service service, String label, double price) {
        this.service = service;
        this.label = label;
        this.price = price;
    }

    public double getPrice() {
        return this.price + service.getPrice();
    }

    public String getLabel() {
        return this.label + service.getLabel();
    }
}
そして、オプション自体 (現時点では 2 つ):
public class Aura extends OptionDecorator {
    public Aura(Service service) {
        super(service, "Характеристика ауры", 1500);
    }
}
public class Chakra extends OptionDecorator {
    public Chakra(Service service) {
        super(service, "Характеристика чакр", 500);
    }
}
まあ、注文自体は
public static void main(String[] args) {
    // Гадание на Таро
    Service taro = new Divination("Таро", 1000);
    Service chakra = new Chakra(taro);
    Service aura = new Aura(chakra);

    // И общая стоимость
    System.out.println(aura.getPrice());
}
3000.0
これは、メイン サービスと 2 つの追加オプションの合計の結果を示します。これは、追加のすべての必要がないことを意味します オプション (または両方の組み合わせ) を使用して、新しいクラスを作成します。なお、これらのオプションは、占いサービスだけでなく星占いサービスにも適用できます。したがって、近い将来、次の追加オプションを実装する必要がある場合、 - ソーシャル ネットワーク上のアバター パートナーの互換性 - リモート チャネリングによるキャッシュ フローの改善、追加のクラスを 2 つだけ作成する必要があります。
public class Channeling extends OptionDecorator {
    public Channeling(Service service) {
        super(service, "Полет в Поле Чудес", 99999);
    }
}
public class Avatar extends OptionDecorator {
    public Avatar(Service service) {
        super(service, "Ваша любовь в соц сетях", 5555);
    }
}
それらを任意のサービスに追加できます。
public static void main(String[] args) {
    // Гадание на Таро
    Service taro = new Divination("Таро", 1000);
    Service chakra = new Chakra(taro);
    Service aura = new Aura(chakra);

    // И общая стоимость
    System.out.println(aura.getPrice());

    // Гороскоп
    Service horoscope = new Horoscope("Персональный гороскоп", 1000);
    Service channenling = new Channeling(horoscope);
    Service avatar = new Avatar(channenling);

    // И общая стоимость
    System.out.println(avatar.getPrice());
}
そしてプログラムの結果(これが必要です):
3000.0
106554.0
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION