Làm thế nào để các Proxy, Trang trí, Bộ điều hợp và Mô hình Cầu khác nhau?


403

Tôi đã xem xét Mẫu Proxy và đối với tôi, nó có vẻ rất khủng khiếp như các mẫu Trang trí, Bộ điều hợp và Cầu. Tôi có hiểu lầm gì không? Có gì khác biệt? Tại sao tôi nên sử dụng mẫu Proxy so với các mẫu khác? Làm thế nào bạn đã sử dụng chúng trong quá khứ trong các dự án thế giới thực?


4
Thường có những mẫu trông rất giống nhau, nhưng khác nhau về ý định của chúng (chiến lược và mẫu trạng thái xuất hiện trong tâm trí). Tôi nghĩ rằng điều này thường là do thực tế là các mẫu thiết kế dựa trên các nguyên tắc thiết kế vững chắc phổ biến.
Jason Xuống

5
Vâng, bốn mẫu này có cùng chi tiết thực hiện. Chiến lược câu thơ nhà nước ít nhất có thể được tóm tắt là câu thơ không trạng thái đầy đủ (đối với hầu hết các phần). Thông thường, Chiến lược chỉ là phương thức tiêm, trong đó mẫu trạng thái sử dụng một giao diện để thực hiện nhiều hơn sau đó trừu tượng hóa một cuộc gọi phương thức. Chiến lược, vào cuối ngày, là một hack để cho phép lập trình chức năng trong thế giới OO.
Charles Graham

Câu trả lời:


648

Proxy, Decorator, Adaptor và Bridge là tất cả các biến thể của việc "gói" một lớp. Nhưng công dụng của chúng là khác nhau.

  • Proxy có thể được sử dụng khi bạn muốn lười biếng khởi tạo một đối tượng hoặc che giấu sự thật rằng bạn đang gọi một dịch vụ từ xa hoặc kiểm soát quyền truy cập vào đối tượng.

  • Công cụ trang trí còn được gọi là "Proxy thông minh." Điều này được sử dụng khi bạn muốn thêm chức năng cho một đối tượng, nhưng không phải bằng cách mở rộng loại đối tượng đó. Điều này cho phép bạn làm như vậy trong thời gian chạy.

  • Bộ điều hợp được sử dụng khi bạn có giao diện trừu tượng và bạn muốn ánh xạ giao diện đó sang một đối tượng khác có vai trò chức năng tương tự, nhưng giao diện khác.

  • Bridge rất giống với Adaptor, nhưng chúng tôi gọi nó là Bridge khi bạn xác định cả giao diện trừu tượng và triển khai cơ bản. Tức là bạn không thích ứng với một số mã kế thừa hoặc mã của bên thứ ba, bạn là người thiết kế tất cả các mã nhưng bạn cần có thể trao đổi các triển khai khác nhau.

  • Facade là một giao diện cấp cao hơn (đọc: đơn giản hơn) cho một hệ thống con của một hoặc nhiều lớp. Giả sử bạn có một khái niệm phức tạp đòi hỏi nhiều đối tượng để đại diện. Thay đổi tập hợp các đối tượng đó là khó hiểu, bởi vì bạn không biết đối tượng nào có phương thức bạn cần gọi. Đó là thời gian để viết một Mặt tiền cung cấp các phương thức cấp cao cho tất cả các hoạt động phức tạp bạn có thể làm cho bộ sưu tập các đối tượng. Ví dụ: một mô hình tên miền cho một bộ phận học, với các phương pháp như countStudents(), reportAttendance(), assignSubstituteTeacher(), và vân vân.


7
Câu trả lời tốt. Có thể đáng để thêm một số ví dụ về nơi bạn nhìn thấy nó trong tự nhiên? ví dụ: các lớp Proxy trong Dịch vụ web. +1 từ tôi.
Rob Cooper

5
@Rob: cảm ơn, nhưng tôi muốn giữ câu trả lời này ngắn gọn và ngọt ngào. Tôi khuyến khích bạn viết một câu trả lời khác với các ví dụ trong tự nhiên!
Bill Karwin

