2010-08-13 65 views
18

Khi nào chúng ta cần sử dụng mẫu Adapter? Nếu có thể cho tôi một ví dụ thế giới thực phù hợp với mô hình mà ...khi nào chúng ta cần mẫu Adapter?

+0

Bạn có dự định xem toàn bộ cuốn sách GoF và hỏi khi nào bạn cần mẫu X không? –

+0

Miễn là nó cho anh ta tất cả những người upvotes, nếu tôi là anh ta tôi sẽ hỏi về mỗi và mọi mẫu thiết kế :-P –

+0

@Thomas Owens: Tất cả tôi tìm kiếm là một ví dụ thế giới thực tốt sẽ giúp tôi tìm hiểu về mô hình đó . – brainless

Trả lời

33

Tôi đã làm việc trên một hệ thống cần thiết để giao tiếp với DVR bên ngoài. Đối với hầu hết các phần, tất cả các DVR có chức năng cơ bản giống nhau: bắt đầu ghi từ một nguồn video nhất định; ngừng ghi; bắt đầu phát lại từ một thời điểm nhất định; dừng phát lại, vv

Mỗi nhà sản xuất DVR cung cấp thư viện phần mềm, cho phép chúng tôi viết mã để điều khiển thiết bị của họ (vì mục đích của cuộc thảo luận này, tôi sẽ gọi nó là SDK). Mặc dù mọi SDK cung cấp API cho tất cả các chức năng cơ bản, nhưng không có chức năng nào trong số chúng hoàn toàn giống nhau. Đây là một ví dụ rất thô, nhưng bạn có ý tưởng:

  • BeginPlayback (DateTime startTime);
  • StartPlayback (long startTimeTicks);
  • Phát lại (chuỗi startDate, chuỗi startTime);

Phần mềm của chúng tôi cần để có thể tương tác với tất cả DVR. Vì vậy, thay vì viết chuyển đổi khủng khiếp/trường hợp cho từng SDK khác nhau, chúng tôi đã tạo giao diện IDVRController chung của riêng mình và viết tất cả mã hệ thống của chúng tôi tới giao diện đó:

  • Phát lại (DateTime startTime);

Sau đó, chúng tôi đã viết một triển khai bộ điều hợp khác cho mỗi SDK, tất cả đều triển khai giao diện IDVRController của chúng tôi. Chúng tôi đã sử dụng tệp cấu hình để chỉ định loại DVR mà hệ thống sẽ kết nối và mẫu Nhà máy để khởi tạo đúng trình cài đặt IDVRController cho DVR đó.

Theo cách đó, mẫu bộ điều hợp đã làm cho mã hệ thống của chúng tôi đơn giản hơn: chúng tôi luôn mã hóa IDVRController.Và nó cho phép chúng tôi triển khai các bộ điều hợp cho việc triển khai sau khi triển khai SDK mới (Nhà máy của chúng tôi đã sử dụng sự phản chiếu để khởi tạo phiên bản IDVRController chính xác).

+1

Ví dụ thực tế đời sống tuyệt vời. Nó đã giúp tôi hiểu được mục đích thực sự của mô hình này. Tôi đã thấy rằng mô hình này chủ yếu được sử dụng cùng với Dịch vụ Locater hoặc Nhà máy mẫu. – NoobDeveloper

5

Trong lập trình máy tính, Adapter Pattern (thường được gọi là mô hình wrapper hoặc đơn giản là một wrapper) là một mẫu thiết kế mà dịch một giao diện cho một lớp học thành giao diện tương thích . Bộ điều hợp cho phép các lớp hoạt động cùng nhau mà thường không thể do giao diện không tương thích, bằng cách cung cấp giao diện cho khách hàng khi sử dụng giao diện gốc . Bộ điều hợp dịch các cuộc gọi đến giao diện của nó thành cuộc gọi đến giao diện ban đầu và số lượng mã cần thiết để thực hiện điều này thường nhỏ. Bộ điều hợp cũng chịu trách nhiệm chuyển đổi dữ liệu thành các biểu mẫu thích hợp. Đối với Ví dụ, nếu nhiều giá trị boolean được lưu trữ như một số nguyên duy nhất nhưng tiêu dùng của bạn đòi hỏi một 'true'/'false', adapter sẽ chịu trách nhiệm về chiết xuất giá trị thích hợp từ số nguyên giá trị .

alt text

Wikipedia !!!

2

mẫu Adaptor là cần thiết trong tình huống sau:

Giả sử bạn đã xác định một giao diện I1 với phương pháp M1M2

C1C2 thực hiện giao diện này I1, bây giờ cho C1 trong khi thực hiện M1M2 bạn có tìm thấy không có sự giúp đỡ từ các lớp học hiện có khác, do đó bạn cần phải viết tất cả các logic của chính mình.

Bây giờ trong khi thực hiện lớp C2 bạn đã đi qua lớp C3 với các phương pháp M3M4 có thể được sử dụng để thực hiện M1M2 cho C2 như vậy để tận dụng những M3M4 trong lớp C2 bạn mở rộng lớp C3 và sử dụng M3M4 của C3.

Trong ví dụ này C2 trở thành Adapter classC3 trở thành adaptee

package com.design.patterns; 

public class AdapterExample { 
    public static void main(String[] args) { 
     Shape line = new LineShape(); 
     line.draw(); 

     Shape text = new TextShape(); 
     text.draw(); 
    } 
} 

