Blog#51: Design Patterns: Strategy Pattern trong TypeScript 😊 (Series: Bón hành TypeScript – PHẦN 1)

Mình là TUẤN hiện đang là một Full-stack Developer tại Tokyo 😊. Nếu bạn thấy Blog này hay xin hãy cho mình một like và đăng ký để ủng hộ mình nhé 😉. Cách sử dụng Strategy Pattern bằng TypeScript để giải quyết các vấn đỠthực tế trong các project web. Chào mừng bạn

image.png

Mình là TUẤN hiện đang là một Full-stack Developer tại Tokyo 😊.
Nếu bạn thấy Blog này hay xin hãy cho mình một like và đăng ký để ủng hộ mình nhé 😉.

Cách sử dụng Strategy Pattern bằng TypeScript để giải quyết các vấn đỠthực tế trong các project web.

Chào mừng bạn đến với loạt bài Design Patterns trong TypeScript, loạt bài này mình sẽ giới thiệu một số Design Patterns hữu ích trong phát triển web bằng TypeScript.

Các Design Patterns rất quan trá»ng đối vá»›i các web developer và chúng ta có thể code tốt hÆ¡n bằng cách thành thạo chúng. Trong bài viết này, mình sẽ sá»­ dụng TypeScript để giá»›i thiệu Strategy Pattern .

Strategy Pattern

Äăng ký và Äăng nhập là các tính năng quan trá»ng trong các ứng dụng web. Khi đăng ký má»™t ứng dụng web, cách phổ biến hÆ¡n để đăng ký là sá»­ dụng account/password, email hoặc số Ä‘iện thoại di Ä‘á»™ng… Khi bạn đã đăng ký thành công, bạn có thể sá»­ dụng hàm tÆ°Æ¡ng ứng để Login.

functionlogin(mode){if(mode ==="account"){loginWithPassword();}elseif(mode ==="email"){loginWithEmail();}elseif(mode ==="mobile"){loginWithMobile();}}

Khi ứng dụng web cần há»— trợ các hàm Login khác, ví dụ: ngoài hàm Login email, trang Login còn há»— trợ các tính năng Login của ná»n tảng bên thứ ba nhÆ° Google, Facebook, Apple và Twitter.

image.png

Vậy để hỗ trợ thêm các phương thức hàm Login của bên thứ ba, chúng ta cần sửa đổi function login trước đó:

functionlogin(mode){if(mode ==="account"){loginWithPassword();}elseif(mode ==="email"){loginWithEmail();}elseif(mode ==="mobile"){loginWithMobile();}elseif(mode ==="google"){loginWithGoogle();}elseif(mode ==="facebook"){loginWithFacebook();}elseif(mode ==="apple"){loginWithApple();}elseif(mode ==="twitter"){loginWithTwitter();}}

Nhìn có vẻ không ổn chút nào nhở!
Nếu sau này chúng ta tiếp tục thêm hoặc sá»­a đổi các phÆ°Æ¡ng thức Login, chúng ta sẽ thấy rằng function login này ngày càng trở nên khó maintenance hÆ¡n. Äối vá»›i vấn Ä‘á» này, chúng ta có thể sá»­ dụng Strategy Pattern để đóng gói các hàm Login khác nhau vào các strategy khác nhau.

Äể hiểu rõ hÆ¡n vá» Ä‘oạn code sau, trÆ°á»›c tiên chúng ta hãy xem sÆ¡ đồ UML tÆ°Æ¡ng ứng:

image.png

Trong hình trên, chúng ta xác định một Interface Strategy, sau đó implement hai strategy Login cho Twitter và account/password dựa trên Interface này.

Interface strategy

interfaceStrategy{authenticate(args: any[]): boolean;}

Strategy Twitter Class được triển khai từ Interface Strategy

classTwitterStrategyimplementsStrategy{authenticate(args: any[]){const[token]= args;if(token !=="tw123"){
      console.error("Twitter account authentication failed!");returnfalse;}
    console.log("Twitter account authentication succeeded!");returntrue;}}

LocalStrategy class cũng được triển khai từ Interface Strategy

classLocalStrategyimplementsStrategy{authenticate(args: any[]){const[username, password]= args;if(username !=="bytefer"|| password !=="666"){
      console.log("Incorrect username or password!");returnfalse;}
    console.log("Account and password authentication succeeded!");returntrue;}}