8
@RobertDailey Decorator cũng tốt để tránh ra khỏi hệ thống phân cấp loại kiểm soát. Ví dụ: giả sử bạn có một cửa sổ trong GUI và bạn muốn có các thanh cuộn tùy chọn. Bạn có thể có các lớp Window, VScrollWindow, HScrollWindow và VHScrollWindow hoặc bạn có thể tạo các trang trí VScroll và HScroll trên Window.
Eva

1
@RobertDailey, Trang trí thành phần.
Bill Karwin

1
Và nếu bạn muốn sao chép giao diện của đối tượng được bọc 1: 1 nhưng sau đó thêm một vài phương thức bổ sung thì sao? Đây là một trang trí hoặc một bộ chuyển đổi?
donquixote

198

Như câu trả lời của Bill nói, trường hợp sử dụng của họ là khác nhau .

Cấu trúc của chúng cũng vậy.

  • Proxytrang tríCả đều có cùng giao diện với các kiểu được bao bọc của chúng, nhưng proxy tạo một thể hiện dưới mui xe, trong khi trình trang trí lấy một thể hiện trong hàm tạo.

  • Bộ chuyển đổi và mặt tiềnCả đều có giao diện khác với những gì chúng bọc. Nhưng bộ điều hợp bắt nguồn từ một giao diện hiện có, trong khi mặt tiền tạo ra một giao diện mới.

  • Cầubộ chuyển đổi cả hai điểm tại một loại hiện có. Nhưng cây cầu sẽ chỉ vào một loại trừu tượng và bộ chuyển đổi có thể trỏ đến một loại cụ thể. Cây cầu sẽ cho phép bạn ghép nối việc thực hiện trong thời gian chạy, trong khi bộ điều hợp thường không có.


30
Câu trả lời của bạn kết hợp với Bill kết thúc 5 chương Mẫu thiết kế rất độc đáo. Người ta có thể gọi chúng là giao diện cấp cao hơn (đọc: đơn giản hơn) cho cuốn sách.
Jonas E Rich

54

Tôi đưa vào chủ đề.

Tất cả bốn mẫu có rất nhiều điểm chung, cả bốn mẫu đôi khi được gọi một cách không chính thức hoặc các mẫu bao bọc. Tất cả sử dụng thành phần, gói chủ đề và ủy thác thực hiện cho chủ thể tại một số điểm, thực hiện ánh xạ một phương thức gọi đến một phương thức khác. Họ dành cho khách hàng sự cần thiết phải xây dựng một đối tượng khác và sao chép tất cả dữ liệu liên quan. Nếu được sử dụng một cách khôn ngoan, chúng sẽ tiết kiệm bộ nhớ và bộ xử lý.

Bằng cách thúc đẩy khớp nối lỏng lẻo, họ làm cho mã ổn định một lần ít bị phơi bày trước những thay đổi không thể tránh khỏi và dễ đọc hơn cho các nhà phát triển đồng nghiệp.

Bộ chuyển đổi

Bộ điều hợp điều chỉnh chủ đề (bộ điều hợp) sang một giao diện khác. Bằng cách này, chúng ta có thể thêm đối tượng được đặt vào một bộ sưu tập các loại khác nhau.

Bộ điều hợp chỉ hiển thị các phương thức có liên quan đến máy khách, có thể hạn chế tất cả các phương thức khác, tiết lộ ý định sử dụng cho các bối cảnh cụ thể, như điều chỉnh thư viện bên ngoài, làm cho nó xuất hiện ít chung hơn và tập trung hơn vào nhu cầu ứng dụng của chúng tôi. Bộ điều hợp tăng khả năng đọc và tự mô tả mã của chúng tôi.

Bộ điều hợp bảo vệ một đội khỏi mã dễ bay hơi từ các đội khác; một công cụ cứu sinh khi làm việc với các đội ngoài khơi ;-)

Mục đích ít được đề cập đến nó để ngăn lớp chủ đề vượt quá các chú thích. Với rất nhiều khung dựa trên các chú thích, điều này trở nên quan trọng hơn bao giờ hết.

