ホームページ >Java >&#&チュートリアル >ファクトリ メソッド パターンを理解する

ファクトリ メソッド パターンを理解する

Susan Sarandon
Susan Sarandonオリジナル
2025-01-05 10:49:41826ブラウズ

Understanding the Factory Method Pattern

導入

皆さん、こんにちは。私はデザイン パターンについて学び続けているので、私の知識を共有するためにこの投稿を書いています。今日は、実際のアプリケーションで一般的に使用されるデザイン パターンであるファクトリー メソッド パターンを紹介します。私の投稿に間違いがある場合は、お気軽に以下にコメントしてください。喜んで修正して更新します。

ファクトリ メソッド パターンは、スーパークラスでオブジェクトを作成するためのインターフェイスを提供しますが、サブクラスは作成されるオブジェクトのタイプを変更できます。

問題

銀行アプリケーションがあり、銀行振込、PayPal 振込などのさまざまな方法で送金するための機能を構築しているとします。

ファクトリー メソッド パターンを使用する前に、それを使用しないシナリオを調べてみましょう。

Java で実装された例を示します。

状況: 人物 1 が振込方法 (銀行振込または PayPal 振込) を使用して人物 2 に送金します。

フォルダー構造:

problem/
├─ BankApp.java
├─ service/
│  ├─ PaypalTransferPayment.java
│  ├─ BankTransferPayment.java
├─ data/
│  ├─ Person.java

メイン アプリケーションで、デフォルトの金額を持つ 2 人の人物を作成します。

package problem;

import problem.data.Person;

public class BankApp {
    public static void main(String[] args) {
        Person person1 = new Person("John", 1000);
        Person person2 = new Person("Jane", 500);
    }
}

BankTransferPayment クラスと PaypalTransferPayment クラスを作成します。

package problem.service;

import problem.data.Person;

public class BankTransferPayment {
    public void processPayment(Person fromAccount, Person toAccount, float amount) {
        fromAccount.withdraw(amount);
        toAccount.deposit(amount);
        System.out.println("Bank transfer payment success.");
    }
}
package problem.service;

import problem.data.Person;

public class PaypalPayment {
    public void processPayment(Person fromAccount, Person toAccount, float amount) {
        fromAccount.withdraw(amount);
        toAccount.deposit(amount);
        System.out.println("Paypal transfer payment success.");
    }
}

メイン関数にロジックを実装します。

package problem;

import problem.data.Person;
import problem.service.BankTransferPayment;
import problem.service.PaypalPayment;

public class BankApp {
    public static void main(String[] args) {
        Person person1 = new Person("John", 1000);
        Person person2 = new Person("Jane", 500);

        String paymentMethod = "BANK_TRANSFER";

        if (paymentMethod.equals("BANK_TRANSFER")) {
            BankTransferPayment bankTransferPayment = new BankTransferPayment();
            bankTransferPayment.processPayment(person1, person2, 100);

            System.out.println("===Method bank_transfer===");
            System.out.println(person1.getName() + " has " + person1.getAmount());
            System.out.println(person2.getName() + " has " + person2.getAmount());
        } else if (paymentMethod.equals("PAYPAL")) {
            PaypalPayment paypalPayment = new PaypalPayment();
            paypalPayment.processPayment(person1, person2, 100);

            System.out.println("===Method paypal===");
            System.out.println(person1.getName() + " has " + person1.getAmount());
            System.out.println(person2.getName() + " has " + person2.getAmount());
        }
    }
}

現在の実装の問題:

  1. 反復コード: processPayment メソッドのロジックは、支払い方法ごとに繰り返されます。
  2. 密結合コード: アプリケーションは支払い方法オブジェクト自体を作成する必要があるため、アプリケーションの拡張が困難になります。
  3. スケーラビリティの問題: 新しい支払い方法が追加されると、ソース コードがより複雑になり、保守が困難になります。

解決

上記の状況の解決策は、ファクトリ メソッド パターンを使用することです。では、それをどのように適用すればよいでしょうか?

