TungDaDev's Blog

abstract factory pattern

Abstract pattern.webp
Published on
/8 mins read/

Nhiều bài giảng giới thiệu Abstract Factory bằng ví dụ vẽ giao diện Light Theme vs Dark Theme (Button, Checkbox). Nhưng trong thế giới kiến trúc phần mềm thực chiến, hiếm khi một backend engineer phải viết UI Button. Nơi mà Abstract Factory phát huy sức mạnh tối thượng chính là trong các bài toán Kiến trúc Đa Đám Mây (Multi-Cloud Architecture): Làm thế nào để một ứng dụng lõi (Core Business) có thể triển khai trên AWS, GCP, hoặc On-Premise Data Center mà không bị khóa chặt vào SDK độc quyền của bất kỳ nhà cung cấp nào (Vendor Lock-in)?

Nếu ứng dụng của bạn trực tiếp gọi AmazonS3Client, AmazonSQSAsync hay AWSSecretsManager rải rác khắp hàng trăm Service classes, thì khi Ban Giám Đốc quyết định chuyển sang Google Cloud (để nhận gói tài trợ triệu USD) hoặc yêu cầu triển khai On-Premise cho khách hàng chính phủ, toàn bộ dự án sẽ rơi vào bế tắc với chi phí viết lại mã nguồn khổng lồ.

Bài viết này phân tích chi tiết cách áp dụng Abstract Factory Pattern để kiến tạo một tầng Hạ tầng đám mây trừu tượng (Cloud Infrastructure Abstraction Layer) chuẩn production.


# bản chất kiến trúc: gia đình sản phẩm tương thích (family of products)

Khác với Factory Method chỉ chịu trách nhiệm tạo một đối tượng đơn lẻ, Abstract Factory cung cấp một giao diện trừu tượng để tạo ra một "Gia đình" các đối tượng có quan hệ mật thiết với nhau:

# tại sao phải gom thành một "gia đình"?

  1. Đảm bảo tính nhất quán (Consistency): Nếu ứng dụng đang chạy trên AWS, toàn bộ các thành phần (Lưu trữ file, Bắn message, Lấy mật khẩu) bắt buộc phải cùng thuộc hạ tầng AWS để tận dụng mạng nội bộ (AWS VPC), IAM Roles và giảm thiểu chi phí truyền dữ liệu ra ngoài (Data Egress Cost).
  2. Ngăn chặn xung đột chéo: Không thể có chuyện ứng dụng lưu file vào AWS S3 nhưng lại dùng cơ chế IAM của Google Cloud để phân quyền. Abstract Factory ép buộc tính đồng bộ 100% của hệ sinh thái.

# thiết kế tầng trừu tượng hóa đám mây (cloud abstraction interfaces)

Đầu tiên, định nghĩa các bản giao kèo trừu tượng (Contracts) mà tầng nghiệp vụ yêu cầu:

// 1. Quản lý lưu trữ đối tượng nhị phân (Object / Blob Storage)
public interface BlobStorage {
    void upload(String bucketName, String objectKey, byte[] data);
    byte[] download(String bucketName, String objectKey);
}
 
// 2. Hàng đợi thông điệp bất đồng bộ (Message Queue)
public interface MessageQueue {
    void publish(String topicOrQueue, String payload);
    void subscribe(String topicOrQueue, Consumer<String> handler);
}
 
// 3. Quản lý bí mật và mật khẩu (Secrets Management)
public interface SecretManager {
    String getSecret(String secretName);
}

Định nghĩa Abstract Factory Interface:

public interface CloudInfrastructureFactory {
    BlobStorage createBlobStorage();
    MessageQueue createMessageQueue();
    SecretManager createSecretManager();
}

# hiện thực hóa cho AWS vs google cloud (GCP)

# concrete Factory cho hệ sinh thái AWS

public class AwsInfrastructureFactory implements CloudInfrastructureFactory {
 
    private final AwsCredentialsProvider credentialsProvider;
    private final Region region;
 
    public AwsInfrastructureFactory(AwsCredentialsProvider credentialsProvider, Region region) {
        this.credentialsProvider = credentialsProvider;
        this.region = region;
    }
 