Bộ điều hợp giúp vượt qua giới hạn Java chỉ có tính kế thừa duy nhất. Nó có thể kết hợp một số người thích nghi dưới một phong bì tạo ấn tượng về sự kế thừa nhiều.

Mã khôn ngoan, Adaptor là loại mỏng. Nó không nên thêm nhiều mã vào lớp người thích ứng, ngoài việc gọi phương thức thích nghi và chuyển đổi dữ liệu không thường xuyên cần thiết để thực hiện các cuộc gọi như vậy.

Không có nhiều ví dụ về bộ điều hợp tốt trong JDK hoặc các thư viện cơ bản. Các nhà phát triển ứng dụng tạo Bộ điều hợp, để điều chỉnh các thư viện cho các giao diện cụ thể của ứng dụng.

Người trang trí

Trình trang trí không chỉ ủy thác, không chỉ ánh xạ một phương thức này sang phương thức khác, họ còn làm nhiều hơn, họ sửa đổi hành vi của một số phương thức chủ đề, nó có thể quyết định không gọi phương thức chủ đề nào cả, ủy thác cho một đối tượng khác, một đối tượng trợ giúp.

Trình trang trí thường thêm chức năng (trong suốt) vào đối tượng được bọc như ghi nhật ký, mã hóa, định dạng hoặc nén vào chủ đề. Chức năng mới này có thể mang lại rất nhiều mã mới. Do đó, các nhà trang trí thường rất nhiều người thích Fatter, sau đó là Người thích nghi.

Trình trang trí phải là một lớp con của giao diện của chủ đề. Chúng có thể được sử dụng trong suốt thay vì các đối tượng của nó. Xem BufferedOutputStream, nó vẫn là OutputStream và có thể được sử dụng như vậy. Đó là một sự khác biệt kỹ thuật lớn từ Bộ điều hợp.

Các ví dụ về sách giáo khoa của toàn bộ gia đình trang trí có sẵn trong JDK - Java IO. Tất cả các lớp như BufferedOutputStream , FilterOutputStreamObjectOutputStream đều là những người trang trí cho OutputStream . Chúng có thể được xếp lớp hành tây, trong đó một trang trí được trang trí lại, thêm chức năng.

Ủy quyền

Proxy không phải là một trình bao bọc thông thường. Đối tượng được bao bọc, chủ đề proxy, có thể chưa tồn tại tại thời điểm tạo proxy. Proxy thường tạo ra nó trong nội bộ. Nó có thể là một đối tượng nặng được tạo theo yêu cầu hoặc nó là đối tượng từ xa trong JVM khác nhau hoặc nút mạng khác nhau và thậm chí là một đối tượng không phải Java, một thành phần trong mã gốc. Nó hoàn toàn không phải bọc hoặc ủy thác cho một đối tượng khác.

Ví dụ điển hình nhất là proxy từ xa, khởi tạo đối tượng nặng và proxy truy cập.

  • Remote Proxy - chủ đề nằm trên máy chủ từ xa, JVM khác hoặc thậm chí không phải hệ thống Java. Proxy chuyển các cuộc gọi phương thức sang các cuộc gọi RMI / REST / SOAP hoặc bất cứ điều gì cần thiết, bảo vệ khách hàng tiếp xúc với công nghệ cơ bản.

  • Lazy Load Proxy - khởi tạo hoàn toàn đối tượng chỉ sử dụng đầu tiên hoặc sử dụng chuyên sâu đầu tiên.

  • Proxy truy cập - kiểm soát quyền truy cập vào chủ đề.

Mặt tiền

Mặt tiền được liên kết chặt chẽ với nguyên tắc thiết kế của kiến ​​thức tối thiểu (Law of Demeter). Mặt tiền rất giống với Adaptor. Cả hai bao bọc, cả hai ánh xạ đối tượng này sang đối tượng khác, nhưng chúng khác nhau về ý định. Mặt tiền làm phẳng cấu trúc phức tạp của một đối tượng, đồ thị đối tượng phức tạp, đơn giản hóa việc truy cập vào một cấu trúc phức tạp.

