Menu
CoddyTech

Mẫu phương thức khuôn mẫu

Thuộc phần Lập trình hướng đối tượng trong hành trình C# của Coddy. Bài học 59 trên 70.

Mẫu thiết kế Template Method là một mẫu thiết kế hành vi, xác định khung của một thuật toán trong lớp cơ sở, cho phép các lớp con ghi đè những bước cụ thể mà không làm thay đổi cấu trúc tổng thể. Lớp cơ sở kiểm soát quy trình, còn các lớp dẫn xuất tùy chỉnh từng phần.

Mẫu này sử dụng tính kế thừa và các phương thức trừu tượng. Lớp cơ sở chứa một “phương thức khuôn mẫu” gọi một chuỗi bước, trong đó một số bước là trừu tượng và các lớp con phải triển khai:

public abstract class DataProcessor
{
    // Phương thức mẫu (template method): xác định cấu trúc thuật toán (algorithm)
    public void Process()
    {
        ReadData();
        ProcessData();
        SaveData();
    }
    
    protected abstract void ReadData();
    protected abstract void ProcessData();
    protected virtual void SaveData() => Console.WriteLine("Saving to default location");
}

public class CsvProcessor : DataProcessor
{
    protected override void ReadData() => Console.WriteLine("Reading CSV file");
    protected override void ProcessData() => Console.WriteLine("Parsing CSV data");
}

public class JsonProcessor : DataProcessor
{
    protected override void ReadData() => Console.WriteLine("Reading JSON file");
    protected override void ProcessData() => Console.WriteLine("Parsing JSON data");
    protected override void SaveData() => Console.WriteLine("Saving to cloud");
}

Mỗi lớp con cung cấp cách triển khai riêng, còn lớp cơ sở quy định thứ tự thực hiện:

DataProcessor csv = new CsvProcessor();
csv.Process();
// Đọc tệp CSV
// Phân tích dữ liệu CSV
// Lưu vào vị trí mặc định

DataProcessor json = new JsonProcessor();
json.Process();
// Đọc tệp JSON
// Phân tích dữ liệu JSON
// Lưu lên đám mây

Mẫu Template Method phù hợp khi nhiều lớp dùng chung cấu trúc thuật toán (algorithm) nhưng khác nhau ở một số bước cụ thể. Mẫu này giúp tái sử dụng code bằng cách đặt logic chung trong lớp cơ sở, đồng thời vẫn linh hoạt nhờ các phương thức (methods) có thể ghi đè.

challenge icon

Thử thách

Dễ

Hãy xây dựng một hệ thống tạo báo cáo bằng mẫu thiết kế Template Method. Các loại báo cáo khác nhau, chẳng hạn như báo cáo doanh số và báo cáo tồn kho, có cùng cấu trúc tổng thể: tất cả đều cần thu thập dữ liệu, định dạng dữ liệu và xuất kết quả, nhưng mỗi loại báo cáo xử lý các bước này theo cách khác nhau.

Bạn sẽ sắp xếp code trong ba tệp:

  • ReportGenerator.cs: Tạo lớp trừu tượng ReportGenerator trong không gian tên Reporting. Lớp cơ sở này định nghĩa khung của thuật toán tạo báo cáo thông qua một phương thức khuôn mẫu có tên Generate(). Phương thức này cần gọi lần lượt ba bước: GatherData(), FormatReport() và OutputReport(). Đặt GatherData() và FormatReport() thành phương thức trừu tượng, vì mỗi loại báo cáo sẽ triển khai chúng theo cách khác nhau, còn OutputReport() là phương thức ảo có phần triển khai mặc định để in ra Sending to default printer.
  • ConcreteReports.cs: Tạo hai lớp báo cáo cụ thể trong cùng không gian tên, kế thừa từ ReportGenerator:
    • SalesReport: triển khai GatherData() để in ra Collecting sales data from database và FormatReport() để in ra Formatting as sales summary
    • InventoryReport: triển khai GatherData() để in ra Scanning warehouse inventory, FormatReport() để in ra Formatting as inventory list và ghi đè OutputReport() để in ra Sending to warehouse manager
  • Program.cs: Kết hợp mọi thứ bằng cách tạo các đối tượng báo cáo và tạo báo cáo. Phương thức khuôn mẫu đảm bảo mỗi báo cáo tuân theo cùng một quy trình ba bước, nhưng cách thực hiện cụ thể của mỗi bước sẽ thay đổi tùy theo loại báo cáo.

Bạn sẽ nhận một đầu vào:

  • Loại báo cáo: sales hoặc inventory

Dựa trên đầu vào, hãy tạo bộ tạo báo cáo phù hợp và gọi phương thức Generate() của nó.

Ví dụ, nếu đầu vào là sales, đầu ra sẽ là:

Collecting sales data from database
Formatting as sales summary
Sending to default printer

Nếu đầu vào là inventory, đầu ra sẽ là:

Scanning warehouse inventory
Formatting as inventory list
Sending to warehouse manager

Hãy lưu ý rằng cả hai báo cáo đều tuân theo cùng một cấu trúc thuật toán chính xác: thu thập, định dạng, xuất, nhưng phần triển khai của từng bước được tùy chỉnh. SalesReport dùng hành vi xuất mặc định, còn InventoryReport ghi đè hành vi đó. Điều này cho thấy mẫu thiết kế Template Method giúp bạn kiểm soát những bước nào bắt buộc phải ghi đè và những bước nào có thể tùy chỉnh!

Tự làm thử

using System;
using Reporting;

class Program
{
    public static void Main(string[] args)
    {
        string reportType = Console.ReadLine();
        
        // TODO: Tạo đối tượng tạo báo cáo phù hợp dựa trên reportType
        // Nếu reportType là "sales", tạo một SalesReport
        // Nếu reportType là "inventory", tạo một InventoryReport
        // Sau đó gọi phương thức (method) Generate() trên đối tượng báo cáo
        
    }
}
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Trình biên dịch C# online