この方法でのみあなたは悲しみから奮闘し、あなた自身を幸せにすることができるので、あなたの気分を変えることを学びなさい。
デザインパターンの学習、近い将来23のデザインパターンについてブログを書きますので、お楽しみに〜
—2021 / 1/11
定義
変更モードは、オブジェクト指向プログラミングの分野でクラスに新しい動作を動的に追加する設計モードです。関数に関しては、変更モードはサブクラスを生成するよりも柔軟性があるため、クラス全体ではなく一部の関数をオブジェクトに追加できます。
アプリケーションシナリオ
クラスが現在のクラスを変更せずに新しい機能を追加する必要がある場合、
たとえば、クラスの関数が「チャーハン」の場合、このクラスに「卵」関数を追加するか、「ベーコン」関数を追加して、元の「チャーハン」を「卵チャーハン」に変換します。
役割分析
- 抽象構造(コンポーネント)の役割:追加の責任を受け入れる準備ができているオブジェクトを標準化するための抽象インターフェースを定義します
- 具体的なコンポーネントの役割:抽象的な構造を実装し、装飾的な役割を通じてそれらにいくつかの責任を追加します。
- 抽象装飾(デコレータ)の役割:継承または抽象構築。具体的な構築例が含まれます。これにより、サブクラスを通じて具体的な構築機能を拡張できます。
- コンクリートデコレータの役割:抽象的な装飾の関連メソッドを実装し、コンクリート建設オブジェクトに追加の責任を追加します
簡単な分析:
- 抽象構築の役割:デコレータによる抽象クラス
- 具体的な構造の役割:装飾されたデバイスの抽象クラス、装飾されたデバイスを実装する
- 抽象装飾の役割:デコレータ抽象クラス
- 特定の装飾の役割:デコレータ、デコレータ抽象クラスを実装する
なぜこれほど多くの抽象クラスを定義するのですか?
依存性逆転の原則を遵守する(インターフェース指向プログラミング)
分析
UML类图(1.1)
:
- 麺
- チャーハン
- 食物
麺やチャーハンは食品に属しているため、食品から受け継がれています。食品ごとに新製品を追加する必要があります。
たとえば、卵を追加したい
現在、この食品カテゴリーはデコレーターになり、卵は「麺卵」または「チャーハン卵」の効果を実現するように装飾され、卵はデコレーターになります
元々チャーハンが10元で卵が1元だったら、卵チャーハンを11元に注文します
UML类图(1.2)
:
これが完成する最終レンダリングです。この画像が理解されていなくてもかまいません。最初にコードを見て、最後に戻ってこの画像を一目で確認しましょう。
コード
食品カテゴリー:
public abstract class Food {
private String name;//名字
private float price;//价格
//总价
public abstract float totalPrice();
set...
get...
}
FriedRiceチャーハン:
public class FriedRice extends Food {
public FriedRice() {
setName("炒饭");
setPrice(12);
}
@Override
public float totalPrice() {
//调用父类的价格方法 将set的值获取出来
return getPrice();
}
}
分析:
代码流程图(2.1)
:
ここで、FriedRice(Fried Rice)コンストラクターを呼び出す場合は、最初にチャーハンの価格を割り当てます。
麺:
public class Noodles extends Food {
public Noodles() {
setName("面食");
setPrice(9);
}
@Override
public float totalPrice() {
return getPrice();
}
}
FriedRice(チャーハン)と同じ
実装コード:
//面条
Noodles noodles = new Noodles();
Log.i("装饰器模式", noodles.getName() + "\t" +
noodles.getPrice() + "\t总价:" +
noodles.totalPrice()
);
// 炒饭
FriedRice friedRice = new FriedRice();
Log.i("装饰器模式", friedRice.getName() + "\t" +
friedRice.getPrice() + "\t总价:" +
friedRice.totalPrice()
);
Log图(3.1)
:
これは非常に簡単です、私はそれを説明しません、ここでは飾り付けと呼ばれ、卵を取り、彼を「卵麺」または「卵チャーハン」にさせます、ここの卵はデコレータです。
GarnishFood装飾カテゴリ:
public abstract class GarnishFood extends Food {
Food food;
public GarnishFood(Food food) {
this.food = food;
}
set..
get..
}
卵の卵:
public class Egg extends GarnishFood{
public Egg(Food food) {
super(food);
setName("鸡蛋");
setPrice(1);
}
@Override
public float totalPrice() {
return getPrice()+ getFood().totalPrice();
}
}
卵卵totalPrice()パラメーター分析:
- getPrice()パラメーター:
赤いボックス:ここでは、getPrice()はコンストラクターによって1に設定され
ます。黄色のボックス:eggクラス(Egg)は装飾クラス(GarnishFood)を継承するため、装飾クラスはFoodを継承するため、ここで呼び出します。食品のすべてのトップレベルのメソッドです - getFood()。totalPrice()パラメーター:これ
は最上位の親クラスのFoodメソッドでもある
ため、getFood()。totalPrice()=合計価格
使用コード:
Noodles nd = new Noodles();
Log.i("装饰器模式", nd.getName() + "\t" +
nd.getPrice() + "\t总价:" +
nd.totalPrice());
Egg egg = new Egg(nd);
Log.i("装饰器模式", egg.getName() + "\t" +
egg.getPrice() + "\t总价:" +
egg.totalPrice());
Egg egg1 = new Egg(egg);
Log.i("装饰器模式", egg1.getName() + "\t" +
egg1.getPrice() + "\t总价:" +
egg1.totalPrice());
Log图(3.2)
:
卵を追加しないと、合計金額が+1元であることがわかります
たとえば、ベーコンを追加できるなど、今すぐ新製品を追加できる場合は、コードの書き方を見てみましょう〜
ベーコンベーコン:
public class Bacon extends GarnishFood{
public Bacon(Food food) {
super(food);
setName("培根");
setPrice(3.5f);
}
@Override
public float totalPrice() {
return super.getPrice() + super.getFood().totalPrice();
}
}
使用コード:
Bacon bacon = new Bacon(egg1);
Log.i("装饰器模式", bacon.getName() + "\t" +
bacon.getPrice() + "\t总价:" +
bacon.totalPrice());
Log图(3.3)
:
総括する
コスプレ:
- 抽象構造の役割:Food()
- 特定の構造の役割:FriedRice()。Noodles()
- 抽象的な装飾的な役割:GarnishFood()
- 特定の装飾の役割:Egg()。Bacon()
デコレータモードは、クラスの元の機能を変更せずに新しいものに装飾することと、元のクラスの機能を、開閉の原則(拡張のために開く、変更するために閉じる)に従って装飾することです。
利点:
- デコレータモードは、継承よりも柔軟な拡張機能をもたらすことができます
- 装飾モードと装飾された人は独立して開発することができ、互いに結合されることはありません。
- デコレータモードは、開閉の原則に準拠しています(拡張のために開く、変更のために閉じる)
短所:
- 継承が必要なため、各クラスの結合は非常に高くなります
オリジナリティは簡単ではありません、あなたの好きなものは私にとってあなたの最大のサポートです、あなたの好きなものを残してください〜