Mặt tiền bao bọc một cấu trúc phức tạp, cung cấp một giao diện phẳng cho nó. Điều này ngăn đối tượng khách hàng tiếp xúc với các mối quan hệ bên trong trong cấu trúc chủ thể do đó thúc đẩy khớp nối lỏng lẻo.

Cầu

Biến thể phức tạp hơn của mẫu Adaptor trong đó không chỉ thực hiện khác nhau mà còn trừu tượng hóa. Nó thêm một sự gián tiếp cho phái đoàn. Đoàn thêm là cầu. Nó tách bộ điều hợp ngay cả từ giao diện thích ứng. Nó làm tăng độ phức tạp hơn bất kỳ mẫu quấn nào khác, vì vậy hãy cẩn thận.

Sự khác biệt trong các nhà xây dựng

Sự khác biệt mẫu cũng rõ ràng khi nhìn vào các nhà xây dựng của họ.

  • Proxy không bao bọc một đối tượng hiện có. Không có chủ đề trong constructor.

  • Trình trang tríBộ điều hợp không bao bọc đối tượng đã có và thường
    được cung cấp trong hàm tạo.

  • Hàm tạo mặt tiền lấy phần tử gốc của toàn bộ biểu đồ đối tượng, nếu không, nó trông giống như Bộ điều hợp.

Ví dụ thực tế - Bộ điều hợp Marshall JAXB . Mục đích của bộ chuyển đổi này là ánh xạ một lớp phẳng đơn giản đến cấu trúc phức tạp hơn được yêu cầu bên ngoài và để ngăn chặn lớp chủ đề "gây ô nhiễm" với các chú thích quá mức.


30

Có rất nhiều sự trùng lặp trong nhiều mẫu của GoF. Tất cả đều được xây dựng dựa trên sức mạnh của đa hình và đôi khi chỉ thực sự khác nhau về ý định. (chiến lược so với nhà nước)

Sự hiểu biết của tôi về các mẫu tăng gấp 100 lần sau khi đọc các Mẫu thiết kế đầu tiên .

Tôi khuyên bạn nên nó!


9

Tất cả các câu trả lời tốt từ các chuyên gia đã giải thích từng mẫu tượng trưng cho cái gì.

Tôi sẽ trang trí các điểm chính.

Người trang trí:

  1. Thêm hành vi vào đối tượng trong thời gian chạy . Kế thừa là chìa khóa để đạt được chức năng này, đó là cả ưu điểm và nhược điểm của mẫu này.
  2. Nó sửa đổi hành vi của giao diện.

ví dụ: (với chuỗi): java.iocác lớp gói liên quan đến InputStream& OutputStreamgiao diện

FileOutputStream fos1 = new FileOutputStream("data1.txt");  
ObjectOutputStream out1 = new ObjectOutputStream(fos1);

Ủy quyền:

  1. Sử dụng nó để khởi tạo lười biếng, cải thiện hiệu suất bằng cách lưu trữ đối tượng và kiểm soát quyền truy cập vào máy khách / người gọi . Nó có thể cung cấp hành vi thay thế hoặc gọi đối tượng thực sự. Trong quá trình này, nó có thể tạo Đối tượng mới.
  2. Không giống như Decorator , cho phép xâu chuỗi các đối tượng, Proxy không cho phép xâu chuỗi.

ví dụ: java.rmicác lớp gói.

Bộ chuyển đổi:

  1. Nó cho phép hai giao diện không liên quan làm việc với nhau thông qua các đối tượng khác nhau , có thể đóng vai trò giống nhau.
  2. Nó sửa đổi giao diện ban đầu .

ví dụ java.io.InputStreamReader( InputStreamtrả về a Reader)

Cầu:

  1. Nó cho phép cả trừu tượng và triển khai thay đổi độc lập .
  2. Nó sử dụng thành phần trên thừa kế .

ví dụ: các lớp Collection trong java.util. Listthực hiện bởi ArrayList.

