Bài kế tiếp của builder dùng cho các trường hợp nào
Chúng tôi có thể xây dựng một lớp BaseService sử dụng phong cách Builder để dùng chung cho mọi class.
Cho các yêu cầu HTTP, BaseService sẽ cung cấp các phương thức cơ bản như thiết lập tên dịch vụ, URL cơ sở và headers.
Dưới đây là một ví dụ về cách sử dụng BaseService, cũng như một số lớp con cụ thể sử dụng nó:
// BaseService định nghĩa cấu trúc cơ bản và các phương thức dùng chung class BaseService { constructor() { this.serviceName = ''; this.baseUrl = ''; this.headers = {}; } } // BaseServiceBuilder xây dựng đối tượng BaseService class BaseServiceBuilder { constructor() { this.baseService = new BaseService(); } setServiceName(serviceName) { this.baseService.serviceName = serviceName; return this; } setBaseUrl(baseUrl) { this.baseService.baseUrl = baseUrl; return this; } setHeaders(headers) { this.baseService.headers = headers; return this; } build() { return this.baseService; } } // UserService thừa kế từ BaseService và mở rộng chức năng class UserService extends BaseService { constructor() { super(); } getUser(userId) { // Giả lập gọi API lấy thông tin người dùng console.log(`Fetching user ${userId} from ${this.baseUrl}`); // Đây là nơi bạn sẽ sử dụng fetch hoặc axios để thực hiện yêu cầu HTTP thực sự } } // ProductService thừa kế từ BaseService và mở rộng chức năng class ProductService extends BaseService { constructor() { super(); } getProduct(productId) { // Giả lập gọi API lấy thông tin sản phẩm console.log(`Fetching product ${productId} from ${this.baseUrl}`); // Đây là nơi bạn sẽ sử dụng fetch hoặc axios để thực hiện yêu cầu HTTP thực sự } } // Sử dụng BaseServiceBuilder để tạo ra đối tượng UserService và ProductService const userService = new BaseServiceBuilder() .setServiceName('User Service') .setBaseUrl('https://api.example.com/users') .setHeaders({ 'Authorization': 'Bearer token' }) .build(); const productService = new BaseServiceBuilder() .setServiceName('Product Service') .setBaseUrl('https://api.example.com/products') .setHeaders({ 'Authorization': 'Bearer token' }) .build(); // Thiết lập cho UserService và ProductService const userSvc = Object.assign(new UserService(), userService); const productSvc = Object.assign(new ProductService(), productService); // Sử dụng UserService và ProductService để gọi API userSvc.getUser(123); productSvc.getProduct(456);
Khi đó chúng ta sử dụng build để điền thuộc tính vào lớp rất dễ nhìn và linh hoạt đúng không
Giải thích:
– BaseService mô tả các đặc điểm cơ bản và cách sử dụng thông thường của các dịch vụ.
– BaseServiceBuilder: Để thiết lập các thuộc tính của BaseService, hãy sử dụng mô hình Builder.
– Các dịch vụ người dùng và hàng hóa: Các dịch vụ này phát triển từ dịch vụ cơ bản và có các phương thức riêng cho từng dịch vụ.
– Sử dụng Builder: Bằng BaseServiceBuilder, bạn có thể tạo đối tượng UserService và ProductService với các thuộc tính đã được thiết lập trước đó.
– Object.
assign có thể sao chép các thuộc tính vào các đối tượng UserService và ProductService từ đối tượng BaseService đã được xây dựng.
– Để thêm các dịch vụ mới mà vẫn tận dụng được các thiết lập chung của BaseService, cấu trúc này cho phép bạn dễ dàng mở rộng.
Trong những trường hợp sau đây, Builder pattern thường được sử dụng:
– Xây dựng các đối tượng phức tạp: được sử dụng khi cần tạo ra các đối tượng có nhiều thuộc tính hoặc khi việc thiết lập đối tượng cần nhiều bước hoặc phụ thuộc vào một trình tự cụ thể.
– Khởi tạo đối tượng bất biến: Phương pháp xây dựng giúp thiết lập toàn bộ đối tượng trước khi khởi tạo khi bạn cần khởi tạo một đối tượng mà không thể thay đổi trạng thái của nó sau khi tạo.
Tránh các nhà xây dựng có nhiều tham số:
– Builder pattern giúp làm rõ mã nguồn và tránh nhầm lẫn khi gọi constructor khi một constructor có quá nhiều tham số.
Điều này đặc biệt đúng khi constructor có một số tham số là tùy chọn.
Mở rộng khả năng đọc và bảo trì của mã nguồn:
– Builder pattern cho phép bạn xây dựng các đối tượng từng bước với các phương thức có tên rõ ràng khi bạn muốn mã nguồn của mình dễ đọc và bảo trì hơn.
Thiết lập đối tượng một cách linh hoạt theo từng bước:
– Khi bạn muốn linh hoạt hóa các thuộc tính của đối tượng, bạn không cần tuân theo một trình tự nhất định như khi sử dụng constructor.
Các minh họa cụ thể:
– Các đối tượng cấu hình thường có nhiều chức năng và tùy chọn, chẳng hạn như cấu hình kết nối cơ sở dữ liệu, cấu hình máy chủ và cấu hình ứng dụng.
const config = new ConfigBuilder() .setHost('localhost') .setPort(8080) .setUsername('admin') .setPassword('password') .build();
Có nhiều lựa chọn để tạo thành phần giao diện người dùng, chẳng hạn như các dialog, form hoặc widget.
const dialog = new DialogBuilder() .setTitle('Confirm Delete') .setMessage('Are you sure you want to delete this item?') .setPositiveButton('Yes') .setNegativeButton('No') .build();
Khi làm việc với các đối tượng mô hình dữ liệu có nhiều trường, đặc biệt là khi có một số trường tùy chọn.
const user = new UserBuilder() .setFirstName('John') .setLastName('Doe') .setEmail('[email protected]') .setAge(30) .build();
khi tạo báo cáo, email hoặc file PDF với nhiều phần và định dạng.
const report = new ReportBuilder() .setTitle('Annual Report') .addSection('Introduction') .addSection('Financial Overview') .addSection('Future Plans') .build();
Trong các hệ thống phần mềm lớn và phức tạp, nơi các đối tượng phải được xây dựng theo một cách tuần tự và phụ thuộc vào nhiều yếu tố.
const gameCharacter = new GameCharacterBuilder() .setName('Archer') .setClass('Ranger') .setLevel(10) .setHealth(150) .setMana(50) .addSkill('Arrow Shot') .addSkill('Evasion') .build();
Tóm lại, khi bạn cần tạo các đối tượng phức tạp hoặc khi bạn muốn cải thiện tính rõ ràng và bảo trì của mã nguồn, Builder pattern là một công cụ tuyệt vời.
Nó giúp việc tạo và thiết lập đối tượng trở nên rõ ràng và có cấu trúc hơn.
Đây là một ví dụ về việc xây dựng một đối tượng API client trong JavaScript bằng cách sử dụng kỹ thuật Builder.
API client này có thể được sử dụng để gửi các yêu cầu HTTP đến một API riêng biệt.
class ApiClient { constructor() { this.baseUrl = ''; this.headers = {}; this.timeout = 0; } get(endpoint) { return fetch(`${this.baseUrl}${endpoint}`, { method: 'GET', headers: this.headers, timeout: this.timeout }).then(response => response.json()); } post(endpoint, body) { return fetch(`${this.baseUrl}${endpoint}`, { method: 'POST', headers: { 'Content-Type': 'application/json', ...this.headers }, body: JSON.stringify(body), timeout: this.timeout }).then(response => response.json()); } // Các phương thức HTTP khác như PUT, DELETE có thể được thêm vào tương tự }
Lớp ApiClientBuilder
class ApiClientBuilder { constructor() { this.apiClient = new ApiClient(); } setBaseUrl(baseUrl) { this.apiClient.baseUrl = baseUrl; return this; } setHeaders(headers) { this.apiClient.headers = headers; return this; } setTimeout(timeout) { this.apiClient.timeout = timeout; return this; } build() { return this.apiClient; } }
Sử dụng ApiClientBuilder để xây dựng một API Client
const apiClient = new ApiClientBuilder() .setBaseUrl('https://api.example.com/') .setHeaders({ 'Authorization': 'Bearer token' }) .setTimeout(5000) .build(); // Sử dụng API client để thực hiện các yêu cầu apiClient.get('/users') .then(data => console.log(data)) .catch(error => console.error('Error:', error)); apiClient.post('/users', { name: 'John Doe', email: '[email protected]' }) .then(data => console.log(data)) .catch(error => console.error('Error:', error));
– Giải thích: ApiClient là lớp đại diện cho API client và có các phương thức như GET và POST để thực hiện các yêu cầu HTTP.
Tương tự như vậy, bạn có thể thêm các phương thức bổ sung, chẳng hạn như PUT và DELETE.
– ApiClientBuilder: Lớp này sử dụng pattern Builder để thiết lập các thuộc tính của ApiClient như baseUrl, headers và timeout.
– Sử dụng Builder: ApiClientBuilder được sử dụng để tạo ra một đối tượng ApiClient với các thuộc tính đã được thiết lập trước đó.
Sau đó, các yêu cầu HTTP có thể được thực hiện bằng cách sử dụng đối tượng ApiClient này.
– Cấu trúc này giúp tạo các API client với nhiều cấu hình và thêm các phương thức HTTP mới dễ dàng và hợp lý.
Phương thức handleResponse có thể được mở rộng để xử lý lỗi từ API và hiển thị thông báo trên giao diện người dùng.
Điều này cho phép xử lý các mã lỗi riêng biệt và tạo ra các thông báo tương ứng.
Đây là cách bạn thực hiện điều này.
class ApiClient { constructor() { this.baseUrl = ''; this.headers = {}; this.timeout = 0; } async handleResponse(response) { if (!response.ok) { const errorData = await response.json(); let errorMessage = `Error: ${response.status} ${response.statusText}`; switch (response.status) { case 400: errorMessage = 'Bad Request: ' + (errorData.message || errorMessage); break; case 401: errorMessage = 'Unauthorized: ' + (errorData.message || errorMessage); break; case 403: errorMessage = 'Forbidden: ' + (errorData.message || errorMessage); break; case 404: errorMessage = 'Not Found: ' + (errorData.message || errorMessage); break; case 500: errorMessage = 'Internal Server Error: ' + (errorData.message || errorMessage); break; // Bạn có thể thêm nhiều mã lỗi khác tại đây default: errorMessage = errorData.message || errorMessage; break; } const error = new Error(errorMessage); error.data = errorData; throw error; } return response.json(); } async get(endpoint) { try { const response = await fetch(`${this.baseUrl}${endpoint}`, { method: 'GET', headers: this.headers, timeout: this.timeout }); return this.handleResponse(response); } catch (error) { console.error('GET request failed:', error); this.showErrorNotification(error.message); throw error; } } async post(endpoint, body) { try { const response = await fetch(`${this.baseUrl}${endpoint}`, { method: 'POST', headers: { 'Content-Type': 'application/json', ...this.headers }, body: JSON.stringify(body), timeout: this.timeout }); return this.handleResponse(response); } catch (error) { console.error('POST request failed:', error); this.showErrorNotification(error.message); throw error; } } // Các phương thức HTTP khác như PUT, DELETE có thể được thêm vào tương tự showErrorNotification(message) { // Giả lập hiển thị thông báo lỗi (ví dụ: sử dụng alert hoặc tích hợp với hệ thống thông báo giao diện người dùng) alert(message); } }
Cách sử dụng
const apiClient = new ApiClientBuilder() .setBaseUrl('https://api.example.com/') .setHeaders({ 'Authorization': 'Bearer token' }) .setTimeout(5000) .build(); // Sử dụng API client để thực hiện các yêu cầu apiClient.get('/users') .then(data => console.log(data)) .catch(error => console.error('Error:', error)); apiClient.post('/users', { name: 'John Doe', email: '[email protected]' }) .then(data => console.log(data)) .catch(error => console.error('Error:', error));
Tính năng handleResponse xử lý mã lỗi HTTP riêng biệt và tạo ra các thông báo lỗi cụ thể dựa trên mã lỗi.
Mỗi mã lỗi bao gồm một thông báo để người dùng biết nguyên nhân gây ra lỗi.
Xử lý các lỗi trong GET và POST:
– Trong các phương thức get và post, nếu xảy ra lỗi, chúng tôi sử dụng phương thức hiển thị thông báo lỗi trước khi ném lại lỗi.
– Phương pháp này giả lập việc hiển thị thông báo lỗi trên giao diện người dùng.
Bạn có thể tùy chỉnh nó để tích hợp nó vào hệ thống thông báo của ứng dụng, chẳng hạn như sử dụng thư viện thông báo như Toastr, SweetAlert hoặc Custom Alerts.
– Sử dụng API client: Các ví dụ get và post cho bạn biết cách sử dụng API client và xử lý các lỗi phát sinh khi gọi API.
Cấu trúc này cho phép người dùng dễ dàng nhìn thấy các thông báo lỗi chi tiết.
#Mtips5s #Contact
Fanpage: https://www.facebook.com/mtipscoder
Group trao đổi, chia sẻ: https://www.facebook.com/groups/mtipscoder
Website: https://mtips5s.com
Youtube: https://mtips5s.com
Twitter(X): @takagiks99
Instagram: @khuongkara
Threads: @khuongkara
Google Maps: @khuongkara
#Base Code #Souce Code
Npm: @tools.mtips5s.com
Bộ công cụ My Self: @github
Npm: @npm
Docker: @docker
Chúc các bạn thành công!
Leave A Comment