๐with Modern Backend Development
Design Patterns for Modern Backend Development โ with Example Use Cases
MVC (Model-View-Controller) Pattern

Overview
Mรด hรฌnh Model-View-Controller (MVC) lร mแปt mแบซu thiแบฟt kแบฟ ฤฦฐแปฃc sแปญ dแปฅng rแปng rรฃi trong phรกt triแปn backend hiแปn ฤแบกi. Nรณ cung cแบฅp cรกch phรขn tรกch tแบงng trรฌnh bร y (View) khแปi tแบงng business logic vร lฦฐu trแปฏ dแปฏ liแปu (Model vร Controller). Sแปฑ phรขn tรกch nร y giรบp cรกc lแบญp trรฌnh viรชn viแบฟt mรฃ mรด-ฤun hฦกn vร dแป dร ng bแบฃo trรฌ.
Trong mรด hรฌnh MVC, Model ฤแบกi diแปn cho dแปฏ liแปu vร business logic cแปงa แปฉng dแปฅng. Controller hoแบกt ฤแปng nhฦฐ mแปt trung gian giแปฏa Model vร View, xแปญ lรฝ ฤแบงu vร o tแปซ ngฦฐแปi dรนng vร cแบญp nhแบญt Model tฦฐฦกng แปฉng. View chแปu trรกch nhiแปm trรฌnh bร y dแปฏ liแปu cho ngฦฐแปi dรนng vร nhแบญn ฤแบงu vร o tแปซ ngฦฐแปi dรนng.
Mแปt trong cรกc ฦฐu ฤiแปm chรญnh cแปงa viแปc sแปญ dแปฅng mรด hรฌnh MVC lร cho phรฉp dแป dร ng kiแปm tra vร bแบฃo trรฌ mรฃ nguแปn. Vรฌ Model vร Controller ฤฦฐแปฃc tรกch ra khแปi View, nรชn cรณ thแป kiแปm tra vร sแปญa ฤแปi tแปซng thร nh phแบงn mแปt cรกch ฤแปc lแบญp.
Lแปฃi รญch khรกc cแปงa viแปc sแปญ dแปฅng mรด hรฌnh MVC lร cho phรฉp tรกi sแปญ dแปฅng mรฃ. Model vร Controller cรณ thแป ฤฦฐแปฃc tรกi sแปญ dแปฅng trong cรกc View khรกc nhau, cung cแบฅp mแปt cรกch tiแบฟp cแบญn mรด-ฤun hฦกn vแปi phรกt triแปn phแบงn mแปm.
Nhรฌn chung, mรด hรฌnh MVC lร mแปt cรดng cแปฅ hแปฏu รญch ฤแป tแบกo ra cรกc hแป thแปng backend cรณ thแป mแป rแปng, dแป bแบฃo trรฌ vร hiแปu quแบฃ. Nรณ phรขn tรกch cรกc mแปi quan tรขm vร cho phรฉp mแปt cรกch tiแบฟp cแบญn mรด-ฤun hฦกn trong phรกt triแปn phแบงn mแปm, giรบp dแป dร ng kiแปm tra, bแบฃo trรฌ vร sแปญa ฤแปi mรฃ nguแปn.
Example of using the MVC pattern in a web application
ฤแบงu tiรชn, chรบng ta sแบฝ xem xรฉt mแปt vรญ dแปฅ vแป viแปc sแปญ dแปฅng mรด hรฌnh MVC trong mแปt แปฉng dแปฅng web vแปi framework Node.js phแป biแบฟn, Express.js.
Trong mแปt แปฉng dแปฅng Express.js, thร nh phแบงn Model thฦฐแปng ฤฦฐแปฃc thแปฑc hiแปn bแบฑng cรกch sแปญ dแปฅng cฦก sแป dแปฏ liแปu nhฦฐ MongoDB hoแบทc MySQL. Thร nh phแบงn View thฦฐแปng ฤฦฐแปฃc thแปฑc hiแปn bแบฑng cรกch sแปญ dแปฅng cรกc cรดng cแปฅ tแบกo mแบซu nhฦฐ EJS hoแบทc Handlebars. Thร nh phแบงn Controller ฤฦฐแปฃc thแปฑc hiแปn bแบฑng cรกch sแปญ dแปฅng cรกc hร m phแบงn mแปm trung gian (middleware), cรกc hร m ฤฦฐแปฃc thแปฑc thi theo mแปt thแปฉ tแปฑ cแปฅ thแป khi cรณ yรชu cแบงu gแปญi ฤแบฟn mรกy chแปง.
Vรญ dแปฅ, khi ngฦฐแปi dรนng gแปญi yรชu cแบงu ฤแป xem mแปt bร i ฤฤng trรชn blog, yรชu cแบงu ฤฦฐแปฃc xแปญ lรฝ bแปi thร nh phแบงn Controller. Controller lแบฅy bร i viแบฟt tแปซ thร nh phแบงn Model vร truyแปn nรณ sang thร nh phแบงn View, nฦกi hiแปn thแป nรณ bแบฑng cรกch sแปญ dแปฅng mแปt cรดng cแปฅ tแบกo mแบซu. HTML kแบฟt quแบฃ sau ฤรณ ฤฦฐแปฃc gแปญi trแบฃ lแบกi trรฌnh duyแปt cแปงa ngฦฐแปi dรนng.
Sแปญ dแปฅng mรด hรฌnh MVC trong mแปt แปฉng dแปฅng web cรณ thแป mang lแบกi nhiแปu lแปฃi รญch, bao gแปm khแบฃ nฤng mแป rแปng, bแบฃo trรฌ vร kiแปm tra ฤฦฐแปฃc cแบฃi thiแปn. Bแบฑng cรกch tรกch แปฉng dแปฅng thร nh cรกc thร nh phแบงn riรชng biแปt, cรกc nhร phรกt triแปn cรณ thแป thay ฤแปi mแปt thร nh phแบงn mร khรดng แบฃnh hฦฐแปng ฤแบฟn cรกc thร nh phแบงn khรกc. ฤiแปu nร y giรบp dแป dร ng bแบฃo trรฌ vร kiแปm tra แปฉng dแปฅng theo thแปi gian.
Trong vรญ dแปฅ sau ฤรขy, Model ฤฦฐแปฃc thแป hiแปn bแปi lแปp PostModel, cรณ trรกch nhiแปm lแบฅy vร lฦฐu dแปฏ liแปu vร o cฦก sแป dแปฏ liแปu.
View ฤฦฐแปฃc thแป hiแปn bแปi lแปp PostView, cรณ trรกch nhiแปm hiแปn thแป trang HTML vร xแปญ lรฝ ฤแบงu vร o tแปซ ngฦฐแปi dรนng.
Controller ฤฦฐแปฃc thแป hiแปn bแปi lแปp PostController, hoแบกt ฤแปng nhฦฐ mแปt trung gian giแปฏa Model vร View. Nรณ khแปi tแบกo View, xแปญ lรฝ ฤแบงu vร o tแปซ ngฦฐแปi dรนng vร cแบญp nhแบญt View dแปฑa trรชn cรกc thay ฤแปi cแปงa Model.
// the model
interface Post {
id: number;
title: string;
content: string;
date: Date;
}
class PostModel {
private posts: Post[] = [];
getPosts() {
// fetch posts from database
return this.posts;
}
addPost(post: Post) {
// save post to database
this.posts.push(post);
}
}
// the view
class PostView {
displayPosts(posts: Post[]) {
// render posts to the HTML page
}
getPostFromInput(): Post {
// retrieve input values from the HTML page
// and create a new Post object
}
}
// the controller
class PostController {
private model: PostModel;
private view: PostView;
constructor(model: PostModel, view: PostView) {
this.model = model;
this.view = view;
}
init() {
// initialize the view
this.view.displayPosts(this.model.getPosts());
}
addPost() {
// get new post from view
const post = this.view.getPostFromInput();
// add post to model
this.model.addPost(post);
// update view
this.view.displayPosts(this.model.getPosts());
}
}
Viแปc triแปn khai mแบซu MVC nร y cho phรฉp tรกch biแปt cรกc mแปi quan tรขm vร tรญnh mรด ฤun trong web application code, khiแบฟn viแปc bแบฃo trรฌ vร mแป rแปng dแป dร ng hฦกn theo thแปi gian.
Repository Pattern