Lưu ý chính:

  1. Adaptor cung cấp một giao diện khác với chủ đề của nó. Proxy cung cấp giao diện tương tự. Trang trí cung cấp một giao diện nâng cao.
  2. Bộ điều hợp thay đổi giao diện của một đối tượng, Decorator nâng cao trách nhiệm của một đối tượng.
  3. Trang trí Proxy có các mục đích khác nhau nhưng cấu trúc tương tự
  4. Bộ điều hợp làm cho mọi thứ hoạt động sau khi chúng được thiết kế; Cầu làm cho họ làm việc trước khi họ đang có.
  5. Cầu được thiết kế lên phía trước để cho sự trừu tượng và việc thực hiện thay đổi độc lập. Bộ điều hợp được trang bị thêm để làm cho các lớp không liên quan làm việc cùng nhau
  6. Decorator được thiết kế để cho phép bạn thêm trách nhiệm cho các đối tượng mà không cần phân lớp.

Có một cái nhìn về các câu hỏi / bài viết SE tuyệt vời liên quan đến các ví dụ về các mẫu thiết kế khác nhau

Khi nào nên sử dụng mẫu trang trí?

Khi nào bạn sử dụng Mẫu cầu? Nó khác với mẫu Adaptor như thế nào?

Sự khác nhau giữa Proxy và Mẫu trang trí


8

Chúng khá giống nhau, và các đường giữa chúng khá xám. Tôi đề nghị bạn đọc các mục Mẫu ProxyMẫu trang trí trong wiki c2.

Các mục và thảo luận ở đó khá rộng rãi, và chúng cũng liên kết đến các bài viết liên quan khác. Nhân tiện, wiki c2 rất tuyệt vời khi tự hỏi về các sắc thái giữa các mẫu khác nhau.

Để tổng hợp các mục c2, tôi sẽ nói một người trang trí thêm / thay đổi hành vi, nhưng một proxy có liên quan nhiều hơn đến kiểm soát truy cập (khởi tạo lười biếng, truy cập từ xa, bảo mật, v.v.). Nhưng như tôi đã nói, các đường kẻ giữa chúng có màu xám và tôi thấy các tham chiếu đến các proxy có thể dễ dàng được xem như là vật trang trí và ngược lại.


4

Tất cả bốn mẫu liên quan đến việc bọc đối tượng / lớp bên trong với lớp bên ngoài, vì vậy chúng rất giống nhau về mặt cấu trúc. Tôi sẽ phác thảo sự khác biệt theo mục đích:

  • Ủy quyền đóng gói truy cập từ bên ngoài vào bên trong.
  • Người trang trí sửa đổi hoặc mở rộng hành vi của bên trong với bên ngoài.
  • Bộ chuyển đổi chuyển đổi giao diện từ bên trong ra bên ngoài.
  • Cầu tách phần bất biến của hành vi (bên ngoài) khỏi phần phụ thuộc vào biến hoặc nền tảng (bên trong).

Và bởi sự thay đổi giao diện giữa các đối tượng bên trong và bên ngoài:

  • trong các giao diện Proxy là như nhau.
  • trong giao diện trang trí là như nhau.
  • trong các giao diện Adaptor khác nhau chính thức, nhưng thực hiện cùng một mục đích.
  • trong giao diện Bridge là khác nhau về mặt khái niệm.

4

Đây là trích dẫn từ các mẫu thiết kế đầu tiên

Định nghĩa thuộc về cuốn sách. Ví dụ thuộc về tôi.

Trình trang trí - Không thay đổi giao diện, nhưng thêm trách nhiệm. Giả sử bạn có giao diện xe hơi, khi bạn thực hiện điều này cho các mẫu xe khác nhau (s, sv, sl), bạn có thể cần thêm trách nhiệm hơn đối với một số mẫu xe. Giống như có cửa sổ trời, túi khí vv ..

Bộ chuyển đổi - Chuyển đổi một giao diện này sang giao diện khác. Bạn có một giao diện xe hơi và bạn muốn nó hoạt động như xe jeep. Vì vậy, bạn lấy xe, sửa đổi nó và biến thành một chiếc xe jeep. Vì nó không phải là một chiếc xe jeep thực sự. Nhưng hoạt động như một chiếc xe jeep.

