2011-12-19 9 views
6

Tôi đang triển khai chương trình C++ có thể lập trình nhanh đối tượng cho một tệp đầu vào cung cấp tên và đối số lớp để truyền cho các hàm tạo.C++ Mẫu Nhà máy với Cấu trúc Constructor Constraint

Các lớp học có nguồn gốc từ một lớp cơ sở chung nhưng chữ ký hàm tạo của chúng khác nhau.

Họ được khai báo như sau:

class Base { ... } 
class Class1 : Base { Class1(int a1, int a2); } 
class Class2 : Base { Class2(int a1, int a2, int a3); } 
... and so on... 

Các loại đối số không phải là int, trong thực tế, họ có thể là bất kỳ built-in loại hay phức tạp, kiểu tùy chỉnh.

Chương trình đầu vào có thể trông như thế này ở dạng JSON:

[ 
    { "Class1": ["arg11", "arg12"] }, 
    { "Class2": ["arg21", "arg22", "arg23"] }, 
    ...and so on... 
] 

Đọc qua tài liệu cho Boost.Functional/Factory có vẻ như nó có thể giải quyết vấn đề của tôi là nó không có thực tế rằng trong ứng dụng của tôi chữ ký constructor khác nhau (sự ràng buộc không đồng nhất). Boost.Function/Cách tiếp cận của nhà máy là bình thường hóa các chữ ký của hàm tạo tuy nhiên điều này là không thể trong ứng dụng của tôi.

Trong ngôn ngữ động như Python, điều này sẽ khá tầm thường: obj = klass(*args) trong đó klass = Class1args = ["arg11, "arg12"].

Vậy làm cách nào để thực hiện mô hình nhà máy với ràng buộc không đồng nhất trong C++?

Có thư viện nào khác ngoài Boost mà tôi đã bỏ qua có thể hỗ trợ không?

Có thể thực hiện điều này sao cho phụ thuộc duy nhất là thư viện chuẩn (tức là không có tăng cường)?

Hơn nữa, trong trường hợp đối số hàm tạo là kiểu phức tạp để nó phải được xây dựng đặc biệt từ biểu diễn JSON của nó, nó ảnh hưởng như thế nào đến độ phức tạp của vấn đề?

+0

Để tham khảo trong tương lai, trái ngược với đồng nhất là không đồng nhất –

+2

Hey Seth, 'không đồng nhất' cũng là một từ hợp lệ theo từ điển Merriam-Webster và cũng tương tự như trong ý nghĩa cho 'đồng nhất'. Tôi đã chọn tên cũ vì đó cũng là lựa chọn của tài liệu Boost.Function/Factory (xem liên kết trong bài đăng của tôi). –

+0

Có, tôi biết, bạn có thể thêm "in" hoặc "un" vào hầu hết các từ và nó vẫn sẽ là một từ. Nghe có vẻ kì lạ. –

Trả lời

1

Để đạt được những gì bạn muốn, bạn sẽ cần, tại một số điểm trong mã của bạn, một người khổng lồ switch -statement để quyết định lớp để xây dựng dựa trên tên (trên thực tế, một switch sẽ không hoạt động, bởi vì bạn không thể bật chuỗi - giống như một số rất dài if - else if).

Ngoài ra, có vẻ như đại diện bạn hiển thị không chứa bất kỳ thông tin nào về loại đối số của hàm tạo. Điều này có thể là một vấn đề nếu bạn có một lớp có nhiều hàm tạo có thể gọi được với cùng số đối số.

Cuối cùng, tôi nghĩ tốt nhất là bạn nên dùng thứ gì đó như @selbies answer, nhưng hãy sử dụng tạo mã để tạo mã xây dựng cho bạn.

+0

Cảm ơn @bjorn & selbie. Đối với trường hợp sử dụng của tôi, câu trả lời hay nhất là tạo mã. Trình tạo mã của tôi là ~ 100 dòng Python và tạo _approximately_ chức năng nhà máy hợp lệ. I E. Tôi phải xoa bóp một số mã được tạo ra. Ngay cả với một trình tạo mã hoàn hảo hơn, tôi đã vô cùng hiệu quả trong việc hoàn thành nhiệm vụ này. Nó vẫn có thể có giá trị mở rộng Boost.Functional/Nhà máy cho trường hợp sử dụng của tôi. Để được khám phá sau. :) FYI: Thư viện phân tích cú pháp tiêu đề C++: [Thư viện CppHeaderParser] (https://bitbucket.org/senex/cppheaderparser/src), phù hợp với nhu cầu của tôi. –

5

Bạn đã xem xét việc có một phương pháp nhà máy cho mỗi lớp biết cách xây dựng đối tượng từ một "mảng" các tham số được đọc từ tệp.

Đó là:

// declared "static" in header file 
Class1* Class1::FactoryCreate(int argc, const char** argv) 
{ 
    if (argc != 2) 
     return NULL; // error 

    int a1 = atoi(argv[0]); 
    int a2 = atoi(argv[1]); 
    return new Class1(a1, a2, a3); 
} 

// declared "static" in header file 
Class2* Class2::FactoryCreate(int argc, const char** argv) 
{ 
    if (argc != 3) 
     return NULL; // error 
    int a1 = atoi(argv[0]); 
    int a2 = atoi(argv[1]); 
    int a3 = atoi(argv[2]); 
    return new Class2(a1, a2, a3); 
} 
+0

Tôi chắc chắn đã xem xét một tùy chọn tương tự như thế này ... tức là chuyển đối tượng JSON đến một hàm nhà máy tĩnh và nó trả về cá thể. Vấn đề là cơ sở mã mà tôi đang xử lý có hơn 100 lớp như vậy vào thời điểm này và đang phát triển. Vì vậy, trong khi điều này chắc chắn sẽ là một giải pháp có thể, tôi ngần ngại gọi nó là lý tưởng vào lúc này. –