Overview
Mแบซu Repository lร mแปt mแบซu thiแบฟt kแบฟ cung cแบฅp mแปt lแปp trแปซu tฦฐแปฃng giแปฏa lแปp truy cแบญp dแปฏ liแปu vร phแบงn cรฒn lแบกi cแปงa แปฉng dแปฅng. Nรณ tรกch riรชng logic truy xuแบฅt dแปฏ liแปu tแปซ lแปp lฦฐu trแปฏ dแปฏ liแปu, cung cแบฅp mแปt phฦฐฦกng phรกp phรกt triแปn phแบงn mแปm mรด-ฤun hฦกn.
Trong mแบซu Repository, mแปt kho lฦฐu trแปฏ hoแบกt ฤแปng nhฦฐ mแปt ngฦฐแปi trung gian giแปฏa lแปp lฦฐu trแปฏ dแปฏ liแปu vร lแปp logic แปฉng dแปฅng. Nรณ cung cแบฅp mแปt ฤiแปm nhแบญp duy nhแบฅt ฤแป truy xuแบฅt vร thao tรกc dแปฏ liแปu, cho phรฉp phแบงn cรฒn lแบกi cแปงa แปฉng dแปฅng tรกch rแปi khแปi cรกc chi tiแบฟt cแปฅ thแป cแปงa lแปp lฦฐu trแปฏ dแปฏ liแปu. ฤiแปu nร y lร m cho viแปc thay ฤแปi lแปp lฦฐu trแปฏ dแปฏ liแปu dแป dร ng hฦกn mร khรดng แบฃnh hฦฐแปng ฤแบฟn phแบงn cรฒn lแบกi cแปงa แปฉng dแปฅng.
Mแปt trong nhแปฏng lแปฃi thแบฟ chรญnh cแปงa viแปc sแปญ dแปฅng mแบซu Repository lร nรณ cho phรฉp mแปt phฦฐฦกng phรกp phรกt triแปn phแบงn mแปm mรด-ฤun hฦกn. Lแปp logic แปฉng dแปฅng ฤฦฐแปฃc tรกch ra khแปi lแปp lฦฐu trแปฏ dแปฏ liแปu, lร m cho viแปc kiแปm tra vร bแบฃo trรฌ tแปซng thร nh phแบงn riรชng lแบป dแป dร ng hฦกn. ฤiแปu nร y cลฉng lร m cho viแปc tรกi sแปญ dแปฅng lแปp logic แปฉng dแปฅng vแปi cรกc lแปp lฦฐu trแปฏ dแปฏ liแปu khรกc nhau trแป nรชn dแป dร ng hฦกn.
Mแปt lแปฃi รญch khรกc cแปงa viแปc sแปญ dแปฅng mแบซu Repository lร nรณ cรณ thแป cแบฃi thiแปn hiแปu suแบฅt bแบฑng cรกch giแบฃm sแป lฦฐแปฃng lแบงn gแปi ฤแบฟn lแปp lฦฐu trแปฏ dแปฏ liแปu. Do logic truy cแบญp dแปฏ liแปu ฤฦฐแปฃc ฤรณng gรณi trong kho lฦฐu trแปฏ, nรชn cรณ thแป tแปi ฦฐu hรณa truy vแบฅn vร giแบฃm sแป lฦฐแปฃng lแบงn gแปi cฦก sแป dแปฏ liแปu.
Nhรฌn chung, mแบซu Repository lร mแปt cรดng cแปฅ hแปฏu รญch ฤแป tแบกo ra cรกc hแป thแปng phรญa sau linh hoแบกt, dแป bแบฃo trรฌ vร hiแปu quแบฃ. Nรณ tรกch biแปt cรกc mแปi quan tรขm vร cho phรฉp mแปt phฦฐฦกng phรกp phรกt triแปn phแบงn mแปm mรด-ฤun hฦกn, giรบp viแปc kiแปm tra, bแบฃo trรฌ vร sแปญa ฤแปi cฦก sแป mรฃ dแป dร ng hฦกn. Nรณ cลฉng cรณ thแป cแบฃi thiแปn hiแปu suแบฅt bแบฑng cรกch giแบฃm sแป lฦฐแปฃng lแบงn gแปi ฤแบฟn lแปp lฦฐu trแปฏ dแปฏ liแปu.
Example of using the Repository pattern with a database
Mแบซu Repository lร mแปt mแบซu thiแบฟt kแบฟ cung cแบฅp mแปt lแปp trแปซu tฦฐแปฃng giแปฏa lแปp truy cแบญp dแปฏ liแปu vร phแบงn cรฒn lแบกi cแปงa แปฉng dแปฅng. Trong mแบซu Repository, cฦก sแป dแปฏ liแปu ฤฦฐแปฃc biแปu diแป n dฦฐแปi dแบกng mแปt tแบญp hแปฃp cรกc ฤแปi tฦฐแปฃng, vแปi mแปi ฤแปi tฦฐแปฃng ฤแบกi diแปn cho mแปt bแบฃng hoแบทc bแป sฦฐu tแบญp trong cฦก sแป dแปฏ liแปu. Lแปp Repository cung cแบฅp mแปt tแบญp hแปฃp cรกc phฦฐฦกng thแปฉc ฤแป tฦฐฦกng tรกc vแปi cฦก sแป dแปฏ liแปu, chแบณng hแบกn nhฦฐ tแบกo, ฤแปc, cแบญp nhแบญt vร xรณa cรกc ฤแปi tฦฐแปฃng.
Vรญ dแปฅ, giแบฃ sแปญ chรบng ta cรณ mแปt แปฉng dแปฅng Express lฦฐu trแปฏ thรดng tin vแป sรกch trong cฦก sแป dแปฏ liแปu. Chรบng ta cรณ thแป tแบกo ra Book model
, ฤแปnh nghฤฉa cรกc field vร behavior cแปงa mแปt book object
. Sau ฤรณ, chรบng ta cรณ thแป tแบกo ra mแปt lแปp BookRepository
cung cแบฅp cรกc phฦฐฦกng thแปฉc ฤแป tแบกo, ฤแปc, cแบญp nhแบญt vร xรณa cรกc ฤแปi tฦฐแปฃng sรกch trong cฦก sแป dแปฏ liแปu.
Trong lแปp BookRepository
, chรบng ta cรณ thแป ฤแปnh nghฤฉa cรกc phฦฐฦกng thแปฉc nhฦฐ get_all_books
vร get_book_by_id
ฤแป lแบฅy cรกc ฤแปi tฦฐแปฃng sรกch tแปซ cฦก sแป dแปฏ liแปu. Chรบng ta cลฉng cรณ thแป ฤแปnh nghฤฉa cรกc phฦฐฦกng thแปฉc nhฦฐ create_book
vร update_book
ฤแป thรชm hoแบทc sแปญa ฤแปi cรกc book object
trong cฦก sแป dแปฏ liแปu.
Sแปญ dแปฅng mแบซu Repository vแปi cฦก sแป dแปฏ liแปu cรณ thแป mang lแบกi nhiแปu lแปฃi รญch, bao gแปm cแบฃi thiแปn khแบฃ nฤng kiแปm tra, bแบฃo trรฌ vร linh hoแบกt.
Bแบฑng cรกch trแปซu tฦฐแปฃng hรณa lแปp truy cแบญp cฦก sแป dแปฏ liแปu khแปi phแบงn cรฒn lแบกi cแปงa แปฉng dแปฅng, cรกc nhร phรกt triแปn cรณ thแป dแป dร ng chuyแปn ฤแปi giแปฏa cรกc cรดng nghแป cฦก sแป dแปฏ liแปu khรกc nhau hoแบทc thay ฤแปi lฦฐแปฃc ฤแป cฦก sแป dแปฏ liแปu mร khรดng แบฃnh hฦฐแปng ฤแบฟn phแบงn cรฒn lแบกi cแปงa แปฉng dแปฅng. Ngoร i ra, bแบฑng cรกch cung cแบฅp mแปt tแบญp hแปฃp cรกc phฦฐฦกng thแปฉc ฤแป tฦฐฦกng tรกc vแปi cฦก sแป dแปฏ liแปu, mแบซu Repository cรณ thแป giรบp viแปc viแบฟt cรกc bร i kiแปm tra cho แปฉng dแปฅng trแป nรชn dแป dร ng hฦกn.
// Define a Book interface that represents a book object
interface Book {
id: number;
title: string;
author: string;
publishedDate: Date;
}
// Define a BookRepository class that provides methods for interacting with a database of books
class BookRepository {
private db: any; // Database connection object
constructor(db: any) {
this.db = db;
}
// Get all books from the database
async getAllBooks(): Promise<Book[]> {
const result = await this.db.query('SELECT * FROM books');
return result.rows;
}
// Get a book by its ID
async getBookById(id: number): Promise<Book> {
const result = await this.db.query('SELECT * FROM books WHERE id = $1', [id]);
return result.rows[0];
}
// Create a new book in the database
async createBook(book: Book): Promise<void> {
await this.db.query('INSERT INTO books (title, author, published_date) VALUES ($1, $2, $3)', [book.title, book.author, book.publishedDate]);
}
// Update an existing book in the database
async updateBook(id: number, book: Book): Promise<void> {
await this.db.query('UPDATE books SET title = $1, author = $2, published_date = $3 WHERE id = $4', [book.title, book.author, book.publishedDate, id]);
}
// Delete a book from the database
async deleteBook(id: number): Promise<void> {
await this.db.query('DELETE FROM books WHERE id = $1', [id]);
}
}
// Example usage of the BookRepository class
const db = new Database(); // Instantiate a database connection object
const bookRepository = new BookRepository(db); // Instantiate a BookRepository object
const books = await bookRepository.getAllBooks(); // Get all books from the database
const book = await bookRepository.getBookById(1); // Get a book by its ID
const newBook = { title: 'New Book', author: 'Jane Doe', publishedDate: new Date() };
await bookRepository.createBook(newBook); // Create a new book in the database
await bookRepository.updateBook(1, { title: 'Updated Book', author: 'John Smith', publishedDate: new Date() }); // Update an existing book in the database
await bookRepository.deleteBook(1); // Delete a book from the database
Dependency Injection Pattern