Mặt tiền - Làm cho giao diện đơn giản hơn. Giả sử bạn có giao diện xe hơi, máy bay, tàu thủy. Trên thực tế tất cả những gì bạn cần là một lớp gửi mọi người từ vị trí này sang vị trí khác. Bạn muốn mặt tiền để quyết định sử dụng phương tiện nào. Sau đó, bạn thu thập tất cả các tham chiếu giao diện dưới 1 ô và để nó quyết định / ủy nhiệm để giữ cho nó đơn giản.

Đầu tiên: "Mặt tiền không chỉ đơn giản hóa giao diện, nó tách khách hàng khỏi hệ thống con của các thành phần. Mặt tiền và bộ điều hợp có thể bao bọc nhiều lớp, nhưng mục đích của mặt tiền là đơn giản hóa, trong khi bộ chuyển đổi là để chuyển đổi giao diện sang thứ khác. "


1

Tôi sử dụng nó khá thường xuyên khi tiêu thụ các dịch vụ web. Mẫu Proxy có lẽ nên được đổi tên thành một cái gì đó thực dụng hơn, như 'Mẫu Wrapper ". Tôi cũng có một thư viện là Proxy cho MS Excel. Nó rất dễ dàng để tự động hóa Excel, mà không phải lo lắng về các chi tiết nền như cái gì phiên bản được cài đặt (nếu có).


Đó sẽ không chỉ là Mẫu bộ điều hợp?
Charles Graham

1
Một dịch vụ web được sử dụng bởi Proxy, trong khi Mẫu bộ điều hợp được sử dụng nhiều hơn cho việc chuyển đổi hoặc dịch dữ liệu từ dạng này sang dạng khác.
hmcclungiii

1

Nói về triển khai chi tiết, tôi thấy một sự khác biệt giữa Proxy và Trình trang trí, Bộ điều hợp, Mặt tiền ... Trong triển khai chung các mẫu này có một đối tượng đích được bao bọc bởi một đối tượng kèm theo. Khách hàng sử dụng đối tượng kèm theo thay vì đối tượng đích. Và đối tượng đích thực sự đóng một phần quan trọng bên trong một số phương thức bao quanh đối tượng.

Tuy nhiên, trong trường hợp Proxy, đối tượng kèm theo có thể tự chơi một số phương thức, nó chỉ khởi tạo đối tượng đích khi máy khách gọi một số phương thức mà nó cần đối tượng đích tham gia. Đây là khởi tạo lười biếng. Trong trường hợp các mẫu khác, đối tượng kèm theo hầu như dựa trên đối tượng đích. Vì vậy, đối tượng đích luôn được khởi tạo cùng với đối tượng kèm theo trong hàm tạo / setters.

Một điều nữa, một proxy thực hiện chính xác những gì một mục tiêu làm trong khi các mẫu khác thêm nhiều chức năng hơn vào mục tiêu.


1

Tôi muốn thêm các ví dụ vào câu trả lời của Bill Karwing (đó là btw tuyệt vời.) Tôi cũng thêm một số khác biệt chính của việc triển khai, mà tôi cảm thấy còn thiếu

