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: HelloMẫ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.
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ớpLegacyAudioPlayertrong không gian tênMediaSystem, với phương thứcPlayMp3(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ệnIMediaPlayervới phương thứcPlay(string filename)trả về một chuỗi. Sau đó, tạo lớpMediaPlayerAdaptertriển khaiIMediaPlayer. Adapter của bạn nên bao bọc một đối tượngLegacyAudioPlayer(được truyền qua hàm khởi tạo) và chuyển lời gọiPlaythành lời gọi phương thứcPlayMp3củ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ệnIMediaPlayer. 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
}
}
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
1Các khái niệm cơ bản về lập trình hướng đối tượng
Tệp bên ngoàiKhông gian tên và chỉ thịGiới thiệu về lớp và đối tượngTừ khóa thisPhương thức và tham sốTrường và thuộc tínhHàm khởi tạoKhởi tạo đối tượngÔn tập: Máy tính đơn giản4Kế thừa
Cú pháp kế thừa cơ bản (:)Từ khóa 'base'Từ khóa virtual và overrideLớp sealedLớp cơ sở 'object'Ôn tập: hệ phân cấp nhân viên7Tính năng nâng cao
Nạp chồng toán tửBộ lập chỉ mục (this[])Ghi đè ToString()Phương thức mở rộngÔn tập: Danh sách tùy chỉnh10Các mẫu thiết kế phần 1
Giới thiệu về mẫu thiết kếSingleton an toàn với luồngMẫu FactoryMẫu Observer (sự kiện)Mẫu Strategy2Thuộc tính và thành viên tĩnh
Thuộc tính tự độngThuộc tính chỉ đọc hoặc chỉ ghiTrường và phương thức tĩnhLớp tĩnhThành viên có thân biểu thức5Đa hình và interface
Đa hình lúc biên dịch và lúc chạyInterface và lớp trừu tượngNhiều interfaceInterface tường minhUpcasting và downcastingÔn tập: bộ tính toán hình học8Các khái niệm OOP nâng cao
Ưu tiên composition hơn kế thừaGenerics (lớp và phương thức)Delegate và sự kiệnAttribute và reflectionGiao diện IDisposable và câu lệnh usingKiến thức cơ bản về dependency injection11Các mẫu thiết kế phần 2
Mẫu lệnhMẫu bộ chuyển đổiMẫu trang tríMẫu phương thức khuôn mẫuMẫu trạng tháiMẫu tổ hợpTự luyện tập: Trình biên dịch C# online