본문으로 건너뛰기

เนื้อหาภาษาไทย / 태국어 콘텐츠

시스템 가이드 검수 완료된 콘텐츠

Factory Pattern: สร้าง PaymentGatewayFactory

บทความนี้อธิบายถึงการนำ Factory Pattern มาใช้ในการสร้างระบบ Payment Gateway เพื่อให้การสร้าง Instance ของคลาส Payment Gateway ต่างๆ (เช่น StripePayment, PayPalP...

Workshop: สร้างระบบ Payment Gateway (7/10) - Factory Pattern: สร้าง PaymentGatewayFactory

ในบทที่ผ่านมา เราได้สร้างคลาส StripePayment และ PayPalPayment ซึ่งทั้งสองคลาสนี้ Implement PaymentGatewayInterface ทำให้เราสามารถจัดการการชำระเงินผ่าน Stripe และ PayPal ได้อย่างอิสระ อย่างไรก็ตาม การสร้าง Instance ของคลาสเหล่านี้โดยตรงในโค้ดของเรา อาจทำให้โค้ดดูซับซ้อนและยากต่อการบำรุงรักษาในระยะยาว

ดังนั้น ในบทนี้ เราจะมาเรียนรู้เกี่ยวกับ Factory Pattern ซึ่งเป็น Design Pattern ที่ช่วยให้เราสร้าง Object ได้อย่างยืดหยุ่นและง่ายต่อการจัดการ โดยเราจะสร้าง PaymentGatewayFactory เพื่อสร้าง Instance ของ StripePayment หรือ PayPalPayment ตามต้องการ

Factory Pattern คืออะไร

Factory Pattern เป็น Creational Design Pattern ที่ช่วยให้เราสร้าง Object โดยไม่ต้องระบุคลาสของ Object ที่เราต้องการสร้างโดยตรง กล่าวคือ เราจะสร้าง Factory Class ที่มีหน้าที่ในการสร้าง Object ตามเงื่อนไขที่เรากำหนด

ทำไมต้องใช้ Factory Pattern?

  • Decoupling: ลดการพึ่งพาระหว่างคลาสที่ใช้ Object กับคลาสที่สร้าง Object ทำให้โค้ดมีความยืดหยุ่นและง่ายต่อการแก้ไข
  • Abstraction: ซ่อนรายละเอียดการสร้าง Object ทำให้โค้ดที่เรียกใช้งาน Factory Class ไม่จำเป็นต้องรู้ว่า Object นั้นถูกสร้างขึ้นมาอย่างไร
  • Flexibility: สามารถเปลี่ยนแปลงวิธีการสร้าง Object ได้ง่าย โดยไม่ต้องแก้ไขโค้ดที่เรียกใช้งาน Factory Class
  • Centralized Object Creation: รวม logic การสร้าง Object ไว้ในที่เดียว ทำให้ง่ายต่อการบำรุงรักษาและแก้ไข

Trade-offs ของ Factory Pattern:

  • Complexity: อาจเพิ่มความซับซ้อนให้กับโค้ดในระยะแรก แต่จะช่วยลดความซับซ้อนในระยะยาว
  • Overhead: อาจมี overhead ในการสร้าง Factory Class แต่โดยทั่วไปแล้ว overhead นี้จะน้อยมาก

ในบริบทของระบบ Payment Gateway ของเรา Factory Pattern จะช่วยให้เราสามารถเลือก Payment Gateway ที่เราต้องการใช้ (Stripe หรือ PayPal) ได้อย่างง่ายดาย โดยไม่ต้องแก้ไขโค้ดที่เรียกใช้งาน Payment Gateway

สร้าง PaymentGatewayFactory

เราจะสร้างคลาส PaymentGatewayFactory ที่มี method create() ซึ่งจะรับ parameter เป็น type ของ Payment Gateway ที่เราต้องการสร้าง (เช่น 'stripe' หรือ 'paypal') และจะ return Instance ของคลาส Payment Gateway ที่เหมาะสม

สร้างไฟล์ PaymentGatewayFactory.php ใน directory src ของ project ของเรา:

<?php

namespace App;

use App\PaymentGatewayInterface;
use App\StripePayment;
use App\PayPalPayment;

class PaymentGatewayFactory
{
    public function create(string $gatewayType): PaymentGatewayInterface
    {
        switch ($gatewayType) {
            case 'stripe':
                return new StripePayment();
            case 'paypal':
                // ดึงค่าจาก config หรือ environment variable
                $clientId = $_ENV['PAYPAL_CLIENT_ID'] ?? 'YOUR_PAYPAL_CLIENT_ID';
                $clientSecret = $_ENV['PAYPAL_CLIENT_SECRET'] ?? 'YOUR_PAYPAL_CLIENT_SECRET';

                return new PayPalPayment($clientId, $clientSecret);
            default:
                throw new \InvalidArgumentException("Invalid payment gateway type: {$gatewayType}");
        }
    }
}

คำอธิบายโค้ด:

  • namespace App;: กำหนด namespace ของคลาส
  • use App\PaymentGatewayInterface;, use App\StripePayment;, use App\PayPalPayment;: Import interface และคลาสที่เราต้องการใช้
  • class PaymentGatewayFactory: สร้างคลาส PaymentGatewayFactory
  • public function create(string $gatewayType): PaymentGatewayInterface: สร้าง method create() ซึ่งรับ parameter $gatewayType เป็น string และ return Object ที่ implements PaymentGatewayInterface
  • switch ($gatewayType): ใช้ switch statement เพื่อตรวจสอบค่าของ $gatewayType
  • case 'stripe':: ถ้า $gatewayType เป็น 'stripe' ให้สร้าง Instance ของ StripePayment และ return
  • case 'paypal':: ถ้า $gatewayType เป็น 'paypal' ให้สร้าง Instance ของ PayPalPayment และ return
  • default:: ถ้า $gatewayType ไม่ตรงกับ case ใดๆ ให้ throw InvalidArgumentException

กำหนด method create()

Method create() ใน PaymentGatewayFactory มีหน้าที่ในการสร้าง Instance ของคลาส Payment Gateway ที่เหมาะสมตาม type ที่กำหนด

เหตุผลในการออกแบบ:

  • Single Responsibility Principle: PaymentGatewayFactory มีหน้าที่เดียวคือสร้าง Instance ของ Payment Gateway ทำให้โค้ดมีความชัดเจนและง่ายต่อการบำรุงรักษา
  • Open/Closed Principle: เราสามารถเพิ่ม Payment Gateway ใหม่ได้ โดยไม่ต้องแก้ไขโค้ดของ PaymentGatewayFactory เพียงแค่เพิ่ม case ใหม่ใน switch statement
  • Dependency Inversion Principle: เราพึ่งพา abstraction (PaymentGatewayInterface) แทนที่จะพึ่งพา concrete implementation (StripePayment, PayPalPayment) ทำให้โค้ดมีความยืดหยุ่นและง่ายต่อการทดสอบ

แนวปฏิบัติที่ดี:

  • Error Handling: ควรมีการจัดการ error ที่เหมาะสม เช่น throw exception เมื่อ $gatewayType ไม่ถูกต้อง
  • Configuration: ควรดึงค่า configuration (เช่น API Key, Client ID, Client Secret) จาก environment variable หรือ configuration file แทนที่จะ hardcode ในโค้ด
  • Logging: ควรมีการ logging เพื่อตรวจสอบการทำงานของ Factory Class

ตัวอย่างการใช้งาน:

<?php

require_once __DIR__ . '/vendor/autoload.php';

use App\PaymentGatewayFactory;

// Load environment variables from .env file
$dotenv = \Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load();

$factory = new PaymentGatewayFactory();

try {
    // สร้าง Instance ของ StripePayment
    $stripePayment = $factory->create('stripe');

    // สร้าง Instance ของ PayPalPayment
    $paypalPayment = $factory->create('paypal');

    // ... ใช้งาน Payment Gateway ...
    echo "Stripe Payment created successfully.\n";
    echo "Paypal Payment created successfully.\n";

} catch (\InvalidArgumentException $e) {
    echo "Error: " . $e->getMessage() . "\n";
}

ในตัวอย่างนี้ เราสร้าง Instance ของ PaymentGatewayFactory จากนั้นใช้ method create() เพื่อสร้าง Instance ของ StripePayment และ PayPalPayment ตามลำดับ หาก $gatewayType ไม่ถูกต้อง จะเกิด InvalidArgumentException

ในบทถัดไป เราจะมาทดสอบการชำระเงินผ่าน Stripe โดยใช้ PaymentGatewayFactory ที่เราได้สร้างขึ้นในบทนี้

Office.in.th Custom Service

이 구조를 바탕으로 시스템을 개발하거나 맞춤 변경하고 싶으신가요?

Office.in.th는 엔터프라이즈 웹 애플리케이션, API 연동, 공공/민간 업무 관리 시스템을 설계·개발하며 장기 지원을 제공합니다.

소프트웨어 개발 서비스 보기