Mẫu bộ chuyển đổi
Thuộc phần Lập trình hướng đối tượng trong hành trình Dart của Coddy. Bài học 95 trên 110.
Mẫu thiết kế Adapter pattern cho phép các giao diện không tương thích hoạt động cùng nhau. Nó đóng vai trò cầu nối giữa hai lớp vốn không thể cộng tác, bằng cách bao bọc một lớp hiện có bằng giao diện mới mà các bên sử dụng mong đợi. Mẫu này đặc biệt hữu ích khi tích hợp thư viện của bên thứ ba hoặc code cũ vào ứng dụng của bạn.
Hãy tưởng tượng bạn có một hệ thống làm việc với dữ liệu JSON, nhưng bạn cần tích hợp một thành phần chỉ xuất XML. Thay vì chỉnh sửa một trong hai lớp, bạn tạo một bộ chuyển đổi để chuyển đổi giữa chúng:
// Giao diện hiện có mà hệ thống của bạn yêu cầu
abstract class JsonData {
String getJson();
}
// Lớp cũ có giao diện không tương thích
class XmlService {
String getXml() {
return '<data><name>John</name></data>';
}
}
// Adapter giúp XmlService tương thích với JsonData
class XmlToJsonAdapter implements JsonData {
final XmlService _xmlService;
XmlToJsonAdapter(this._xmlService);
@override
String getJson() {
String xml = _xmlService.getXml();
// Chuyển XML sang JSON (đã đơn giản hóa)
return '{"name": "John"}';
}
}
void main() {
var xmlService = XmlService();
var adapter = XmlToJsonAdapter(xmlService);
print(adapter.getJson()); // {"name": "John"}
}XmlToJsonAdapter bọc XmlService và triển khai giao diện JsonData. Code phía client làm việc với giao diện quen thuộc JsonData mà không cần biết dữ liệu ban đầu đến từ nguồn XML. Adapter tự xử lý mọi việc chuyển đổi bên trong.
Hãy dùng mẫu Adapter 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 bạn, hoặc khi bạn cần tạo một lớp có thể tái sử dụng để phối hợp với các lớp có giao diện không tương thích.
Thử thách
DễHãy xây dựng một hệ thống bộ chuyển đổi cho trình phát đa phương tiện! Hãy tưởng tượng bạn có một hệ thống âm thanh hiện đại, yêu cầu mọi nguồn phương tiện phát âm thanh thông qua một giao diện tiêu chuẩn, nhưng bạn cần tích hợp một máy phát đĩa vinyl kiểu cũ, có cách tạo ra âm thanh hoàn toàn khác.
Bạn sẽ tạo hai tệp để sắp xếp phần triển khai mẫu bộ chuyển đổi:
media_adapter.dart: Tệp này chứa giao diện và các lớp bộ chuyển đổi. Định nghĩa một lớp trừu tượngAudioSourcemà hệ thống hiện đại của bạn yêu cầu. Lớp này cần có phương thứcString playAudio()trả về đầu ra âm thanh dưới dạng chuỗi. Sau đó, tạo lớpVinylPlayerđại diện cho thiết bị cũ, có trườngtrackNamevà phương thứcString spinRecord()trả về*crackle* Playing vinyl: [trackName] *crackle*. Cuối cùng, xây dựngVinylAdaptertriển khaiAudioSourcevà bao bọc mộtVinylPlayer. Phương thứcplayAudio()của bộ chuyển đổi cần gọi phương thứcspinRecord()của máy phát đĩa vinyl rồi trả về kết quả, qua đó kết nối hai giao diện không tương thích.main.dart: Nhập tệp bộ chuyển đổi phương tiện của bạn và minh họa cách bộ chuyển đổi giúp máy phát đĩa vinyl cũ hoạt động với code yêu cầu giao diện hiện đạiAudioSource. Tạo mộtVinylPlayervới tên bản nhạcBohemian Rhapsody. Sau đó, tạo mộtVinylAdapterbao bọc máy phát đĩa vinyl này. Lưu bộ chuyển đổi vào một biến có kiểuAudioSourceđể chứng minh rằng nó tuân theo giao diện mong đợi. GọiplayAudio()trên nguồn âm thanh của bạn rồi in ra kết quả.
Điểm hay của mẫu này là code chính của bạn làm việc với giao diện tiêu chuẩn AudioSource, mà không cần biết rằng phía sau, một máy phát đĩa vinyl cũ đang thực hiện công việc thực sự!
Đầu ra mong đợi:
*crackle* Playing vinyl: Bohemian Rhapsody *crackle*Tự làm thử
import 'media_adapter.dart';
void main() {
// TODO: Tạo VinylPlayer với tên bản nhạc "Bohemian Rhapsody"
// TODO: Tạo VinylAdapter để bọc trình phát đĩa than
// TODO: Lưu adapter vào một biến (variable) có kiểu dữ liệu AudioSource
// TODO: Gọi playAudio() trên nguồn âm thanh của bạn và in ra kết quả
}
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
1Nền tảng về lập trình hướng đối tượng
Tệp bên ngoàiThư viện và câu lệnh importGiới thiệu về lập trình hướng đối tượngLớp và đối tượngTừ khóa thisPhương thứcBiến thể hiệnKiến thức cơ bản về hàm khởi tạoÔn tập: Máy tính đơn giản4An toàn với giá trị null
Giới thiệu về an toàn với giá trị nullCó thể null và không thể nullToán tử ? và !Từ khóa late và an toàn với giá trị nullToán tử xử lý nullAn toàn với giá trị null trong lớpÔn tập: hệ thống hồ sơ người dùng7Lớp trừu tượng và interface
Lớp trừu tượngPhương thức trừu tượngInterface trong DartInterface ngầm địnhTriển khai và kế thừaNhiều interfaceÔn tập: Máy tính hình10Bộ sưu tập và kiểu tổng quát
Tổng quan về List, Set và MapBộ sưu tập an toàn về kiểuLớp tổng quátPhương thức tổng quátRàng buộc kiểu tổng quátIterable và IteratorÔn tập: Lưu trữ tổng quát2Hàm khởi tạo trong Dart
Hàm khởi tạo mặc địnhHàm khởi tạo có tênDanh sách khởi tạoHàm khởi tạo hằng sốHàm khởi tạo nhà máyHàm khởi tạo chuyển hướngÔn tập: Trình tạo hình dạng5Đóng gói
Thành viên công khai và riêng tưQuy ước tiền tố _Tính riêng tư ở cấp thư việnTìm hiểu sâu về getter và setterChe giấu thông tinÔn tập: hồ sơ học sinh8Mixin
Giới thiệu về MixinTạo MixinSử dụng nhiều MixinTừ khóa on trong MixinMixin và kế thừaMixin và giao diệnÔn tập: hệ thống động vật3Thuộc tính của lớp
Thành viên instance và thành viên tĩnhTrường final và constBiến latePhương thức và trường tĩnhGetter và setterÔn tập: trình quản lý tài khoản ngân hàng6Kế thừa
Kế thừa cơ bảnTừ khóa superGhi đè phương thứcChú thích @overrideTừ khóa lớp finalHàm khởi tạo và kế thừaÔn tập: phân cấp nhân viên9Đa hình
Khái niệm cơ bản về đa hìnhĐa hình qua giao diệnKiểm tra kiểu lúc chạyToán tử is và asTừ khóa hiệp biếnÔn tập: Bộ xử lý thanh toán12OOP bất đồng bộ
Future và async/awaitCơ bản về StreamBộ điều khiển StreamHàm khởi tạo bất đồng bộBất đồng bộ trong phương thức lớpÔn tập: Trình lấy dữ liệu15Cá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ổng hợpMẫu RepositoryTự luyện tập: Trình biên dịch Dart online