1. デコレータパターン
Decoratorパターンを使用すると、既存のオブジェクトの構造を変更せずに、新しい機能を追加できます。このタイプのデザイン パターンは構造パターンであり、既存のクラスのラッパーとして機能します。
使用するシーン:
-
他のオブジェクトに影響を与えることなく、動的かつ透過的に個々のオブジェクトに責任を追加します。
-
関数はオブジェクトに動的に追加する必要があり、これらの関数は動的に取り消すこともできます。継承によってシステムを拡張できない場合、または継承によってシステムの拡張や保守が困難な場合。
このパターンは、元のクラスをラップし、クラス メソッド シグネチャの整合性を維持しながら追加機能を提供するデコレータ クラスを作成します。
例:
interface Coffee {
double getCost();
String getIngredients();
}
class SimpleCoffee implements Coffee {
@Override
public double getCost() {
return 1;
}
@Override
public String getIngredients() {
return "Coffee";
}
}
abstract class CoffeeDecorator implements Coffee {
private final Coffee decoratedCoffee;
public CoffeeDecorator(Coffee coffee) {
this.decoratedCoffee = coffee;
}
@Override
public double getCost() {
return decoratedCoffee.getCost();
}
@Override
public String getIngredients() {
return decoratedCoffee.getIngredients();
}
}
class MilkCoffee extends CoffeeDecorator {
public MilkCoffee(Coffee coffee) {
super(coffee);
}
@Override
public double getCost() {
return super.getCost() + 0.5;
}
@Override
public String getIngredients() {
return super.getIngredients() + ", Milk";
}
}
class WhipCoffee extends CoffeeDecorator {
public WhipCoffee(Coffee coffee) {
super(coffee);
}
@Override
public double getCost() {
return super.getCost() + 0.7;
}
@Override
public String getIngredients() {
return super.getIngredients() + ", Whip";
}
}
public class DecoratorExample {
public static void main(String[] args) {
Coffee c = new SimpleCoffee();
System.out.println("Cost : " + c.getCost() + "; Ingredients : " + c.getIngredients());
c = new MilkCoffee(c);
System.out.println("Cost : " + c.getCost() + "; Ingredients : " + c.getIngredients());
c = new WhipCoffee(c);
System.out.println("Cost : " + c.getCost() + "; Ingredients : " + c.getIngredients());
}
}
この例では、 getCost()とgetIngredients()という 2 つのメソッドを持つ抽象インターフェイスCoffeeを定義する単純なコーヒー飲料ショップを示します。
次に、単純なコーヒー飲料SimpleCoffeeを定義します。これはCoffeeインターフェイスを実装し、デフォルトの価格と材料を持ちます。
長所と短所
アドバンテージ
-
デコレータ パターンは継承よりも柔軟性を提供できます。
-
オブジェクトの機能を動的に拡張し、実行時にさまざまなデコレータを選択してさまざまな動作を実現できます。
-
さまざまな具体的な装飾クラスとこれらの装飾クラスの順列を使用することにより、さまざまな動作の多くの組み合わせを作成できます。複数の特定の装飾クラスを使用して同じオブジェクトを装飾し、より強力なオブジェクトを取得できます。
-
特定コンポーネントクラスと特定装飾クラスは独立して変更可能 ユーザは必要に応じて新たに特定コンポーネントクラスと特定装飾クラスを追加し、組み合わせて使用することが可能 元のコードを変更する必要はなく、仕様に沿っています「開閉原理」。
欠点がある
-
小さなオブジェクトが多数生成され、システムの複雑さが増加します。
-
この継承よりも柔軟な機能は、デコレーション モードが継承よりもエラーが発生しやすく、トラブルシューティングも難しいことを意味します。複数回装飾されたオブジェクトの場合、デバッグ中にエラーを見つけるには段階的なトラブルシューティングが必要になる場合があり、これはより面倒です。
2.戦略モード
戦略パターンは、アルゴリズムのファミリーを定義し、各アルゴリズムを相互に置き換えられるようにカプセル化する共通の設計パターンです。戦略パターンにより、アルゴリズムを使用するクライアントとは独立してアルゴリズムを変更できるため、クライアントはソース コードを変更せずにアルゴリズムの使用方法を変更できます。
以下は、ストラテジー パターンを使用して並べ替えを実装するサンプル コードです。さまざまな並べ替えアルゴリズムを使用して整数配列を並べ替えできるSorterクラスがあり、使用される特定のアルゴリズムがクライアント コードによって指定されているとします。
まず、並べ替えアルゴリズムを表すインターフェイスSortStrategyを定義する必要があります。このインターフェイスには、整数配列をパラメータとして受け取り、ソートされた配列を返すsortメソッドが含まれています。
public interface SortStrategy {
int[] sort(int[] array);
}
次に、特定の並べ替えアルゴリズムを定義できます。ここでは、バブル ソートとクイック ソートという 2 つのソート アルゴリズムを実装します。これらはすべてSortStrategyインターフェイスを実装しています。
public class BubbleSort implements SortStrategy {
public int[] sort(int[] array) {
// 冒泡排序算法的具体实现
// ...
return sortedArray;
}
}
public class QuickSort implements SortStrategy {
public int[] sort(int[] array) {
// 快速排序算法的具体实现
// ...
return sortedArray;
}
}
これで、 Sorterクラスを定義できます。これには、整数の配列と並べ替え戦略をパラメーターとして受け入れる並べ替えメソッドが含まれています。並べ替え戦略は、 SortStrategyインターフェイスを実装するクラスのインスタンスです。Sorterクラスのsortメソッドは、渡された並べ替え戦略を使用して配列を並べ替えます。
public class Sorter {
private SortStrategy strategy;
public void setStrategy(SortStrategy strategy) {
this.strategy = strategy;
}
public int[] sort(int[] array) {
return this.strategy.sort(array);
}
}
最後に、クライアント コードでSorterクラスを使用して配列を並べ替えることができます。まず整数配列を作成し、次にSorterオブジェクトを作成し、並べ替え戦略をバブル ソートに設定します。次に、Sorterオブジェクトのsortメソッドを使用して配列を並べ替え、結果を出力します。次に、並べ替え戦略をクイック 並べ替えに設定し、配列を再度並べ替えて、結果を出力します。
public static void main(String[] args) {
int[] array = {5, 2, 4, 6, 1, 3};
Sorter sorter = new Sorter();
sorter.setStrategy(new BubbleSort());
int[] sortedArray = sorter.sort(array);
System.out.println(Arrays.toString(sortedArray)); // 输出 [1, 2, 3, 4, 5, 6]
sorter.setStrategy(new QuickSort());
sortedArray = sorter.sort(array);
System.out.println(Arrays.toString(sortedArray)); // 输出 [1, 2, 3, 4, 5, 6]
}
戦略パターンは、クラスの動作を動的に変更できる動作設計パターンです。
このコードには、BubbleSort と QuickSort という 2 つの並べ替えアルゴリズムがあります。
Sorter クラスでは、Strategy パターンを使用して、使用する並べ替えアルゴリズムを動的に選択します。
メインクラス Main で、Sorter オブジェクトを作成し、BubbleSort アルゴリズムを使用してそれを並べ替えます。
その後、 setSortStrategy() メソッドを使用して、使用する並べ替えアルゴリズムを変更できます。
実際、ストラテジ パターンとテンプレート パターンは非常に似ていますが、同じではありません。次の章を見てみましょう: Java デザイン パターンの詳細な説明 (3)