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 C# của Coddy. Bài học 57 trên 70.

Mẫu thiết kế Adapter là một mẫu thiết kế cấu trúc, cho phép các giao diện không tương thích hoạt động cùng nhau. Nó đóng vai trò như cầu nối giữa hai lớp, chuyển đổi giao diện của một lớp thành giao diện mà các ứng dụng khách mong đợi. Hãy hình dung nó như một bộ chuyển đổi điện giúp bạn cắm thiết bị châu Âu vào ổ cắm của Mỹ.

Mẫu này đặc biệt hữu ích khi bạn muốn dùng một lớp có sẵn nhưng giao diện của nó không phù hợp với nhu cầu của code. Thay vì sửa lớp ban đầu (có thể bạn không kiểm soát được lớp đó), bạn tạo một bộ chuyển đổi bao bọc lớp đó:

// Lớp (class) hiện có với giao diện không tương thích
public class OldPrinter
{
    public void PrintMessage(string msg) => Console.WriteLine($"Old: {msg}");
}

// Giao diện mà code của bạn cần
public interface IPrinter
{
    void Print(string text);
}

// Bộ chuyển đổi kết nối hai giao diện
public class PrinterAdapter : IPrinter
{
    private OldPrinter _oldPrinter;
    
    public PrinterAdapter(OldPrinter oldPrinter)
    {
        _oldPrinter = oldPrinter;
    }
    
    public void Print(string text)
    {
        _oldPrinter.PrintMessage(text);  // Chuyển lời gọi đến giao diện cũ
    }
}

Giờ đây, code của bạn có thể hoạt động với máy in cũ thông qua giao diện mong đợi:

OldPrinter legacy = new OldPrinter();
IPrinter printer = new PrinterAdapter(legacy);

printer.Print("Hello");  // Old: Hello

Mẫu Adapter rất hữu ích khi tích hợp thư viện bên thứ ba hoặc code cũ vào ứng dụng của bạn. Code phía client làm việc với giao diện IPrinter mà không hề biết một lớp cũ, không tương thích đang thực hiện công việc thực sự phía sau.

challenge icon

Thử thách

Dễ

Hãy xây dựng một hệ thống phát đa phương tiện bằng mẫu Adapter. Bạn có một thư viện âm thanh hiện có để phát tệp MP3, nhưng ứng dụng của bạn cần một giao diện thống nhất có thể xử lý nhiều loại phương tiện khác nhau. Bạn sẽ tạo một adapter để kết nối hai phần này, giúp trình phát đa phương tiện hiện đại hoạt động liền mạch với thư viện âm thanh cũ.

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

  • LegacyAudio.cs: Tệp này đại diện cho một thư viện hiện có mà bạn không thể chỉnh sửa. Tạo lớp LegacyAudioPlayer trong không gian tên MediaSystem, với phương thức PlayMp3(string filename) trả về chuỗi "Playing MP3: {filename}". Đây là “đối tượng được điều chỉnh”, tức lớp có giao diện không tương thích.
  • MediaAdapter.cs: Tạo giao diện và adapter trong cùng không gian tên. Định nghĩa giao diện IMediaPlayer với phương thức Play(string filename) trả về một chuỗi. Sau đó, tạo lớp MediaPlayerAdapter triển khai IMediaPlayer. Adapter của bạn nên bao bọc một đối tượng LegacyAudioPlayer (được truyền qua hàm khởi tạo) và chuyển lời gọi Play thành lời gọi phương thức PlayMp3 của trình phát cũ.
  • Program.cs: Kết hợp mọi thứ bằng cách tạo trình phát cũ, bao bọc nó trong adapter rồi sử dụng adapter thông qua giao diện IMediaPlayer. Cách này cho thấy code phía máy khách có thể làm việc với giao diện hiện đại, trong khi adapter xử lý việc giao tiếp với hệ thống cũ ở phía sau.

Bạn sẽ nhận một đầu vào:

  • Tên tệp cần phát (ví dụ: song.mp3)

Tạo một đối tượng LegacyAudioPlayer, bao bọc nó trong MediaPlayerAdapter, sau đó gọi Play trên adapter thông qua giao diện IMediaPlayer và in kết quả ra.

Ví dụ, nếu đầu vào là favorite_track.mp3, đầu ra sẽ là:

Playing MP3: favorite_track.mp3

Điểm hay của mẫu này là code chính của bạn chỉ tương tác với IMediaPlayer, hoàn toàn không biết thư viện âm thanh cũ đang thực hiện công việc thực tế. Nếu sau này bạn cần hỗ trợ một thư viện cũ khác, bạn chỉ cần tạo adapter mới mà không phải thay đổi bất kỳ code phía máy khách nào!

Tự làm thử

using System;
using MediaSystem;

class Program
{
    public static void Main(string[] args)
    {
        // Đọc tên tệp từ đầu vào
        string filename = Console.ReadLine();
        
        // TODO: Tạo một instance của LegacyAudioPlayer
        
        // TODO: Bọc instance đó trong MediaPlayerAdapter
        
        // TODO: Sử dụng adapter thông qua giao diện IMediaPlayer
        // và in ra kết quả khi gọi Play với tên tệp
    }
}
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 C# online