Overview
Mแบซu Dependency Injection (DI) lร mแปt mแบซu thiแบฟt kแบฟ cho phรฉp tแบกo ra cรกc thร nh phแบงn phแบงn mแปm khรดng rร ng buแปc chแบทt chแบฝ. Nรณ ฤฦฐแปฃc sแปญ dแปฅng ฤแป giแบฃm bแปt sแปฑ rร ng buแปc giแปฏa cรกc thร nh phแบงn vร cแบฃi thiแปn tรญnh linh hoแบกt, khแบฃ nฤng kiแปm thแปญ vร khแบฃ nฤng bแบฃo trรฌ cแปงa mรฃ nguแปn.
Trong mแบซu Dependency Injection, cรกc phแปฅ thuแปc ฤฦฐแปฃc tiรชm vร o mแปt thร nh phแบงn thay vรฌ ฤฦฐแปฃc tแบกo trong thร nh phแบงn ฤรณ. ฤiแปu nร y cho phรฉp cรกc thร nh phแบงn ฤฦฐแปฃc tแบกo ra ฤแปc lแบญp vแปi cรกc phแปฅ thuแปc cแปงa chรบng, giรบp dแป dร ng thay thแบฟ hoแบทc sแปญa ฤแปi cรกc phแปฅ thuแปc mร khรดng แบฃnh hฦฐแปng ฤแบฟn thร nh phแบงn chรญnh.
Cรณ ba loแบกi chรญnh cแปงa Dependency Injection: Constructor Injection (Tiรชm qua hร m tแบกo), Property Injection (Tiรชm qua thuแปc tรญnh) vร Method Injection (Tiรชm qua phฦฐฦกng thแปฉc).
Constructor Injection liรชn quan ฤแบฟn viแปc truyแปn cรกc phแปฅ thuแปc vร o mแปt thร nh phแบงn thรดng qua hร m tแบกo cแปงa nรณ. Property Injection liรชn quan ฤแบฟn viแปc ฤแบทt cรกc phแปฅ thuแปc thรดng qua cรกc thuแปc tรญnh cรดng khai cแปงa thร nh phแบงn. Method Injection liรชn quan ฤแบฟn viแปc truyแปn cรกc phแปฅ thuแปc vร o cรกc phฦฐฦกng thแปฉc cแปงa thร nh phแบงn.
Mแปt trong nhแปฏng lแปฃi รญch chรญnh cแปงa viแปc sแปญ dแปฅng mแบซu Dependency Injection lร nรณ cแบฃi thiแปn khแบฃ nฤng kiแปm thแปญ cแปงa mรฃ nguแปn. Bแบฑng cรกch tiรชm cรกc phแปฅ thuแปc vร o mแปt thร nh phแบงn, ta cรณ thแป tแบกo cรกc bร i kiแปm tra ฤฦกn vแป (unit tests) cรด lแบญp thร nh phแบงn khแปi cรกc phแปฅ thuแปc cแปงa nรณ, giรบp dแป dร ng kiแปm thแปญ thร nh phแบงn ฤรณ mแปt cรกch ฤแปc lแบญp.
Mแปt lแปฃi รญch khรกc cแปงa viแปc sแปญ dแปฅng mแบซu Dependency Injection lร nรณ lร m mรฃ nguแปn linh hoแบกt vร dแป bแบฃo trรฌ hฦกn. Bแบฑng cรกch giแบฃm sแปฑ rร ng buแปc giแปฏa cรกc thร nh phแบงn, ta dแป dร ng sแปญa ฤแปi hoแบทc thay thแบฟ cรกc thร nh phแบงn mร khรดng แบฃnh hฦฐแปng ฤแบฟn phแบงn cรฒn lแบกi cแปงa แปฉng dแปฅng.
Tแปng quรกt, mแบซu Dependency Injection lร mแปt cรดng cแปฅ hแปฏu รญch ฤแป tแบกo ra cรกc hแป thแปng backend cรณ khแบฃ nฤng mแป rแปng, dแป bแบฃo trรฌ vร hiแปu quแบฃ. Nรณ giแบฃm sแปฑ rร ng buแปc giแปฏa cรกc thร nh phแบงn vร cแบฃi thiแปn tรญnh linh hoแบกt, khแบฃ nฤng kiแปm thแปญ vร khแบฃ nฤng bแบฃo trรฌ cแปงa mรฃ nguแปn.
Example of using the Dependency Injection pattern for decoupling dependencies
Trong ngแปฏ cแบฃnh phรกt triแปn backend, chรบng ta cรณ thแป sแปญ dแปฅng Dependency Injection ฤแป tรกch rแปi cรกc thร nh phแบงn cแปงa แปฉng dแปฅng khแปi viแปc triแปn khai cแปฅ thแป cแปงa cรกc dแปch vแปฅ hoแบทc thฦฐ viแปn bรชn ngoร i, chแบณng hแบกn nhฦฐ cฦก sแป dแปฏ liแปu, bแป nhแป cache hoแบทc nhร cung cแบฅp email. ฤiแปu nร y cho phรฉp chรบng ta dแป dร ng chuyแปn ฤแปi giแปฏa cรกc triแปn khai khรกc nhau cแปงa cรกc dแปch vแปฅ nร y hoแบทc tแบกo giแบฃ ฤแปi tฦฐแปฃng (mock) chรบng trong quรก trรฌnh kiแปm thแปญ.
Dฦฐแปi ฤรขy lร mแปt vรญ dแปฅ vแป viแปc sแปญ dแปฅng Dependency Injection trong mแปt แปฉng dแปฅng TypeScript tฦฐฦกng tรกc vแปi cฦก sแป dแปฏ liแปu:
// Define an interface for a database connection object
interface DatabaseConnection {
query(sql: string, params?: any[]): Promise<any>;
}
// Define a class for a PostgreSQL database connection
class PostgresConnection implements DatabaseConnection {
private client: any; // PostgreSQL client object
constructor() {
this.client = new PostgreSQLClient(); // Instantiate a PostgreSQL client object
this.client.connect(); // Connect to the database
}
async query(sql: string, params?: any[]): Promise<any> {
const result = await this.client.query(sql, params);
return result.rows;
}
}
// Define a class for a BookService that depends on a database connection
class BookService {
private db: DatabaseConnection; // Database connection object
constructor(db: DatabaseConnection) {
this.db = db;
}
async getAllBooks(): Promise<Book[]> {
const result = await this.db.query('SELECT * FROM books');
return result.map((row: any) => ({ id: row.id, title: row.title, author: row.author, publishedDate: row.published_date }));
}
async getBookById(id: number): Promise<Book> {
const result = await this.db.query('SELECT * FROM books WHERE id = $1', [id]);
return { id: result.id, title: result.title, author: result.author, publishedDate: result.published_date };
}
async createBook(book: Book): Promise<void> {
await this.db.query('INSERT INTO books (title, author, published_date) VALUES ($1, $2, $3)', [book.title, book.author, book.publishedDate]);
}
async updateBook(id: number, book: Book): Promise<void> {
await this.db.query('UPDATE books SET title = $1, author = $2, published_date = $3 WHERE id = $4', [book.title, book.author, book.publishedDate, id]);
}
async deleteBook(id: number): Promise<void> {
await this.db.query('DELETE FROM books WHERE id = $1', [id]);
}
}
// Example usage of the BookService class with a PostgresConnection object
const db = new PostgresConnection(); // Instantiate a PostgresConnection object
const bookService = new BookService(db); // Instantiate a BookService object with the PostgresConnection object as its dependency
const books = await bookService.getAllBooks(); // Get all books from the database
const book = await bookService.getBookById(1); // Get a book by its ID
const newBook = { title: 'New Book', author: 'Jane Doe', publishedDate: new Date() };
await bookService.createBook(newBook); // Create a new book in the database
await bookService.updateBook(1, { title: 'Updated Book', author: 'John Smith', publishedDate: new Date() }); //
Trong Spring Boot, DI lร viแปc cรกc Object nรชn phแปฅ thuแปc vร o cรกc abstract class vร instance chi tiแบฟt cแปงa nรณ sแบฝ ฤฦฐแปฃc Inject vร o ฤแปi tฦฐแปฃng lรบc runtime.
Observer Pattern