    @Override
    public BlobStorage createBlobStorage() {
        S3Client s3Client = S3Client.builder()
            .region(region)
            .credentialsProvider(credentialsProvider)
            .build();
        return new AwsS3BlobStorage(s3Client);
    }
 
    @Override
    public MessageQueue createMessageQueue() {
        SqsClient sqsClient = SqsClient.builder()
            .region(region)
            .credentialsProvider(credentialsProvider)
            .build();
        return new AwsSqsMessageQueue(sqsClient);
    }
 
    @Override
    public SecretManager createSecretManager() {
        SecretsManagerClient smClient = SecretsManagerClient.builder()
            .region(region)
            .credentialsProvider(credentialsProvider)
            .build();
        return new AwsSecretManagerImpl(smClient);
    }
}

# concrete Factory cho hệ sinh thái google cloud (GCP)

public class GcpInfrastructureFactory implements CloudInfrastructureFactory {
 
    private final GoogleCredentials credentials;
    private final String projectId;
 
    public GcpInfrastructureFactory(GoogleCredentials credentials, String projectId) {
        this.credentials = credentials;
        this.projectId = projectId;
    }
 
    @Override
    public BlobStorage createBlobStorage() {
        Storage storage = StorageOptions.newBuilder()
            .setCredentials(credentials)
            .setProjectId(projectId)
            .build()
            .getService();
        return new GcpBlobStorage(storage);
    }
 
    @Override
    public MessageQueue createMessageQueue() {
        // Khởi tạo Publisher / Subscriber của Google Cloud Pub/Sub
        return new GcpPubSubQueue(projectId, credentials);
    }
 
    @Override
    public SecretManager createSecretManager() {
        // Khởi tạo GCP Secret Manager Client
        return new GcpSecretManagerImpl(projectId, credentials);
    }
}

# tích hợp vào Spring Boot: kích hoạt động theo cấu hình

Thay vì khởi tạo Factory bằng tay, trong kiến trúc Spring Boot hiện đại, chúng ta kết hợp Abstract Factory với @ConditionalOnProperty:

@Configuration
public class CloudInfrastructureConfiguration {
 
    @Bean
    @ConditionalOnProperty(name = "cloud.provider", havingValue = "aws")
    public CloudInfrastructureFactory awsInfrastructureFactory(
            @Value("${cloud.aws.region:ap-southeast-1}") String regionStr) {
        return new AwsInfrastructureFactory(DefaultCredentialsProvider.create(), Region.of(regionStr));
    }
 
    @Bean
    @ConditionalOnProperty(name = "cloud.provider", havingValue = "gcp")
    public CloudInfrastructureFactory gcpInfrastructureFactory(
            @Value("${cloud.gcp.project-id}") String projectId) throws IOException {
        return new GcpInfrastructureFactory(GoogleCredentials.getApplicationDefault(), projectId);
    }
 
    // Tự động phân phối các Beans thành phần cho toàn bộ hệ thống
    @Bean
    public BlobStorage blobStorage(CloudInfrastructureFactory factory) {
        return factory.createBlobStorage();
    }
 
    @Bean
    public MessageQueue messageQueue(CloudInfrastructureFactory factory) {
        return factory.createMessageQueue();
    }
 
    @Bean
    public SecretManager secretManager(CloudInfrastructureFactory factory) {
        return factory.createSecretManager();
    }
}

# sử dụng tại tầng nghiệp vụ: 100% độc lập với đám mây!

@Service
public class DocumentManagementService {
 
    private final BlobStorage blobStorage;
    private final MessageQueue messageQueue;
 
    public DocumentManagementService(BlobStorage blobStorage, MessageQueue messageQueue) {
        this.blobStorage = blobStorage;
        this.messageQueue = messageQueue;
    }
 
    public void processInvoice(String invoiceId, byte[] pdfData) {
        // Lưu trữ file: Chạy trên AWS sẽ vào S3, chạy trên GCP sẽ vào Google Cloud Storage
        blobStorage.upload("company-invoices", invoiceId + ".pdf", pdfData);
 
        // Bắn sự kiện: Chạy trên AWS sẽ vào SQS, chạy trên GCP sẽ vào Pub/Sub
        messageQueue.publish("invoice-processed-events", "{\"invoiceId\":\"" + invoiceId + "\"}");
    }
}