Sau khi có các được triển khai từ Interface Strategy khác nhau, chúng ta định nghĩa một lớp Authenticator để chuyển đổi giữa các strategy Login khác nhau và thực hiện các thao tác authentication tương ứng.

Authenticator class

classAuthenticator{
  strategies: Record<string, Strategy>={};use(name: string, strategy: Strategy){this.strategies[name]= strategy;}authenticate(name: string,...args: any){if(!this.strategies[name]){
      console.error("Authentication policy has not been set!");returnfalse;}returnthis.strategies[name].authenticate.apply(null, args);// authenticate.apply là cú pháp apply args của typescript}}

authenticate.apply gá»i hàm authenticate vá»›i giá trị this đã cho và các đối số được cung cấp dÆ°á»›i dạng má»™t mảng (hoặc má»™t đối tượng giống nhÆ° mảng)

Sau đó, chúng ta có thể sử dụng các hàm Login khác nhau để đạt được authentication user theo các cách sau:

const auth =newAuthenticator();
auth.use("twitter",newTwitterStrategy());
auth.use("local",newLocalStrategy());functionlogin(mode: string,...args: any){return auth.authenticate(mode, args);}login("twitter","123");login("local","bytefer","666");

Khi bạn chạy thành công đoạn code trên, output tương ứng được hiển thị trong hình sau:

image.png

Strategy Pattern ngoài việc sá»­ dụng cho trÆ°á»ng hợp authentication Login cÅ©ng có thể được sá»­ dụng trong nhiá»u kịch bản khác nhau (Ví dụ nhÆ°: form validation). Nó cÅ©ng có thể được sá»­ dụng để tối Æ°u hóa các vấn Ä‘á» vá»›i quá nhiá»u nhánh if/else.

Nếu bạn sử dụng Node.js để phát triển các authentication service, thì thông thương các bạn sẽ sử dụng thư viện passport.js này đúng ko. Nếu các bạn đã từng sử dụng thư viện/Mô-đun Passport.js này nhưng ko biết cách nó hoạt động ra sao, thì Strategy Pattern sẽ giúp bạn hiểu vỠnó hơn. Dùng một thứ mình hiểu vẫn tốt hơn là dùng mà ko hiểu đúng ko. Ahihi

Mô-đun passport.js này rất mạnh mẽ và hiện hỗ trợ tới 538 strategy:

image.png

Một số tình huống mà bạn có thể suy nghĩ đến việc sử dụng Strategy Pattern:

  • Khi má»™t hệ thống cần tá»± Ä‘á»™ng chá»n má»™t trong số các thuật toán. Và má»—i thuật toán có thể được gói gá»n trong má»™t strategy.
  • Nhiá»u class chỉ khác nhau vá» hành vi và có thể sá»­ dụng Strategy Pattern để tá»± Ä‘á»™ng chá»n hành vi cụ thể sẽ được thá»±c thi trong thá»i gian chạy.

Roundup

NhÆ° má»i khi, mình hy vá»ng bạn thích bài viết này và há»c thêm được Ä‘iá»u gì đó má»›i.

Cảm Æ¡n và hẹn gặp lại các bạn trong những bài viết tiếp theo! ðŸ˜

Nếu bạn thấy Blog này hay xin hãy cho mình một like và đăng ký để ủng hộ mình nhé. Thank you.😉

Ref

Nguồn: viblo.asia

Bài viết liên quan

Thay đổi Package Name của Android Studio dể dàng với plugin APR

Nếu bạn đang gặp khó khăn hoặc bế tắc trong việc thay đổi package name trong And

Lỗi không Update Meta_Value Khi thay thế hình ảnh cũ bằng hình ảnh mới trong WordPress

Mã dÆ°á»›i đây hoạt Ä‘á»™ng tốt có 1 lá»—i không update được postmeta ” meta_key=

Bài 1 – React Native DevOps các khái niệm và các cài đặt căn bản

HÆ°á»›ng dẫn setup jenkins agent để bắt đầu build mobile bằng jenkins cho devloper an tÃ

Chuyển đổi từ monolith sang microservices qua ví dụ

1. Why microservices? Microservices là kiến trúc hệ thống phần má»m hÆ°á»›ng dịch vụ,