ベストを着て、あなたは素晴らしいです:デコレータパターンの分析

本稿はデザインパターンシリーズの3回目で、本日は主にデコレータパターンについて学びます。

そんな感じがないのかわかりません。読んで勉強すれば理解できても、しばらくすると忘れてしまうので、最初からいくつか質問をして、しばらくしてから復習しました。いくつかの質問は、学んだ知識を統合するために、これらの知識のポイントをあなたの脳に結びつけます。繰り返し考え、点を線に入れ、最後にナレッジブロックを形成し、それを消化できることを願っています。

質問して勉強する

  1. デコレータモードとは何ですか?
  2. どのようなシナリオでデコレータモードを使用する必要がありますか?
  3. デコレータパターンを実装する方法は?
  4. 共通のフレームワークまたはソースコードに反映されるのはどのような場合ですか?

デコレータパターンのコンセプト

まず、デコレータモードの説明を見てみましょう。

「デコレータモード」は、オブジェクトに責任を動的に付加します。機能を拡張するために、デコレーターは継承よりも柔軟な代替手段を提供します。

「新しい設計原則」:クラスは、拡張のために開かれ、変更のために閉じられる必要があります。

上記の定義はデコレータパターンの「役割」を説明していますが、実装で実際に「適用」する方法は説明していません。

次に、クラス図を調べ​​、クラス図と組み合わせて注意深く分析します。

上のクラス図から、デコレータパターンを理解しましょう

  • デコレータと装飾されたオブジェクトは同じスーパータイプを持っています
  • オブジェクト(コンポーネントの特定のコンポーネント)を1つ以上のデコレータでラップできます
  • デコレータと装飾されたオブジェクトは同じスーパータイプを持っているので、装飾されたオブジェクトは、元のオブジェクト(ラップ)の代わりにいつでも使用できます
  • 「デコレーターは、特定の目的を達成するために、委託されたデコレーターの動作の前または後に独自の動作を追加できます。」 これは、使用方法の後半で明らかになります。
  • オブジェクトはいつでも装飾できるので、実行時にお気に入りのデコレータでオブジェクトを動的かつ無制限に装飾できます

使用するシーン

現在、モカ、カプチーノ、マキアート、カンパーナなど、さまざまな種類のコーヒーを販売できるコーヒーショップがあります。また、特定のコーヒーごとに、ミルクフロス、キャラメル、豆乳、モカなどの異なるフレーバーを追加することもできます。最終的な価格を変えるには、異なるフレーバーが必要です。このシーンがOOのアイデアを使用して設計されている場合、どうしますか?

このシーンがデコレータモードに非常に適していることは間違いありません。まず、デコレータはコーヒーの種類であり、デコレータはさまざまなスパイスです。そのため、価格を計算するときに、レイヤーごとにコミッションして最終結果を得ることができます。コーヒーを飾るためにデコレータパターンを使用しているかどうかを確認します。

上記のスターバックスコーヒーの例を見てみると、これはデコレータパターンのクラス図フレームワークに対応していますか?誰もが慎重に考えることができます。

統合および拡張

上記のデコレータパターンを使用してシーンを作成します。既存のコードを変更せずに実装できるかどうかをテストし、デザインパターンの魅力を体験してみましょう。

「ダブルモカ豆乳フォームラテを注文しますか?」

とても便利ですか?デコレータモードを使って組み合わせを広げて魅力を体験しましょう。

実装

上記の例を組み合わせて、コードの実装を見てみましょう。

// 饮料的基础类,即component
public abstract class Beverage {
    String description = "Unknown Beverage";

    public String getDescription() {
 return description;  }  // cost必须在子类实现  public abstract double cost(); } 

調味料の抽象クラス、つまりデコレータクラス:

// 调料抽象类即装饰者类,这个类必须要能替换 Beverage,所以要继承自 Beverage 类
public abstract class CondimentDecorator extends Beverage {

    public abstract String getDescription();
}

これで基本クラスができたので、次は特定の飲み物です。

// 蓝山
public class BlueMountainCoffee extends Beverage {
    public BlueMountainCoffee() {
        description = "BlueMountainCoffee";
    }
 @Override  public double cost() {  return 0;  } }  // 卡布奇诺 public class Cappuccino extends Beverage {  public Cappuccino() {  description = "Cappuccino";  }  @Override  public double cost() {  return 23;  } }  // 意式浓缩咖啡 public class Espresso extends Beverage {  public Espresso() {  description = "Espresso";  }  @Override  public double cost() {  return 25;  } } // 拿铁 public class Latte extends Beverage {  public Latte() {  description = "Latte";  }  @Override  public double cost() {  return .89;  } } 

具象コンポーネントと抽象コンポーネントができたので、デコレーターパターンクラス図を比較することで具象デコレーターを実装できます。

// 摩卡是一个装饰者,所以扩展自 CondimentDecorator
public class Mocha extends CondimentDecorator {
    Beverage beverage;
    public Mocha(Beverage beverage) {
        this.beverage = beverage;
 }  @Override  public String getDescription() {  return beverage.getDescription() + ",Mocha";  }   // 首先调用委托被装饰者对象,以计算价钱,然后再加上Mocha价钱  @Override  public double cost() {  return .20 + beverage.cost();  } } // 豆浆 public class Soy extends CondimentDecorator {  Beverage beverage;  public Soy(Beverage beverage) {  this.beverage = beverage;  }  @Override  public String getDescription() {  return beverage.getDescription() + ",Soy";  }  @Override  public double cost() {  return 2.0 + beverage.cost();  } } 

次のステップは、デコレータモードの魅力を示すことです。

// 测试类
public class StarbuzzCoffee {
    public static void main(String[] args) {
        // 一杯Espresso,不加调料
        Beverage beverage = new Espresso();
 System.out.println(beverage.getDescription() + "$" + beverage.cost());  // 一杯加摩卡和豆浆的蓝山咖啡  Beverage beverage1 = new BlueMountainCoffee();  beverage1 = new Mocha(beverage1);  beverage1 = new Soy(beverage1);  System.out.println(beverage1.getDescription() + "$" + beverage1.cost());  } } 

現時点では、作成するオブジェクトはすべてハードコードされた新しいものであり、あまり友好的ではありません。フォローアップでファクトリモードを学習するので、問題ありません。引き続き学習してください。

実際のデコレーター

以下は、通常使用されるjdkのデコレータパターンの例です。

Java I / O

リストされた順序はデコレータからです->デコレート

LineNumberInputStream-> BufferedInputStream-> FileInputStream

一見すると、これは基本的に上記のデコレータパターンクラス図と同じです。JvaaI / Oパッケージのクラスをもう一度読むと、きっと「すごい」感嘆符が表示されると思います。


全文が終わりました!けんか

オリジナルにするのは簡単ではありません。少しでもお役に立てれば幸いです。この記事の内容があなたが得たものであると思われる場合は、[私が見ている]をクリックするか、転送して共有し、より多くの友達に見せてください。

おすすめ

転載: blog.csdn.net/taurus_7c/article/details/106969515