上記の例では:

  1. 各 if-else ブロックは processPayment メソッドを呼び出すため、コードの繰り返しが発生します。
  2. オブジェクトは支払いタイプの条件に基づいて作成されるため、過剰な if-else ステートメントでコードが複雑になります。

これらの問題を解決するために、Factory Method パターンが段階的に実装されます。

フォルダー構造 (ソリューション):

solution/
├─ BankApp.java
├─ service/
│  ├─ payments/
│  │  ├─ Payment.java
│  │  ├─ PaymentFactory.java
│  │  ├─ BankTransferPayment.java
│  │  ├─ PaypalTransferPayment.java
├─ data/
│  ├─ Person.java

ステップ 1: Payment インターフェースを作成し、共通メソッド processPayment を宣言します

package solution.service.payments;

import solution.data.Person;

// Step 1: Create an interface for the payment
public interface Payment {
    void processPayment(Person fromAccount, Person toAccount,float amount);
}

ステップ 2: Payment インターフェイスを実装する BankTransferPayment クラスと PaypalTransferPayment クラスを作成します。

package solution.service.payments;

import solution.data.Person;

// Step 2: Create a class that implements the Payment interface
public class BankTransferPayment implements Payment {
    @Override
    public void processPayment(Person fromAccount, Person toAccount, float amount) {
        fromAccount.withdraw(amount);
        toAccount.deposit(amount);
        System.out.println("Bank transfer payment success.");
    }
}
package solution.service.payments;

import solution.data.Person;

public class PaypalPayment implements Payment{
    @Override
    public void processPayment(Person fromAccount, Person toAccount, float amount) {
        fromAccount.withdraw(amount);
        toAccount.deposit(amount);
        System.out.println("Paypal transfer payment success.");
    }
}

ステップ 3: PaymentFactory クラスを作成します。このクラスは、支払いタイプの条件に基づいてオブジェクトを作成する役割を果たします。

package solution.service.payments;

public class PaymentFactory {
    public Payment createPayment(String paymentType) {
        if (paymentType == null) {
            return null;
        }
        if (paymentType.equalsIgnoreCase("BANK_TRANSFER")) {
            return new BankTransferPayment();
        } else if (paymentType.equalsIgnoreCase("PAYPAL")) {
            return new PaypalPayment();
        }
        return null;
    }
}

ステップ 4: メイン アプリケーションでファクトリを使用します。

ファクトリ メソッド パターンを使用するように main 関数を変更します。

problem/
├─ BankApp.java
├─ service/
│  ├─ PaypalTransferPayment.java
│  ├─ BankTransferPayment.java
├─ data/
│  ├─ Person.java

ファクトリ メソッド パターンを使用する利点

  • コードはよりクリーンで、より構造化されています。
  • 複数の if-else ブロックでの processPayment への繰り返しの呼び出しは 排除されます
  • オブジェクトの作成はファクトリーに委任され、保守性が向上します。

ボーナス

PaymentFactory クラスをオープン/クローズ原則 (SOLID 原則から) に準拠させるには、戦略パターン を使用して動的登録メカニズムを実装できます。

PaymentFactory.java を更新しました:

package problem;

import problem.data.Person;

public class BankApp {
    public static void main(String[] args) {
        Person person1 = new Person("John", 1000);
        Person person2 = new Person("Jane", 500);
    }
}

メイン アプリケーションで更新されたファクトリーを使用します。

package problem.service;

import problem.data.Person;

public class BankTransferPayment {
    public void processPayment(Person fromAccount, Person toAccount, float amount) {
        fromAccount.withdraw(amount);
        toAccount.deposit(amount);
        System.out.println("Bank transfer payment success.");
    }
}

このアプローチを適用することで、コードは オープン/クローズの原則 に準拠し、PaymentFactory ロジックを変更せずに新しい支払い方法を追加できるようになります。

この投稿がお役に立てば幸いです。

参考文献:

第一人者のデザインパターン

以上がファクトリ メソッド パターンを理解するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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