Các phần được trích dẫn là từ câu trả lời của [ https://stackoverflow.com/a/350471/1984346] (Bill Karwing)

Proxy, Decorator, Adaptor và Bridge là tất cả các biến thể của việc "gói" một lớp. Nhưng công dụng của chúng là khác nhau.

  • Proxy có thể được sử dụng khi bạn muốn lười biếng khởi tạo một đối tượng hoặc che giấu sự thật rằng bạn đang gọi một dịch vụ từ xa hoặc kiểm soát quyền truy cập vào đối tượng.

ProxyClass và ObjectClass được ủy quyền, nên thực hiện cùng một giao diện, vì vậy chúng có thể hoán đổi cho nhau

Ví dụ - đối tượng đắt tiền proxy

class ProxyHumanGenome implements GenomeInterface  {
    private $humanGenome = NULL; 

    // humanGenome class is not instantiated at construct time
    function __construct() {
    }

    function getGenomeCount() {
        if (NULL == $this->humanGenome) {
            $this->instantiateGenomeClass(); 
        }
        return $this->humanGenome->getGenomeCount();
    }
} 
class HumanGenome implement GenomeInterface { ... }
  • Công cụ trang trí còn được gọi là "Proxy thông minh." Điều này được sử dụng khi bạn muốn thêm chức năng cho một đối tượng, nhưng không phải bằng cách mở rộng loại đối tượng đó. Điều này cho phép bạn làm như vậy trong thời gian chạy.

DecoratorClass nên (có thể) triển khai giao diện mở rộng của ObjectClass. Vì vậy, ObjectClass có thể được thay thế bằng DecoratorClass, nhưng không phải ngược lại.

Ví dụ - thêm chức năng bổ sung

class DecoratorHumanGenome implements CheckGenomeInterface  {

    // ... same code as previous example

    // added functionality
    public function isComplete() {
        $this->humanGenome->getCount >= 21000
    }
}

interface CheckGenomeInterface extends GenomeInterface {

    public function isComplete();

}

class HumanGenome implement GenomeInterface { ... }
  • Bộ điều hợp được sử dụng khi bạn có giao diện trừu tượng và bạn muốn ánh xạ giao diện đó sang một đối tượng khác có vai trò chức năng tương tự, nhưng giao diện khác.

Sự khác biệt tiềm ẩn Proxy, Trang trí, Bộ chuyển đổi

Adaptor cung cấp một giao diện khác với chủ đề của nó. Proxy cung cấp giao diện tương tự. Trang trí cung cấp một giao diện nâng cao.

  • Bridge rất giống với Adaptor, nhưng chúng tôi gọi nó là Bridge khi bạn xác định cả giao diện trừu tượng và triển khai cơ bản. Tức là bạn không thích ứng với một số mã kế thừa hoặc mã của bên thứ ba, bạn là người thiết kế tất cả các mã nhưng bạn cần có thể trao đổi các triển khai khác nhau.

  • Facade là một giao diện cấp cao hơn (đọc: đơn giản hơn) cho một hệ thống con của một hoặc nhiều lớp. Giả sử bạn có một khái niệm phức tạp đòi hỏi nhiều đối tượng để đại diện. Thay đổi tập hợp các đối tượng đó là khó hiểu, bởi vì bạn không biết đối tượng nào có phương thức bạn cần gọi. Đó là thời gian để viết một Mặt tiền cung cấp các phương thức cấp cao cho tất cả các hoạt động phức tạp bạn có thể làm cho bộ sưu tập các đối tượng. Ví dụ: một mô hình tên miền cho một bộ phận học, với các phương pháp như countStudents(), reportAttendance(), assignSubstituteTeacher(), và vân vân.

Hầu hết các thông tin trong câu trả lời này là từ https://sourcemaking.com/design_potypes , mà tôi khuyên dùng như một tài nguyên tuyệt vời cho các mẫu thiết kế.


0

Tôi tin rằng mã sẽ đưa ra một ý tưởng rõ ràng (để bổ sung cho câu trả lời của người khác). Vui lòng xem bên dưới, (Tập trung các loại mà một lớp thực hiện và kết thúc)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TestConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            /* Proxy */

            Console.WriteLine(Environment.NewLine);
            Console.WriteLine("PROXY");
            Console.WriteLine(Environment.NewLine);

            //instead of creating here create using a factory method, the facory method will return the proxy
            IReal realProxy = new RealProxy();
            Console.WriteLine("calling do work with the proxy object ");
            realProxy.DoWork();

            Console.WriteLine(Environment.NewLine);
            Console.WriteLine("ADAPTER");
            Console.WriteLine(Environment.NewLine);

            /*Adapter*/
            IInHand objectIHave = new InHand();
            Api myApi = new Api();
            //myApi.SomeApi(objectIHave); /*I cant do this, use a adapter then */
            IActual myAdaptedObject = new ActualAdapterForInHand(objectIHave);
            Console.WriteLine("calling api with  my adapted obj");
            myApi.SomeApi(myAdaptedObject);


            Console.WriteLine(Environment.NewLine);
            Console.WriteLine("DECORATOR");
            Console.WriteLine(Environment.NewLine);

            /*Decorator*/
            IReady maleReady = new Male();
            Console.WriteLine("now male is going to get ready himself");
            maleReady.GetReady();

            Console.WriteLine(Environment.NewLine);

            IReady femaleReady = new Female();
            Console.WriteLine("now female is going to get ready her self");
            femaleReady.GetReady();

            Console.WriteLine(Environment.NewLine);

            IReady maleReadyByBeautician = new Beautician(maleReady);
            Console.WriteLine("now male is going to get ready by beautician");
            maleReadyByBeautician.GetReady();

            Console.WriteLine(Environment.NewLine);

            IReady femaleReadyByBeautician = new Beautician(femaleReady);
            Console.WriteLine("now female is going to get ready by beautician");
            femaleReadyByBeautician.GetReady();

            Console.WriteLine(Environment.NewLine);

            Console.ReadLine();


        }
    }

    /*Proxy*/

    public interface IReal
    {
        void DoWork();
    }

    public class Real : IReal
    {
        public void DoWork()
        {
            Console.WriteLine("real is doing work ");
        }
    }


    public class RealProxy : IReal
    {
        IReal real = new Real();

        public void DoWork()
        {
            real.DoWork();
        }
    }

    /*Adapter*/

    public interface IActual
    {
        void DoWork();
    }

    public class Api
    {
        public void SomeApi(IActual actual)
        {
            actual.DoWork();
        }
    }

    public interface IInHand
    {
        void DoWorkDifferently();
    }

    public class InHand : IInHand
    {
        public void DoWorkDifferently()
        {
            Console.WriteLine("doing work slightly different ");
        }
    }

    public class ActualAdapterForInHand : IActual
    {
        IInHand hand = null;

        public ActualAdapterForInHand()
        {
            hand = new InHand();
        }

        public ActualAdapterForInHand(IInHand hnd)
        {
            hand = hnd;
        }

        public void DoWork()
        {
            hand.DoWorkDifferently();
        }
    }

    /*Decorator*/

    public interface IReady
    {
        void GetReady();
    }

    public class Male : IReady
    {
        public void GetReady()
        {
            Console.WriteLine("Taking bath.. ");
            Console.WriteLine("Dress up....");
        }
    }

    public class Female : IReady
    {
        public void GetReady()
        {
            Console.WriteLine("Taking bath.. ");
            Console.WriteLine("Dress up....");
            Console.WriteLine("Make up....");
        }
    }

    //this is a decorator
    public class Beautician : IReady
    {
        IReady ready = null;

        public Beautician(IReady rdy)
        {
            ready = rdy;
        }

        public void GetReady()
        {
            ready.GetReady();
            Console.WriteLine("Style hair ");

            if (ready is Female)
            {
                for (int i = 1; i <= 10; i++)
                {
                    Console.WriteLine("doing ready process " + i);
                }

            }
        }
    }

}

-3

Mẫu thiết kế không phải là toán học, nó là sự kết hợp giữa nghệ thuật và công nghệ phần mềm. Không có gì giống như đối với yêu cầu này, bạn phải sử dụng proxy, cầu nối, vv Các mẫu thiết kế được tạo ra để giải quyết các vấn đề. Nếu bạn dự đoán một vấn đề thiết kế, sau đó sử dụng nó. Dựa trên kinh nghiệm, bạn sẽ biết được vấn đề cụ thể, nên sử dụng mẫu nào. Nếu bạn giỏi về các nguyên tắc thiết kế vững chắc, bạn sẽ thực hiện mẫu thiết kế mà không biết đó là mẫu. Ví dụ phổ biến là mô hình nhà máy và nhà máy

Do đó tập trung nhiều hơn vào các nguyên tắc giảm dần, nguyên tắc mã hóa sạch và ttd


Đồng ý, mặc dù nó không trả lời câu hỏi.
Leon
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.