>Java >java지도 시간 >팩토리 메소드 패턴 이해

팩토리 메소드 패턴 이해

Susan Sarandon
Susan Sarandon원래의
2025-01-05 10:49:41826검색

Understanding the Factory Method Pattern

소개

안녕하세요 여러분, 저는 디자인 패턴에 대해 계속 배우면서 제가 알고 있는 지식을 공유하기 위해 이 글을 쓰고 있습니다. 오늘은 실제 응용프로그램에서 흔히 사용되는 디자인 패턴인 팩토리 메소드 패턴(Factory Method Pattern)을 소개하겠습니다. 제 글에 잘못된 부분이 있으면 댓글로 남겨주시면 기꺼이 수정해서 업데이트하겠습니다.

팩토리 메소드 패턴은 슈퍼클래스에서 객체를 생성하기 위한 인터페이스를 제공하지만, 생성될 객체의 유형을 하위 클래스에서 변경할 수 있도록 허용합니다.

문제

은행 애플리케이션이 있고 은행 송금, 페이팔 송금 등 다양한 방법을 통해 자금을 이체하는 기능을 구축하고 있다고 가정해 보겠습니다.

팩토리 메소드 패턴을 사용하기 전에 팩토리 메소드 패턴이 없는 시나리오를 살펴보겠습니다.

Java로 구현한 예를 들어보겠습니다.

상황: Person1이 이체 방법(은행 이체 또는 PayPal 이체)을 사용하여 Person2에게 돈을 보냅니다.

폴더 구조:

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단계: 결제 인터페이스 생성, 공통 메소드 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단계: 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단계: 기본 애플리케이션에서 팩토리를 사용합니다.

Factory Method 패턴을 사용하도록 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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.