Nội dung
Factory Method là một mẫu thiết kế khởi tạo giải quyết vấn đề tạo ra các đối tượng mà không chỉ định các lớp cụ thể của chúng. Factory Method định nghĩa một phương thức, phương thức này sẽ được sử dụng để tạo các đối tượng thay vì gọi hàm tạo trực tiếp (toán tử new). Các lớp con có thể ghi đè phương thức này để thay đổi kiểu lớp cho đối tượng sẽ được tạo.
Cách sử dụng mẫu trong C++
Sử dụng: Mẫu Factory Method được sử dụng rộng rãi trong mã C++. Nó rất hữu ích khi bạn cần cung cấp mức độ linh hoạt cao cho mã của mình.
Nhận biết: Các phương thức factory có thể nhận biết bởi các phương thức khởi tạo, phương thức này tạo ra các đối tượng từ các lớp cụ thể, nhưng trả về chúng dưới dạng các đối tượng thuộc kiểu trừu tượng hoặc interface.
Chương trình minh họa
Ví dụ này minh họa cấu trúc của mẫu thiết kế Factory Method. Nó tập trung vào việc trả lời những câu hỏi sau:
- Nó bao gồm những lớp nào?
- Các lớp này có vai trò gì?
- Các thành phần của mẫu có liên quan với nhau theo cách nào?
main.cpp
/**
* Interface Product khai báo các phương thức mà tất cả các concrete product phải hiện thực.
*/
class Product {
public:
virtual ~Product() {}
virtual std::string Operation() const = 0;
};
/**
* Concrete Product cung cấp các hiện thực khác nhau của interface Product.
*/
class ConcreteProduct1 : public Product {
public:
std::string Operation() const override {
return "{Result of the ConcreteProduct1}";
}
};
class ConcreteProduct2 : public Product {
public:
std::string Operation() const override {
return "{Result of the ConcreteProduct2}";
}
};
/**
* Lớp Creator khai báo phương thức factory method mà sẽ trả về một đối tượng của
* lớp Product. Các lớp con của Creator sẽ cung cấp hiện thực cho phương thức này.
*/
class Creator {
/**
* Lưu ý Creator cũng có thể tạo một hiện thực mặc định cho phương thức factory.
*/
public:
virtual ~Creator(){};
virtual Product* FactoryMethod() const = 0;
/**
* Cũng lưu ý rằng, mặc dù tên của nó, nhưng trách nhiệm chỉnh của Creator không phải là
* tạo product. Thông thường, nó chứa những logic cốt lõi dựa trên đối tượng Product,
* được trả về bởi phương thức factory. Các lớp con có thể thay đổi logic này không
* trực tiếp bằng cách ghi đè phương thức factory và trả về một kiểu khác của product.
*/
std::string SomeOperation() const {
// Gọi phương thức factory để tạo một đối tượng Product.
Product* product = this->FactoryMethod();
// Giờ thì sử dụng product.
std::string result = "Creator: The same creator's code has just worked with " + product->Operation();
delete product;
return result;
}
};
/**
* Concrete Creator ghi đè phương thức factory để thay đổi kiểu trả về của product.
*/
class ConcreteCreator1 : public Creator {
/**
* Lưu ý rằng chữ ký của phương thức vẫn sử dụng kiểu trừu tượng, mặc dù kiểu
* product cụ thể thực sự được trả về từ phương thức. Bằng cách này, Creator có
* thể độc lập với các lớp product cụ thể.
*/
public:
Product* FactoryMethod() const override {
return new ConcreteProduct1();
}
};
class ConcreteCreator2 : public Creator {
public:
Product* FactoryMethod() const override {
return new ConcreteProduct2();
}
};
/**
* Mã client làm việc với một thể hiện của concrete creator, mặc dù thông qua interface
* cơ sở của nó. Miễn là client còn tiếp tục làm việc với creator thông qua interface
* cơ sở, bạn có thể truyền nó vào bất kỳ lớp con nào của creator.
*/
void ClientCode(const Creator& creator) {
// ...
std::cout << "Client: I'm not aware of the creator's class, but it still works.\n"
<< creator.SomeOperation() << std::endl;
// ...
}
/**
* Chương trình sẽ chọn một kiểu creator tùy thuộc vào cài đặt hay môi trường.
*/
int main() {
std::cout << "App: Launched with the ConcreteCreator1.\n";
Creator* creator = new ConcreteCreator1();
ClientCode(*creator);
std::cout << std::endl;
std::cout << "App: Launched with the ConcreteCreator2.\n";
Creator* creator2 = new ConcreteCreator2();
ClientCode(*creator2);
delete creator;
delete creator2;
return 0;
}
Kết quả
App: Launched with the ConcreteCreator1.
Client: I'm not aware of the creator's class, but it still works.
Creator: The same creator's code has just worked with {Result of the ConcreteProduct1}
App: Launched with the ConcreteCreator2.
Client: I'm not aware of the creator's class, but it still works.
Creator: The same creator's code has just worked with {Result of the ConcreteProduct2}
Để lại một bình luận