Structural Patterns - Adapter
Khái niệm
Adapter Design Pattern là một mẫu thiết kế cấu trúc (Structural Pattern) cho phép các giao diện (interface) không tương thích có thể làm việc cùng nhau.
Các thành phần chính
- Target: Interface mà phía máy khách (client) muốn sử dụng.
- Client: Lớp tương tác với đối tượng phù hợp với Target.
- Adaptee: Lớp có sẵn nhưng interface không tương thích với client.
- Adapter: Lớp trung gian thực hiện chuyển đổi, kế thừa hoặc chứa Adaptee để chuyển đổi interface của nó thành Target.
Ưu điểm
- Tương thích: Cho phép các interface khác nhau có thể dễ dàng giao tiếp.
- Giữ nguyên code gốc: Không cần thay đổi mã nguồn của lớp cũ (Adaptee).
- Nguyên tắc Trách nhiệm Đơn nhất (Single Responsibility Principle): Giúp tách mã giao diện (interface), hoặc mã chuyển đổi dữ liệu khỏi logic nghiệp vụ chính của ứng dụng.
- Nguyên tắc Đóng/Mở (Open/Closed Principle): Bạn có thể tạo các loại bộ chuyển chuyển đổi mới mà không làm hỏng code hiện có phía máy khách, miễn là chúng làm việc với các bộ chuyển đổi thông qua giao diện phía máy khách.
Nhược điểm
- Việc đưa vào chương trình một tập hợp các giao diện và lớp mới làm cho độ phức tạp của chương trình tăng lên. Trong khi đó chỉ cần thay đổi logic ở lớp dịch vụ để phù hợp với thông tin cần lấy ra là đủ. Không nhất thiết phải thêm các tập hợp đó.
Ví dụ thực tế
- Bài toán
Giả sử ta có một đối tượng nhân viên mà bao gồm đầy đủ thông tin của một nhân viên như là: Mã, Họ tên, Địa chỉ, v.v…. Đối tượng này được lấy từ một nguồn dùng chung nào đó như thông qua việc gọi API chẳng hạn.
Vấn đề đặt ra đó là, khi ta cần triển khai một tính năng mà cần sử dụng sẵn đối tượng nhân viên đó. Nhưng ta chỉ cần sử dụng trường Mã và Họ tên của nhân viên, các trường khác là không cần thiết.
- Phân tích bài toán
Ta có một đối tượng đầu vào với đầy đủ thông tin của một nhân viên. Nhưng tính năng ta đang triển khai chỉ sử dụng Mã và Họ tên của nhân viên thôi.
Vì vậy ta cần có một cơ chế chuyển đổi sao cho phù hợp với nhu cầu của tính năng. Ngoài ra, những tính năng khác trong tương lai có thể sử dụng sẵn sự chuyển đổi đó.
- Cách triển khai
Đầu tiên, ta cần tạo lớp giao diện cho thành phần Target.
public interface INhanVienTarget
{
string LayMaVaTen();
}
Interface này sẽ khai báo một phương thức để lấy về Mã và Họ tên của nhân viên.
Tiếp theo, ta tạo một lớp là dữ liệu đầu vào của nhân viên, đặt tên lớp là NhanVienAdaptee. Đây chính là thành phần Adaptee.
class NhanVienAdaptee
{
public string Ma { get; set; } = default!;
public string HoTen { get; set; } = default!;
public string DiaChi { get; set; } = default!;
public string SoDienThoai { get; set; } = default!;
}
Đến thành phần quan trọng Adapter, ta sẽ tạo lớp NhanVienAdapter như sau:
class NhanVienAdapter : INhanVienTarget
{
private readonly NhanVienAdaptee _adaptee;
public NhanVienAdapter(NhanVienAdaptee adaptee)
{
this._adaptee = adaptee;
}
public string LayMaVaTen()
{
return $" Ma NV: '{this._adaptee.Ma}', Ten NV: '{this._adaptee.HoTen}'";
}
}
Lớp này là lớp trung gian giúp chuyển đổi Adaptee sang Target, nó sẽ kế thừa lớp interface ở trên và triển khai phương thức của interface để trả về thông tin cần thiết.
Cuối cùng là đoạn code mô phỏng phía máy khách.
class ClientAdapter
{
public void Main()
{
NhanVienAdaptee adaptee = new NhanVienAdaptee
{
Ma = "NV1",
HoTen = "Dao Van A",
DiaChi = "Ha Noi",
SoDienThoai = "0988888888"
};
INhanVienTarget target = new NhanVienAdapter(adaptee);
Console.WriteLine("Doi tuong Nhan Vien dau vao la khong tuong thich voi mong muon tu phia may khach.");
Console.WriteLine("....Ma: '{0:s}', Ho Ten: '{1:s}', Dia Chi: '{2:s}', So DT: '{3:s}'", adaptee.Ma, adaptee.HoTen, adaptee.DiaChi, adaptee.SoDienThoai);
Console.WriteLine("Nhung voi bo chuyen doi NhanVienAdapter, phia may khach co the lay nhung thong tin can thiet nhu la:");
Console.WriteLine(target.LayMaVaTen());
}
}
Kết quả sau khi chạy chương trình:
Kết luận
Như vậy, qua bài viết này, tôi hi vọng các bạn sẽ nắm được khái niệm cũng như biết được việc khi nào thì nên áp dụng mẫu thiết kế Adapter vào trong ứng dụng của mình.
Ví dụ tôi đưa đôi khi không chính xác và thuyết phục hoàn toàn, rất mong sự góp ý từ phía các bạn để tôi có thể củng cố thêm kiến thức cho bản thân mình.