# thách thức kiến trúc: bài toán "mẫu số chung nhỏ nhất" (lowest common denominator)

Không có giải pháp nào là hoàn hảo. Khi áp dụng Abstract Factory để che giấu hạ tầng đám mây, Kiến trúc sư Giải pháp phải đối mặt với Nghịch lý Mẫu số chung nhỏ nhất:

# đánh đổi thực tế

  • Mất đi tính năng độc quyền: Nếu bạn trừu tượng hóa S3 và GCS thành một interface BlobStorage chung, bạn sẽ không thể tận dụng được các tính năng độc quyền cao cấp (như S3 Glacier Instant Retrieval hay GCP Turbo Replication) mà không làm rách giao diện trừu tượng.
  • Chi phí duy trì: Đội ngũ Platform phải tự duy trì và kiểm thử các lớp Adapter cho từng Cloud Provider mỗi khi SDK của họ nâng cấp phiên bản.

Quyết định của Solution Architect: Chỉ áp dụng Abstract Factory cho các dịch vụ cốt lõi có sự tương đồng lớn (Object Storage, Message Queues, RDBMS). Đối với các dịch vụ chuyên biệt (như BigQuery của Google hay Amazon Bedrock AI của AWS), hãy giữ nguyên kết nối trực tiếp thay vì cố gắng trừu tượng hóa một cách gượng ép.


# bảng kiểm tra sẵn sàng vận hành (architect's checklist)

  • 1. Kiểm Tra Rò Rỉ Dependency: Đảm bảo module domain-core tuyệt đối không import bất kỳ package nào của software.amazon.awssdk hay com.google.cloud. Toàn bộ dependencies đám mây phải nằm trong module infrastructure.
  • 2. Hỗ Trợ Local Mock Factory: Xây dựng một LocalStorageFactory (lưu file vào ổ cứng cục bộ và dùng hàng đợi bộ nhớ LinkedBlockingQueue) để lập trình viên có thể chạy và Unit Test mà không cần tài khoản Cloud thật.
  • 3. Thống Nhất Quy Ước Error Handling: Các exception riêng biệt của AWS (S3Exception) và GCP (StorageException) phải được các Concrete Factories bọc lại thành các Domain Exceptions chuẩn hóa (ví dụ: StorageUnavailableException).
  • 4. Quản Lý Connection Lifecycle: Đảm bảo các Client tạo ra bởi Factory (S3Client, PubSub) được đăng ký đóng kết nối an toàn (close() / @PreDestroy) khi ứng dụng tắt.
  • 5. Giám Sát Cloud Metrics Độc Lập: Gắn Micrometer Tags xác định rõ cloud_provider: "aws" hoặc cloud_provider: "gcp" để theo dõi độ trễ SLA của từng đám mây trên Grafana.

# lời kết

Abstract Factory Pattern không sinh ra để vẽ các nút bấm UI. Khi được đặt vào tay của một Kiến trúc sư Hệ thống, nó trở thành chiếc khiên bảo vệ doanh nghiệp khỏi nguy cơ Vendor Lock-in hàng triệu USD, cho phép hệ thống phần mềm tự do di chuyển linh hoạt giữa các đám mây toàn cầu.

Bằng cách phân tách rạch ròi giữa Bản giao kèo nghiệp vụ và Cơ chế triển khai hạ tầng, bạn đang xây dựng một nền tảng phần mềm có khả năng thích ứng bền bỉ trước mọi biến động về công nghệ và chiến lược kinh doanh của doanh nghiệp.


Chỉ là những ghi chép cá nhân với hy vọng mang lại chút giá trị. Nếu thấy hữu ích, đừng ngại chia sẻ cho bạn bè & đồng nghiệp nhé!

Happy coding 😎 👍🏻 🚀 🔥.

← Previous postdecorator pattern
Next post →facade pattern