Menu
CoddyTech

Mẫu bộ chuyển đổi

Thuộc phần Lập trình hướng đối tượng trong hành trình PHP của Coddy. Bài học 76 trên 91.

Adapter Pattern là một mẫu thiết kế cấu trúc cho phép các đối tượng có giao diện không tương thích hoạt động cùng nhau. Mẫu này đóng vai trò cầu nối giữa hai giao diện, chuyển đổi lời gọi từ định dạng này sang định dạng khác.

Hãy tưởng tượng bạn đang xây dựng một ứng dụng xử lý thanh toán và cần tích hợp một thư viện thanh toán của bên thứ ba. Thư viện hoạt động hoàn hảo, nhưng giao diện của nó không khớp với những gì code của bạn cần. Thay vì viết lại toàn bộ ứng dụng, bạn tạo một bộ chuyển đổi để chuyển đổi giữa hai giao diện.

<?php
// Giao diện mà ứng dụng của bạn yêu cầu
interface PaymentProcessor {
    public function pay(float $amount): string;
}

// Thư viện bên thứ ba có giao diện khác
class StripeAPI {
    public function createCharge(int $cents, string $currency): string {
        return "Charged {$cents} {$currency} via Stripe";
    }
}

Bộ điều hợp triển khai giao diện mà bạn mong đợi, đồng thời sử dụng lớp bên thứ ba ở bên trong:

<?php
class StripeAdapter implements PaymentProcessor {
    public function __construct(private StripeAPI $stripe) {}
    
    public function pay(float $amount): string {
        $cents = (int)($amount * 100);
        return $this->stripe->createCharge($cents, 'USD');
    }
}

$stripe = new StripeAPI();
$processor = new StripeAdapter($stripe);
echo $processor->pay(29.99);

Đầu ra:

Charged 2999 USD via Stripe

Bộ chuyển đổi đổi đô la sang xu và gọi phương thức phù hợp. Code ứng dụng của bạn chỉ biết đến PaymentProcessor, hoàn toàn không cần quan tâm đến các yêu cầu riêng của Stripe. Nếu sau này bạn chuyển sang nhà cung cấp dịch vụ thanh toán khác, bạn chỉ cần tạo một bộ chuyển đổi mới mà không phải thay đổi code hiện có.

challenge icon

Thử thách

Dễ

Hãy xây dựng một hệ thống chuyển đổi nhiệt độ bằng Mẫu bộ chuyển đổi (Adapter Pattern). Bạn có một cảm biến nhiệt độ cũ, cho kết quả đo theo độ Fahrenheit, nhưng ứng dụng thời tiết hiện đại của bạn cần nhiệt độ theo độ Celsius. Thay vì sửa đổi một trong hai hệ thống, bạn sẽ tạo một bộ chuyển đổi để kết nối chúng.

Bạn sẽ sắp xếp code trong bốn tệp:

  • TemperatureSensor.php: Định nghĩa một giao diện (interface) TemperatureSensor mà ứng dụng thời tiết cần dùng. Giao diện này cần có phương thức getTemperature(): float để trả về nhiệt độ theo độ Celsius.
  • LegacySensor.php: Tạo lớp (class) LegacySensor mô phỏng phần cứng cũ. Lớp này có giao diện khác với giao diện ứng dụng cần:
    • Lớp nhận số đo theo độ Fahrenheit trong hàm khởi tạo (constructor). Hãy dùng cú pháp khai báo thuộc tính trong hàm khởi tạo.
    • Lớp có phương thức readFahrenheit(): float để trả về giá trị Fahrenheit đã lưu.
  • LegacySensorAdapter.php: Thêm cả giao diện TemperatureSensor và lớp LegacySensor vào tệp này. Tạo lớp LegacySensorAdapter triển khai TemperatureSensor và bao bọc một LegacySensor. Bộ chuyển đổi cần:
    • Nhận một LegacySensor trong hàm khởi tạo
    • Triển khai getTemperature() bằng cách đọc giá trị Fahrenheit từ cảm biến cũ rồi đổi sang Celsius theo công thức: (fahrenheit - 32) * 5 / 9
  • main.php: Thêm tệp LegacySensorAdapter. Bạn sẽ nhận một đầu vào: nhiệt độ theo độ Fahrenheit.

    Tạo một LegacySensor với nhiệt độ đầu vào, rồi bao bọc nó trong một LegacySensorAdapter. Gọi getTemperature() trên bộ chuyển đổi và in ra kết quả đã làm tròn đến hai chữ số thập phân.

    Định dạng đầu ra cần là: Temperature: [celsius]C

Thử thách này minh họa cách Mẫu bộ chuyển đổi giúp bạn tích hợp các giao diện không tương thích mà không cần sửa đổi code hiện có. Ứng dụng thời tiết chỉ làm việc với giao diện TemperatureSensor và hoàn toàn không biết rằng các số đo thực tế đến từ cảm biến Fahrenheit cũ.

Tự làm thử

<?php
require_once 'LegacySensorAdapter.php';

// Đọc đầu vào
$fahrenheit = floatval(trim(fgets(STDIN)));

// TODO: Tạo một LegacySensor với nhiệt độ đầu vào
// TODO: Bọc đối tượng đó bằng LegacySensorAdapter
// TODO: Gọi getTemperature() trên adapter
// TODO: In ra kết quả làm tròn đến hai chữ số thập phân
// Định dạng đầu ra: Temperature: [celsius]C

?>
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Trình biên dịch PHP online