Blog#57: Design Patterns: Template Method Pattern trong TypeScript 😊 (Series: Bón hành TypeScript – PHẦN 7)

Mình là TUẤN hiện đang là một Full-stack Web 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é 😉. Chào mừng bạn đến với loạt bài Design Patterns trong TypeScript, tại đây mình giới thiệu một số Design Patterns hữu

image.png

Mình là TUẤN hiện đang là một Full-stack Web 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é 😉.

Chào mừng bạn đến với loạt bài Design Patterns trong TypeScript, tại đây mình 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 Template Method Pattern.

Kịch bản thưởng gặp

CSV (Comma-Separated Values – Các value được phân tách bằng dấu phẩy) là định dạng tệp tương đối đơn giản. Tệp CSV lưu trữ dữ liệu dạng bảng (numbers and text) ở dạng văn bản thuần túy. Khi bạn cần xử lý dữ liệu CSV, quy trình xử lý tương ứng được hiển thị trong hình sau:

image.png

Sau khi hiểu được quy trình xử lý trên, chúng ta hãy sử dụng Node.js để implement function Parsing tệp csv.

users.csv

id,Name
1,Bytefer
2,Kakuqo

parse-csv.ts

import fs from"fs";import path from"path";import*as url from"url";import{ csvParse }from"d3-dsv";const __dirname = url.fileURLToPath(newURL(".",import.meta.url));constprocessData=(fileData: any[])=> console.dir(fileData);const content = fs.readFileSync(path.join(__dirname,"users.csv"),"utf8");const fileData =csvParse(content);processData(fileData);

Trong đoạn code trên, chúng ta import mô-đun d3-dsv để implement function Parsing csv. Sau đó, chúng ta sử dụng esno để thực thi tệp parse-cvs.ts :

$ npx esno parse-csv.ts

Khi đoạn code trên chạy thành công, terminal sẽ xuất ra kết quả như sau:

[
  { id: '1', Name: 'Bytefer' },
  { id: '2', Name: 'Kakuqo' },
  columns: [ 'id', 'Name' ]
]

Tiếp theo, Markdown là một ngôn ngữ đánh dấu văn bản nhẹ cho phép mọi người viết tài liệu ở định dạng văn bản thuần túy, dễ đọc và dễ viết. Để hiển thị tài liệu Markdown trên các trang web, chúng ta phải chuyển đổi tài liệu Markdown thành tài liệu HTML.

Để thực hiện được function trên, quy trình xử lý của chúng ta như sau:

image.png

Sau khi hiểu được quy trình xử lý trên, chúng ta hãy sử dụng Node.js để implement function Parsing Markdown.

Users.md

### Users
- Bytefer
- Kakuqo

parse-md.ts

import fs from"fs";import path from"path";import*as url from"url";import{ marked }from'marked';const __dirname = url.fileURLToPath(newURL(".",import.meta.url));constprocessData=(fileData: any[])=> console.dir(fileData);const content = fs.readFileSync(path.join(__dirname,"Users.md"),"utf8");const fileData = marked.parse(content);processData(fileData);

Trong đoạn code trên, chúng ta import mô-đun marked để thực hiện function Parsing Markdown. Sau đó, chúng ta lại sử dụng esno để thực thi tệp parse-md.ts :

$ npx esno parse-md.ts

Khi đoạn code trên chạy thành công, terminal sẽ xuất ra kết quả như sau:

'<h3 id="users">Users</h3>n<ul>n<li>Bytefer</li>n<li>Kakuqo</li>n</ul>n'

Đối với hai ví dụ trước, mặc dù các loại tệp khác nhau được Parsing, nhưng bạn sẽ thấy rằng quá trình Parsing của chúng là tương tự nhau.

image.png

Toàn bộ quá trình chủ yếu bao gồm ba bước: đọc, Parsing và xử lý dữ liệu. Đối với kịch bản này, chúng ta có thể apply Template Method Pattern để gói gọn trình tự xử lý của ba bước trên.

Template Method Pattern

Template Method Pattern bao gồm hai phần: một abstract parent class và một implementation subclass cụ thể. Thông thường, khung thuật toán của subclass được đóng gói trong abstract parent class và nó cũng bao gồm việc thực hiện một số hàm public và thứ tự thực hiện của tất cả các hàm trong subclass được đóng gói. Bằng cách kế thừa abstract class này, các subclass cũng kế thừa toàn bộ cấu trúc thuật toán và có thể chọn ghi đè các hàm của parent class.

Tiếp theo, hãy xem cách implement trình Parsing CSV và Parsing Markdown bằng cách sử dụng Template Method Pattern.

Để hiểu rõ hơn về đoạn code sau, trước tiên chúng ta hãy xem sơ đồ lớp UML tương ứng:

image.png

Trong hình trên, chúng ta định nghĩa một abstract class FileParser và sau đó định nghĩa hai subclass, CsvParserMarkdownParser, tương ứng.

FileParser class

abstract classFileParser{// Template Methodparse(filePath: string){let content =this.readFile(filePath);let fileData =this.parseFile(content);this.processData(fileData);}readFile(filePath: string){if(fs.existsSync(filePath)){return fs.readFileSync(filePath,"utf8");}}
  abstract parseFile(fileContent: string): any;processData(fileData: any[]){
    console.log(fileData);}}

Phương thức parse trong abstract class FileParser được gọi là Template method, trong đó chúng ta đóng gói quá trình xử lý tệp.

CsvParser class

class CsvParser extends FileParser {
parseFile(fileContent: string) {
return csvParse(fileContent);
}
}

MarkdownParser class

class MarkdownParser extends FileParser {
parseFile(fileContent: string) {
return marked.parse(fileContent);
}
}

Với hai lớp CsvParserMarkdownParser, chúng ta có thể Parsing CSV và Markdown theo các cách sau:

const csvParser =newCsvParser();
csvParser.parse(path.join(__dirname,"Users.csv"));const mdParser =newMarkdownParser();
mdParser.parse(path.join(__dirname,"Users.md"));

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

Bằng cách sử dụng Template Method Pattern, chúng ta đã implement lại việc Parsing CSV và Markdown. Trên thực tế, với abstract class FileParser, chúng ta có thể dễ dàng phát triển các chức năng Parsing cú pháp tệp khác nhau mà ko cần sửa Abstract class.

Các tình huống sử dụng của Template Method Pattern:

  • Các bước tổng thể của thuật toán là rất cố định, nhưng khi các phần riêng lẻ có thể thay đổi, Template Method Pattern có thể được sử dụng tại thời điểm này để trừu tượng hóa các phần dễ thay đổi cho các subclass thực hiện.

Các vấn đề tương tư như trên cũng hoàn toàn giải quyết được bằng Dependency Injection Pattern. Tương lai mình cũng sẽ có bài viết về chủ đề này các bạn nhớ đón xem nhé.

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

WebP là gì? Hướng dẫn cách để chuyển hình ảnh jpg, png qua webp

WebP là gì? WebP là một định dạng ảnh hiện đại, được phát triển bởi Google

Điểm khác biệt giữa IPv4 và IPv6 là gì?

IPv4 và IPv6 là hai phiên bản của hệ thống địa chỉ Giao thức Internet (IP). IP l

Check nameservers của tên miền xem website trỏ đúng chưa

Tìm hiểu cách check nameservers của tên miền để xác định tên miền đó đang dùn

Mình đang dùng Google Domains để check tên miền hàng ngày

Từ khi thông báo dịch vụ Google Domains bỏ mác Beta, mình mới để ý và bắt đầ