Menu
CoddyTech

Mẫu Abstract Factory

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

Mẫu Abstract Factory mở rộng mẫu Factory bằng cách tạo ra các nhóm đối tượng có liên quan mà không chỉ định kiểu cụ thể của chúng. Thay vì dùng một hàm factory duy nhất, bạn định nghĩa một giao diện factory để nhiều factory cụ thể triển khai, mỗi factory tạo ra một bộ đối tượng có liên quan nhất quán.

Hãy xem xét một bộ công cụ giao diện người dùng cần tạo nút và hộp kiểm. Mỗi hệ điều hành cần cách triển khai khác nhau, nhưng các thành phần phải hoạt động nhất quán với nhau:

type Button interface {
    Render() string
}

type Checkbox interface {
    Check() string
}

// Giao diện nhà máy trừu tượng
type GUIFactory interface {
    CreateButton() Button
    CreateCheckbox() Checkbox
}

Mỗi nhà máy cụ thể tạo ra một họ các thành phần có liên quan:

// Họ Windows
type WindowsButton struct{}
func (w WindowsButton) Render() string { return "Windows Button" }

type WindowsCheckbox struct{}
func (w WindowsCheckbox) Check() string { return "Windows Checkbox" }

type WindowsFactory struct{}
func (w WindowsFactory) CreateButton() Button { return WindowsButton{} }
func (w WindowsFactory) CreateCheckbox() Checkbox { return WindowsCheckbox{} }

// Họ Mac
type MacButton struct{}
func (m MacButton) Render() string { return "Mac Button" }

type MacCheckbox struct{}
func (m MacCheckbox) Check() string { return "Mac Checkbox" }

type MacFactory struct{}
func (m MacFactory) CreateButton() Button { return MacButton{} }
func (m MacFactory) CreateCheckbox() Checkbox { return MacCheckbox{} }

Code phía máy khách làm việc với giao diện factory và không phụ thuộc vào các cách triển khai cụ thể:

func BuildUI(factory GUIFactory) {
    button := factory.CreateButton()
    checkbox := factory.CreateCheckbox()
    fmt.Println(button.Render(), checkbox.Check())
}

Hãy dùng Abstract Factory khi hệ thống của bạn cần làm việc với nhiều họ sản phẩm liên quan và bạn muốn đảm bảo các thành phần thuộc cùng một họ được dùng cùng nhau. Mẫu này phức tạp hơn Factory đơn giản, vì vậy chỉ dùng khi bạn thực sự cần quản lý các họ sản phẩm.

challenge icon

Thử thách

Dễ

Hãy xây dựng hệ thống cửa hàng nội thất bằng mẫu Abstract Factory! Bạn sẽ tạo các nhà máy sản xuất những nhóm đồ nội thất có liên quan: mỗi nhà máy tạo ra một phong cách nhất quán (Modern hoặc Vintage), đảm bảo ghế và bàn từ cùng một nhà máy có vẻ ngoài hài hòa.

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

  • furniture.go: Định nghĩa các giao diện sản phẩm và các kiểu đồ nội thất cụ thể.

    Tạo hai giao diện sản phẩm:

    • Chair với phương thức SitOn() string
    • Table với phương thức PlaceItems() string

    Triển khai hai nhóm đồ nội thất:

    • Nhóm Modern: ModernChair trả về Sitting on a sleek modern chair và ModernTable trả về Placing items on a glass modern table
    • Nhóm Vintage: VintageChair trả về Sitting on an ornate vintage chair và VintageTable trả về Placing items on a wooden vintage table
  • factory.go: Định nghĩa giao diện nhà máy trừu tượng và các nhà máy cụ thể.

    Tạo giao diện FurnitureFactory với hai phương thức:

    • CreateChair() Chair
    • CreateTable() Table

    Triển khai hai nhà máy cụ thể:

    • ModernFactory tạo ra ModernChair và ModernTable
    • VintageFactory tạo ra VintageChair và VintageTable

    Đồng thời, tạo hàm GetFactory(style string) FurnitureFactory trả về nhà máy phù hợp dựa trên phong cách (modern hoặc vintage). Mặc định trả về ModernFactory nếu không nhận diện được phong cách.

  • main.go: Dùng các nhà máy để trang bị nội thất cho phòng.

    Tạo hàm FurnishRoom(factory FurnitureFactory) string dùng nhà máy để tạo một chiếc ghế và một chiếc bàn, sau đó trả về chuỗi đã định dạng, hiển thị hai hành động trên các dòng riêng biệt.

    Đọc đầu vào về phong cách, lấy nhà máy phù hợp, trang bị nội thất cho phòng và in ra kết quả.

Các đầu vào sau sẽ được cung cấp:

  • Dòng 1: Phong cách nội thất (modern, vintage hoặc một giá trị khác)

Ví dụ, với đầu vào:

modern

Kết quả đầu ra sẽ là:

Sitting on a sleek modern chair
Placing items on a glass modern table

Với đầu vào:

vintage

Kết quả đầu ra sẽ là:

Sitting on an ornate vintage chair
Placing items on a wooden vintage table

Với đầu vào:

rustic

Kết quả đầu ra sẽ là:

Sitting on a sleek modern chair
Placing items on a glass modern table

Lưu ý rằng hàm FurnishRoom có thể làm việc với mọi nhà máy thông qua giao diện. Hàm không biết mình đang tạo đồ nội thất Modern hay Vintage. Nhờ vậy, mọi món đồ nội thất trong phòng đều đến từ cùng một nhóm, giữ cho phong cách nhất quán!

Tự làm thử

package main

import "fmt"

// FurnishRoom dùng bộ tạo để tạo đồ nội thất và trả về kết quả
// TODO: Triển khai hàm (function) này
// Dùng bộ tạo để tạo một chiếc ghế và một chiếc bàn
// Trả về chuỗi có kết quả SitOn() ở dòng đầu và kết quả PlaceItems() ở dòng thứ hai
func FurnishRoom(factory FurnitureFactory) string {
	// TODO: Dùng bộ tạo để tạo ghế và bàn
	// TODO: Trả về chuỗi đã định dạng, mỗi hành động trên một dòng riêng
	return ""
}

func main() {
	var style string
	fmt.Scanln(&style)

	// TODO: Chọn bộ tạo phù hợp dựa trên style
	// TODO: Dùng bộ tạo để trang bị đồ nội thất cho một căn phòng
	// TODO: In ra kết quả
}
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 Go online