Overview
Mแบซu Observer lร mแปt mแบซu thiแบฟt kแบฟ cho phรฉp mแปt object (gแปi lร subject) thรดng bรกo cho cรกc object khรกc (gแปi lร observers) khi trแบกng thรกi cแปงa nรณ thay ฤแปi. Nรณ cung cแบฅp mแปt cรกch cho cรกc object giao tiแบฟp vแปi nhau mร khรดng cแบงn biแบฟt trแปฑc tiแบฟp sแปฑ tแปn tแบกi cแปงa nhau.
Trong mแบซu Observer, subject duy trรฌ mแปt danh sรกch cรกc observers vร thรดng bรกo cho chรบng khi trแบกng thรกi cแปงa nรณ thay ฤแปi. Cรกc observers sau ฤรณ cรณ thแป thแปฑc hiแปn hร nh ฤแปng dแปฑa trรชn sแปฑ thay ฤแปi trong trแบกng thรกi cแปงa subject. ฤiแปu nร y cho phรฉp mแปi quan hแป giแปฏa subject vร observers lร lแปng lแบปo, lร m cho viแปc sแปญa ฤแปi hoแบทc mแป rแปng hแป thแปng dแป dร ng hฦกn.
Mแปt trong nhแปฏng lแปฃi รญch chรญnh cแปงa viแปc sแปญ dแปฅng mแบซu Observer lร nรณ cแบฃi thiแปn tรญnh mรด-ฤun vร tรญnh linh hoแบกt cแปงa mรฃ nguแปn. Bแบฑng cรกch tรกch biแปt subject vร observers, ta cรณ thแป thรชm hoแบทc xรณa observers mร khรดng แบฃnh hฦฐแปng ฤแบฟn subject, hoแบทc thรชm cรกc subject mแปi mร khรดng แบฃnh hฦฐแปng ฤแบฟn observers hiแปn cรณ.
Mแปt lแปฃi รญch khรกc cแปงa viแปc sแปญ dแปฅng mแบซu Observer lร nรณ cรณ thแป cแบฃi thiแปn hiแปu suแบฅt cแปงa hแป thแปng. Bแบฑng cรกch thรดng bรกo chแป cho cรกc observers quan tรขm ฤแบฟn sแปฑ thay ฤแปi, ta cรณ thแป giแบฃm sแป lฦฐแปฃng thรดng bรกo vร cแบฃi thiแปn hiแปu suแบฅt tแปng thแป cแปงa hแป thแปng.
Example of using the Observer pattern for event-driven programming
Giแบฃ sแปญ chรบng ta cรณ mแปt แปฉng dแปฅng web cho phรฉp ngฦฐแปi dรนng ฤฤng kรฝ cรกc chแปง ฤแป quan tรขm khรกc nhau. Khi cรณ nแปi dung mแปi ฤฦฐแปฃc thรชm vร o chแปง ฤแป ฤรฃ ฤฤng kรฝ, ngฦฐแปi dรนng sแบฝ nhแบญn ฤฦฐแปฃc thรดng bรกo. Chรบng ta cรณ thแป triแปn khai tรญnh nฤng nร y bแบฑng cรกch sแปญ dแปฅng mแบซu Observer.
ฤแบงu tiรชn, chรบng ta ฤแปnh nghฤฉa giao diแปn subject Topic, sแบฝ thรดng bรกo cho cรกc observers (subscribers) vแป bแบฅt kแปณ cแบญp nhแบญt nร o:
interface Topic {
subscribe(observer: Observer): void;
unsubscribe(observer: Observer): void;
notify(): void;
}
Sau ฤรณ, chรบng ta triแปn khai giao diแปn Topic trong mแปt lแปp chแปง ฤแป cแปฅ thแป lร TopicManager, quแบฃn lรฝ mแปt danh sรกch cรกc ngฦฐแปi ฤฤng kรฝ vร thรดng bรกo cho hแป mแปi khi cรณ nแปi dung mแปi ฤฦฐแปฃc thรชm vร o:
class TopicManager implements Topic {
private subscribers: Observer[] = [];
public subscribe(observer: Observer): void {
this.subscribers.push(observer);
}
public unsubscribe(observer: Observer): void {
const index = this.subscribers.indexOf(observer);
if (index !== -1) {
this.subscribers.splice(index, 1);
}
}
public notify(): void {
for (const subscriber of this.subscribers) {
subscriber.update();
}
}
public addContent(topic: string, content: string): void {
// Add new content to the topic
// ...
// Notify all subscribers of the new content
this.notify();
}
}
Tiแบฟp theo, chรบng ta ฤแปnh nghฤฉa observer interface, cรณ 1 update method sแบฝ ฤฦฐแปฃc gแปi bแปi subject:
interface Observer {
update(): void;
}
Chรบng ta triแปn khai Observer interface trong concrete observer class, User, lแปp nร y sแบฝ nhแบญn ฤฦฐแปฃc thรดng bรกo khi nแปi dung mแปi ฤฦฐแปฃc thรชm vร o chแปง ฤแป ฤรฃ ฤฤng kรญ:
class User implements Observer {
private readonly username: string;
constructor(username: string) {
this.username = username;
}
public update(): void {
console.log(`[${this.username}] New content has been added to a subscribed topic`);
}
}
Cuแปi cรนng, chรบng ta cรณ thแป sแปญ dแปฅng TopicManager
and User
classes ฤแป triแปn khai features ฤฤng kรฝ:
// Create a new topic manager
const topicManager = new TopicManager();
// Create two users
const user1 = new User("Alice");
const user2 = new User("Bob");
// Subscribe the users to a topic
topicManager.subscribe(user1);
topicManager.subscribe(user2);
// Add new content to the topic
topicManager.addContent("science", "New scientific discovery!");
// Output:
// [Alice] New content has been added to a subscribed topic
// [Bob] New content has been added to a subscribed topic
Trong vรญ dแปฅ nร y, TopicManager
ฤรณng vai trรฒ lร chแปง ฤแป (subject) vร lแปp User ฤรณng vai trรฒ lร ngฦฐแปi quan sรกt (observer).
TopicManager
duy trรฌ mแปt danh sรกch cรกc ngฦฐแปi ฤฤng kรฝ (subscribers) vร thรดng bรกo cho hแป mแปi khi cรณ nแปi dung mแปi ฤฦฐแปฃc thรชm vร o chแปง ฤแป mร hแป ฤรฃ ฤฤng kรฝ. Lแปp User nhแบญn thรดng bรกo vร thแปฑc hiแปn mแปt sแป hร nh ฤแปng, chแบณng hแบกn nhฦฐ hiแปn thแป thรดng bรกo cho ngฦฐแปi dรนng.
Mรด hรฌnh Observer cho phรฉp chรบng ta tรกch rแปi chแปง ฤแป vร ngฦฐแปi quan sรกt, giรบp dแป dร ng thรชm hoแบทc xรณa cรกc ngฦฐแปi ฤฤng kรฝ mร khรดng แบฃnh hฦฐแปng ฤแบฟn phแบงn cรฒn lแบกi cแปงa hแป thแปng.
Decorator Pattern
Mรด hรฌnh Decorator lร mแปt mรด hรฌnh thiแบฟt kแบฟ cho phรฉp thรชm hร nh vi vร o mแปt ฤแปi tฦฐแปฃng cรก nhรขn, cแบฃ tฤฉnh vร ฤแปng, mร khรดng แบฃnh hฦฐแปng ฤแบฟn hร nh vi cแปงa cรกc ฤแปi tฦฐแปฃng khรกc cรนng lแปp. Nรณ ฤฦฐแปฃc sแปญ dแปฅng ฤแป thรชm chแปฉc nฤng vร o cรกc ฤแปi tฦฐแปฃng trong thแปi gian chแบกy, thay vรฌ thแปi gian biรชn dแปch.
Trong mรด hรฌnh Decorator, mแปt lแปp decorator ฤฦฐแปฃc sแปญ dแปฅng ฤแป bao bแปc ฤแปi tฦฐแปฃng gแปc. Lแปp decorator cรณ cรนng giao diแปn vแปi ฤแปi tฦฐแปฃng gแปc, cho phรฉp sแปญ dแปฅng nรณ theo cรนng cรกch. Lแปp decorator sau ฤรณ thรชm hร nh vi vร o ฤแปi tฦฐแปฃng gแปc bแบฑng cรกch chuyแปn giao mแปt phแบงn cรดng viแปc cho ฤแปi tฦฐแปฃng ฤฦฐแปฃc bao bแปc vร thรชm hร nh vi riรชng cแปงa mรฌnh.
Mแปt trong nhแปฏng lแปฃi รญch chรญnh cแปงa viแปc sแปญ dแปฅng mรด hรฌnh Decorator lร cho phรฉp thรชm chแปฉc nฤng vร o cรกc ฤแปi tฦฐแปฃng mแปt cรกch ฤแปng. ฤiแปu nร y cรณ thแป hแปฏu รญch trong nhแปฏng tรฌnh huแปng mร hร nh vi cแปงa mแปt ฤแปi tฦฐแปฃng cแบงn ฤฦฐแปฃc thay ฤแปi trong thแปi gian chแบกy, hoแบทc khi hร nh vi cแปงa mแปt ฤแปi tฦฐแปฃng cแบงn ฤฦฐแปฃc mแป rแปng mร khรดng thay ฤแปi giao diแปn cแปงa nรณ.
Lแปฃi รญch khรกc cแปงa viแปc sแปญ dแปฅng mรด hรฌnh Decorator lร nรณ cรณ thแป cแบฃi thiแปn khแบฃ nฤng bแบฃo trรฌ cแปงa mรฃ nguแปn. Vรฌ hร nh vi cแปงa ฤแปi tฦฐแปฃng ฤฦฐแปฃc phรขn tรกch thร nh cรกc decorator riรชng lแบป, nรชn dแป dร ng chแปnh sแปญa hoแบทc mแป rแปng hร nh vi cแปงa ฤแปi tฦฐแปฃng mร khรดng แบฃnh hฦฐแปng ฤแบฟn cรกc phแบงn khรกc cแปงa hแป thแปng.
Tแปng thแป, mรด hรฌnh Decorator lร mแปt cรดng cแปฅ hแปฏu รญch ฤแป tแบกo ra cรกc hแป thแปng backend cรณ khแบฃ nฤng mแป rแปng, dแป bแบฃo trรฌ vร hiแปu quแบฃ. Nรณ cho phรฉp thรชm chแปฉc nฤng vร o cรกc ฤแปi tฦฐแปฃng mแปt cรกch ฤแปng, cแบฃi thiแปn tรญnh linh hoแบกt vร khแบฃ nฤng bแบฃo trรฌ cแปงa mรฃ nguแปn.
Example of using the Decorator pattern for adding functionality to a class dynamically
Giแบฃ sแปญ chรบng ta cรณ 1 class Car ฤแบกi diแปn cho 1 basic car vแปi cรกc properties and methods:
class Car {
private make: string;
private model: string;
private year: number;
private price: number;
constructor(make: string, model: string, year: number, price: number) {
this.make = make;
this.model = model;
this.year = year;
this.price = price;
}
public getMake(): string {
return this.make;
}
public getModel(): string {
return this.model;
}
public getYear(): number {
return this.year;
}
public getPrice(): number {
return this.price;
}
}
Chรบng ta sแปญ dแปฅng mรด hรฌnh Decorator ฤแป thรชm cรกc chแปฉc nฤng bแป sung vร o lแปp Car, chแบณng hแบกn nhฦฐ tรญnh toรกn thuแบฟ bรกn hร ng trรชn giรก xe vร thรชm mแปt sแป tรญnh nฤng tรนy chแปn cho xe, nhฦฐ hแป thแปng ฤแปnh vแป vร cแปญa sแป trแปi. Chรบng ta cรณ thแป thรชm cรกc tรญnh nฤng nร y vร o lแปp Car mแปt cรกch ฤแปng bแบฑng cรกch sแปญ dแปฅng mรด hรฌnh Decorator.
ฤแบงu tiรชn, chรบng ta ฤแปnh nghฤฉa mแปt lแปp cฦก sแป trแปซu tฦฐแปฃng CarFeature mร tแบฅt cแบฃ cรกc decorator sแบฝ kแบฟ thแปซa tแปซ ฤรณ:
abstract class CarFeature extends Car {
protected car: Car;
constructor(car: Car) {
super(car.getMake(), car.getModel(), car.getYear(), car.getPrice());
this.car = car;
}
public abstract getPrice(): number;
}
Tiแบฟp theo, chรบng ta triแปn khai cรกc concrete decorator class ฤแป thรชm cรกc freatures mong muแปn cho lแปp car:
class SalesTaxDecorator extends CarFeature {
public getPrice(): number {
return this.car.getPrice() * 1.10; // 10% sales tax
}
}
class NavigationDecorator extends CarFeature {
public getPrice(): number {
return this.car.getPrice() + 1500; // add $1500 for navigation system
}
}
class SunroofDecorator extends CarFeature {
public getPrice(): number {
return this.car.getPrice() + 1000; // add $1000 for sunroof
}
}
Sau ฤรณ, chรบng ta dรนng decorators nร y ฤแป thรชm functionally vร o lแปp car 1 cรกch dynamically:
// Create a basic car
const car = new Car("Honda", "Accord", 2022, 25000);
// Add sales tax to the car
const carWithSalesTax = new SalesTaxDecorator(car);
// Add a navigation system to the car
const carWithNavigation = new NavigationDecorator(carWithSalesTax);
// Add a sunroof to the car
const carWithSunroof = new SunroofDecorator(carWithNavigation);
console.log(`Make: ${carWithSunroof.getMake()}`);
console.log(`Model: ${carWithSunroof.getModel()}`);
console.log(`Year: ${carWithSunroof.getYear()}`);
console.log(`Price: ${carWithSunroof.getPrice()}`);
// Output:
// Make: Honda
// Model: Accord
// Year: 2022
// Price: 28750
Trong vรญ dแปฅ nร y, chรบng ta sแปญ dแปฅng mรด hรฌnh Decorator ฤแป thรชm chแปฉc nฤng vร o mแปt ฤแปi tฦฐแปฃng Car mแปt cรกch ฤแปng. Mแปi decorator kแบฟ thแปซa tแปซ lแปp trแปซu tฦฐแปฃng CarFeature vร thรชm mแปt sแป chแปฉc nฤng bแป sung vร o ฤแปi tฦฐแปฃng Car.
Chรบng ta cรณ thแป thรชm nhiแปu decorator vร o mแปt ฤแปi tฦฐแปฃng Car theo bแบฅt kแปณ thแปฉ tแปฑ nร o vร mแปi decorator ฤแปu thรชm chแปฉc nฤng riรชng cแปงa nรณ vร o ฤแปi tฦฐแปฃng. ฤiแปu nร y cho phรฉp chรบng ta tแบกo ra cรกc ฤแปi tฦฐแปฃng Car ฤฦฐแปฃc tรนy chแปnh cao vแปi chแป cรกc tรญnh nฤng chรบng ta cแบงn, trong khi vแบซn giแปฏ cho lแปp Car cแปt lรตi ฤฦกn giแบฃn vร dแป bแบฃo trรฌ.
Last updated