Trước tiên, chúng ta hãy cùng cafedev giới thiệu mọi thứ về Adapter Pattern và phần code ví dụ chi tiết nhằm giúp ace dễ hiểu khi áp dụng trên các ngôn ngữ khác nhau. Ace có thể tham khảo thêm các bài khác tại series Design Pattern tại đây.
Mô hình này rất dễ hiểu vì thế giới thực có đầy đủ các bộ chuyển đổi(Adapter). Ví dụ: hãy xem xét bộ chuyển đổi USB sang Ethernet. Chúng tôi cần điều này khi chúng tôi có giao diện Ethernet ở một đầu và USB ở đầu kia. Vì chúng không tương thích với nhau. chúng ta sử dụng một bộ chuyển đổi để chuyển đổi cái này sang cái khác. Ví dụ này khá giống với bộ chuyển đổi(Adapter)hướng đối tượng. Trong thiết kế, bộ chuyển đổi được sử dụng khi chúng ta có một lớp (Khách hàng) mong đợi một số loại đối tượng và chúng ta có một đối tượng (Người thích ứng) cung cấp các tính năng tương tự nhưng có giao diện khác.
Để sử dụng bộ chuyển đổi:
- Máy khách đưa ra yêu cầu tới bộ chuyển đổi bằng cách gọi một phương thức trên đó bằng giao diện đích.
- bộ chuyển đổi dịch yêu cầu đó trên bộ chuyển đổi bằng cách sử dụng giao diện bộ chuyển đổi.
- Khách hàng nhận được kết quả của cuộc gọi và không biết về sự hiện diện của bộ chuyển đổi.
Nội dung chính
1. Định nghĩa:
Adapter pattern chuyển đổi giao diện của một lớp thành giao diện khác mà khách hàng mong đợi. bộ chuyển đổi cho phép các lớp hoạt động cùng nhau mà không thể vì giao diện không tương thích.
Sơ đồ lớp:
Máy khách chỉ nhìn thấy giao diện đích chứ không nhìn thấy bộ chuyển đổi. bộ chuyển đổi thực hiện giao diện đích. bộ chuyển đổi ủy quyền tất cả các yêu cầu cho bộ chuyển đổi.
Thí dụ:
Giả sử bạn có một lớp Bird với các phương thức fly() và makeSound(). Và cũng là một lớp ToyDuck với phương thức squeak(). Hãy giả sử rằng bạn thiếu các đối tượng ToyDuck và bạn muốn sử dụng các đối tượng Bird thay thế cho chúng. Chim có một số chức năng tương tự nhưng thực hiện một giao diện khác, vì vậy chúng ta không thể sử dụng chúng trực tiếp. Vì vậy, chúng ta sẽ sử dụng Adapter pattern. Ở đây khách hàng của chúng ta sẽ là ToyDuck và người thích nghi sẽ là Bird.
Dưới đây là cách triển khai Java của nó.
// Java implementation of Adapter pattern
interface Bird
{
// birds implement Bird interface that allows
// them to fly and make sounds adaptee interface
public void fly();
public void makeSound();
}
class Sparrow implements Bird
{
// a concrete implementation of bird
public void fly()
{
System.out.println("Flying");
}
public void makeSound()
{
System.out.println("Chirp Chirp");
}
}
interface ToyDuck
{
// target interface
// toyducks dont fly they just make
// squeaking sound
public void squeak();
}
class PlasticToyDuck implements ToyDuck
{
public void squeak()
{
System.out.println("Squeak");
}
}
class BirdAdapter implements ToyDuck
{
// You need to implement the interface your
// client expects to use.
Bird bird;
public BirdAdapter(Bird bird)
{
// we need reference to the object we
// are adapting
this.bird = bird;
}
public void squeak()
{
// translate the methods appropriately
bird.makeSound();
}
}
class Main
{
public static void main(String args[])
{
Sparrow sparrow = new Sparrow();
ToyDuck toyDuck = new PlasticToyDuck();
// Wrap a bird in a birdAdapter so that it
// behaves like toy duck
ToyDuck birdAdapter = new BirdAdapter(sparrow);
System.out.println("Sparrow...");
sparrow.fly();
sparrow.makeSound();
System.out.println("ToyDuck...");
toyDuck.squeak();
// toy duck behaving like a bird
System.out.println("BirdAdapter...");
birdAdapter.squeak();
}
}
Đầu ra:
Sparrow...
Flying
Chirp Chirp
ToyDuck...
Squeak
BirdAdapter...
Chirp Chirp
Giải thích:
Giả sử chúng ta có một con chim có thể tạo ra makeSound() và chúng ta có một con vịt đồ chơi bằng nhựa có thể squeak(). Bây giờ, giả sử khách hàng của chúng ta thay đổi yêu cầu và anh ta muốn toyDuck làm cho Âm thanh hơn?
Giải pháp đơn giản là chúng ta sẽ chỉ thay đổi lớp thực thi thành lớp bộ chuyển đổi mới và yêu cầu máy khách chuyển thể hiện của con chim (muốn squeak()) sang lớp đó.
Trước: ToyDuck toyDuck = new PlasticToyDuck();
Sau: ToyDuck toyDuck = new BirdAdapter (sparrow);
Bạn có thể thấy rằng chỉ cần thay đổi một dòng, toyDuck bây giờ có thể làm được Chirp Chirp !!
Object Adapter Vs Class Adapter
Adapter pattern chúng ta đã triển khai ở trên được gọi là Object Adapter Pattern vì bộ chuyển đổi(Adapter) chứa một thực thể của bộ chuyển đổi(Adapter). Ngoài ra còn có một kiểu khác được gọi là Class Adapter Pattern sử dụng kế thừa thay vì thành phần nhưng bạn yêu cầu đa kế thừa để triển khai nó.
Sơ đồ lớp của Class Adapter Pattern:
Ở đây thay vì có một đối tượng thích ứng bên trong bộ chuyển đổi (thành phần) để sử dụng bộ chuyển đổi chức năng của nó, bộ chuyển đổi kế thừa.
Vì đa kế thừa không được hỗ trợ bởi nhiều ngôn ngữ bao gồm java và có liên quan đến nhiều vấn đề nên chúng ta đã không hiển thị việc triển khai bằng cách sử dụng Class Adapter Pattern.
2. Ưu điểm:
- Giúp đạt được khả năng tái sử dụng và tính linh hoạt.
- Lớp client không phức tạp bằng cách phải sử dụng một giao diện khác và có thể sử dụng tính đa hình để hoán đổi giữa các triển khai khác nhau của bộ chuyển đổi.
3. Nhược điểm:
- Tất cả các yêu cầu đều được chuyển tiếp, vì vậy chi phí sẽ tăng nhẹ.
- Đôi khi cần có nhiều sự điều chỉnh dọc theo một chuỗi bộ chuyển đổi để đạt được loại theo yêu cầu.
Cài ứng dụng cafedev để dễ dàng cập nhật tin và học lập trình mọi lúc mọi nơi tại đây.
Tài liệu từ cafedev:
- Full series tự học Design Pattern từ cơ bản tới nâng cao tại đây nha.
- Các nguồn kiến thức MIỄN PHÍ VÔ GIÁ từ cafedev tại đây
Nếu bạn thấy hay và hữu ích, bạn có thể tham gia các kênh sau của cafedev để nhận được nhiều hơn nữa:
Chào thân ái và quyết thắng!