//==Start from here 
interface Shape{ 
    public void draw(); 
} 

class LineShape implements Shape{ 
    @Override 
    public void draw() { 
     System.out.println("write some logic and draw line"); 
    } 
} 

//Adapter 
class TextShape extends TextView implements Shape{ 
    @Override 
    public void draw() { 
     System.out.println("logic is already there in class TextView"); 
     drawText(); 
    } 
} 

// Adaptee 
class TextView{ 
    public void drawText() { 
     System.out.println("Drawing Text Shape"); 
    } 
} 
1

hiện Interface

interface Shape { 
    public int calculateArea(int r); 
} 

thực hiện hiện tại cho giao diện Shape

class Square implements Shape { 
    @Override 
    public int calculateArea(int r) { 
     return r * r; 
    } 
} 

Bây giờ xem xét rằng bạn muốn lớp Vòng tròn thích ứng với giao diện hiện tại của chúng tôi mà không có cách nào chúng tôi có thể sửa đổi (Được viết bởi bên thứ ba).

class Circle { 
    public double calculateCircularArea (int r) { 
     return 3.14 * r * r; 
    } 
} 

Bây giờ chúng tôi đã điều chỉnh triển khai Vòng kết nối sang giao diện Hình dạng của chúng tôi. Vì vậy, chúng tôi cần một bộ điều hợp vì chúng không tương thích.

class CirCleAdaptor extends Circle implements Shape { 
    @Override 
    public int calculateArea(int r) { 
     return (int) calculateCircularArea(r); 
    } 
} 

CircleAdaptor - Là Adapter cho Vòng
Circle - Là Adaptee
Shape - Là giao diện Target

public class AdapterPattern { 
    public static void main(String[] args) { 
     Shape circle = new CirCleAdaptor(); 
     System.out.println("Circle Area " + circle.calculateArea(5)); 
     Shape square = new Square(); 
     System.out.println("Square Area " + square.calculateArea(5)); 
    } 
} 

Hy vọng điều này đưa ra một ý tưởng tốt hơn về Khi sử dụng nó.

1

Bạn có thể sử dụng mẫu thiết kế bộ điều hợp khi bạn phải xử lý các giao diện khác nhau với hành vi tương tự (thường có nghĩa là các lớp có hành vi tương tự nhưng với các phương pháp khác nhau). Một ví dụ về nó sẽ là một lớp học để kết nối với TV Samsung và một lớp khác để kết nối với TV Sony. Họ sẽ chia sẻ hành vi chung như menu mở, bắt đầu phát lại, kết nối với mạng và vv nhưng mỗi thư viện sẽ có một triển khai khác nhau của nó (với các tên và chữ ký khác nhau). Các triển khai cụ thể của nhà cung cấp khác nhau này được gọi là Adaptee trong biểu đồ UML.

Vì vậy, trong mã của bạn (gọi tắt là Khách hàng trong sơ đồ UML), thay vì cứng mã các cuộc gọi phương pháp của từng nhà cung cấp (hoặc Adaptee), sau đó bạn có thể tạo ra một giao diện chung (gọi tắt là Target trong Các sơ đồ UML) để bọc các hành vi tương tự này và chỉ làm việc với một loại đối tượng.

Các Adapters sau đó sẽ thực hiện giao diện Target ủy phương pháp của nó gọi đến Adaptees được truyền cho Adapters qua constructor.

Để bạn nhận ra điều này trong mã Java, tôi đã viết một dự án rất đơn giản, sử dụng chính xác ví dụ được đề cập ở trên bằng cách sử dụng bộ điều hợp để xử lý nhiều giao diện TV thông minh. Mã nhỏ, được ghi chép và tự giải thích để tìm hiểu về cách thực hiện thế giới thực như thế nào.

Chỉ cần tải xuống mã và nhập mã đó vào Eclipse (hoặc IDE yêu thích của bạn) làm dự án Maven. Bạn có thể thực thi mã bằng cách chạy org.example.Main.java. Hãy nhớ rằng điều quan trọng ở đây là để hiểu cách các lớp và các giao diện được ghép lại với nhau để thiết kế mẫu. Tôi cũng đã tạo một số đối tượng giả Adaptees trong gói com.thirdparty.libs. Hy vọng nó giúp!

https://github.com/Dannemann/java-design-patterns

0

Một ví dụ rất phổ biến của Adapter Pattern được thực hiện thông qua Service Provider Interface và thường được sử dụng trong rất nhiều khuôn khổ Java EE.

Lý do cho việc này là cho phép các triển khai khác nhau của Java EE nhưng các lập trình viên chỉ đơn giản là mã hóa cho đặc tả Java EE chứ không phải là một cái gì đó thực hiện cụ thể.

Trái ngược với một cái gì đó như mã hóa trực tiếp bằng cách sử dụng các lớp WebSphere mà khóa bạn vào sử dụng WebSphere.

Hoặc tồi tệ hơn (từ kinh nghiệm của tôi), Apache HTTP Client và tìm hiểu sau đó bởi vì bạn mã hóa để thực hiện thay vì HttpUrlConnection bình thường bạn phải thực hiện rất nhiều việc mã hóa vì nó không hỗ trợ phiên bản TLS hiện tại có thể tránh được nếu nhà phát triển ban đầu được mã hóa thành một API ổn định hơn và chúng tôi chỉ cần nâng cấp thời gian chạy Java.

Các vấn đề liên quan