Trong những gì chúng ta hy vọng sẽ trở thành một series, “Swift Solutions” sẽ bao gồm các mẫu thiết kế khác nhau, lý do tại sao chúng ta sử dụng chúng và cách triển khai chúng theo cách Swifty. The Adapter Pattern là một mẫu thiết kế cho phép các đối tượng có chức năng tương tự hoạt động cùng nhau mặc dù có giao diện không tương thích. Nó cho phép tích hợp dẫn đến mã sạch hơn và dễ sử dụng hơn. Theo nghĩa đen, nó điều chỉnh một đối tượng để nó sử dụng các API quen thuộc hơn
Use Cases
The Adapter Pattern nên được sử dụng khi những case sau:
- Một thành phần chia sẻ chức năng tương tự với các đối tượng hiện có trong ứng dụng của bạn.
- Mặc dù chia sẻ chức năng tương tự, thành phần này có giao diện không tương thích với các đối tượng khác trong ứng dụng của bạn.
- Thành phần này thường từ framework của bên thứ ba.
- Không thể (hoặc không nên) sửa đổi source code của thành phần.
- Thành phần cần tích hợp với ứng dụng của bạn.
Adapter Pattern cho phép chúng ta lấy vật thể lạ này và làm cho nó hoạt động tốt với các vật thể hiện có của chúng ta. Có hai cách tiếp cận chính để đạt được điều này: Tiện ích mở rộng Swift và Lớp bộ điều hợp chuyên dụng.
Đủ với lý thuyết! Hãy để chúng tôi xem Adapter Pattern trông như thế nào trong practice.
Adapter Pattern: Swift Extension Approach
Swift Extension là một giải pháp thanh lịch cho hầu hết các tình huống đơn giản.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <span class="token keyword">protocol</span> <span class="token builtin">Jumping</span> <span class="token punctuation">{</span> <span class="token keyword">func</span> <span class="token function">jump</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">class</span> <span class="token class-name">Dog</span><span class="token punctuation">:</span> <span class="token builtin">Jumping</span> <span class="token punctuation">{</span> <span class="token keyword">func</span> <span class="token function">jump</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">print</span><span class="token punctuation">(</span><span class="token string">"Jumps Excitedly"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">class</span> <span class="token class-name">Cat</span><span class="token punctuation">:</span> <span class="token builtin">Jumping</span> <span class="token punctuation">{</span> <span class="token keyword">func</span> <span class="token function">jump</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">print</span><span class="token punctuation">(</span><span class="token string">"Pounces"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">let</span> dog <span class="token operator">=</span> <span class="token function">Dog</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">let</span> cat <span class="token operator">=</span> <span class="token function">Cat</span><span class="token punctuation">(</span><span class="token punctuation">)</span> |
Ở đây chúng tôi có một dog và một con cat. Cả hai đều có thể thực hiện jump (). Bây giờ, giả sử chúng ta tích hợp framework bên thứ ba và có một động vật ngoại lai.
The Adaptee
1 2 3 4 5 6 7 8 9 10 | <span class="token keyword">class</span> <span class="token class-name">Frog</span> <span class="token punctuation">{</span> <span class="token keyword">func</span> <span class="token function">leap</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">print</span><span class="token punctuation">(</span><span class="token string">"Leaps"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">let</span> frog <span class="token operator">=</span> <span class="token function">Frog</span><span class="token punctuation">(</span><span class="token punctuation">)</span> |
Một số điều cần lưu ý:
- frog object của chúng ta có một số chức năng tương tự với những người bạn lông lá của chúng ta.
- Mặc dù jumps, nhưng giao diện của nó khác: chúng ta phải gọi hàm leap () thay vì jump () để có được chức năng mong muốn.
The Adapter
1 2 3 4 5 6 7 | <span class="token keyword">extension</span> <span class="token builtin">Frog</span><span class="token punctuation">:</span> <span class="token builtin">Jumping</span> <span class="token punctuation">{</span> <span class="token keyword">func</span> <span class="token function">jump</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">leap</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Ở đây chúng ta tích hợp thành phần của mình bằng cách triển khai Adapter Pattern. Chúng ta chỉ đơn giản là tuân theo Frog để Jumping và tạo một hàm bao bọc các đối tượng khác của chúng tôi nhận ra. Bây giờ chúng tôi có thể loại bỏ hành vi tương tự của con ếch của chúng tôi mà không cần sửa đổi triển khai hiện có của nó. Chúng tôi chỉ đơn giản là mở rộng nó bằng một hàm wrapper mới để loại bỏ sự khác biệt của nó!
Before and After
Sẽ rất hữu ích khi xem cách chúng ta làm việc với các đối tượng của mình trước và sau khi chúng tôi điều chỉnh frog’s interface của mình.
Before:
1 2 3 4 5 6 7 8 9 10 11 12 13 | <span class="token keyword">var</span> animals<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token builtin">Jumping</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span>dog<span class="token punctuation">,</span> cat<span class="token punctuation">]</span> <span class="token keyword">func</span> <span class="token function">jumpAll</span><span class="token punctuation">(</span>animals<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token builtin">Jumping</span><span class="token punctuation">]</span><span class="token punctuation">,</span> frog<span class="token punctuation">:</span> <span class="token builtin">Frog</span> <span class="token operator">=</span> <span class="token constant">nil</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">for</span> animal <span class="token keyword">in</span> animals <span class="token punctuation">{</span> animal<span class="token punctuation">.</span><span class="token function">jump</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">if</span> <span class="token keyword">let</span> frog <span class="token operator">=</span> frog <span class="token punctuation">{</span> frog<span class="token punctuation">.</span><span class="token function">leap</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
After:
1 2 3 4 5 6 7 8 | <span class="token keyword">var</span> animals<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token builtin">Jumping</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span>dog<span class="token punctuation">,</span> cat<span class="token punctuation">,</span> frog<span class="token punctuation">]</span> <span class="token keyword">func</span> <span class="token function">jumpAll</span><span class="token punctuation">(</span>animals<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token builtin">Jumping</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">for</span> animal <span class="token keyword">in</span> animals <span class="token punctuation">{</span> animal<span class="token punctuation">.</span><span class="token function">jump</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Adapter Pattern: The Dedicated Adapter Approach
Đối với các tình huống phức tạp hơn, việc tạo một adapter class có thể hữu ích.
1 2 3 4 5 6 7 8 | <span class="token keyword">class</span> <span class="token class-name">FrogAdapter</span><span class="token punctuation">:</span> <span class="token builtin">Jumping</span> <span class="token punctuation">{</span> <span class="token keyword">private</span> <span class="token keyword">let</span> frog <span class="token operator">=</span> <span class="token function">Frog</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">func</span> <span class="token function">jump</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> frog<span class="token punctuation">.</span><span class="token function">leap</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Ở đây chúng tôi tạo một lớp adapter chứa thành phần foreign trong một thuộc tính riêng. Mở rộng Frog có thể đã tiếp xúc nhiều hơn chúng ta muốn. Với dedicated adapter, người gọi không còn có thể thao tác trực tiếp với frog; nó chỉ có thể sử dụng bất cứ thứ gì được FrogAdapter tiết lộ. Điều này cho phép đóng gói frog tốt hơn, cho phép chúng ta kiểm soát hoàn toàn những gì tiếp xúc với người gọi. Và đó là khá tốt cho cả hai cách tiếp cận!
Referent from Source: Link