2008-08-28 32 views
9

Tôi xin lỗi nếu câu hỏi của tôi quá dài và kỹ thuật nhưng tôi nghĩ rằng điều quan trọng đến nỗi người khác sẽ quan tâm đến nóMẫu khách truy cập chung chung hơn

Tôi đang tìm cách tách riêng một số phần mềm bên trong từ đại diện của họ trong C++

tôi có một lớp thông số chung chung (sau này được lưu trữ trong một container) có thể chứa bất kỳ loại giá trị với các boost :: bất kỳ lớp

tôi có một lớp cơ sở (khoảng) thuộc loại này (tất nhiên có nhiều nội dung hơn)

class Parameter 
{ 
public: 
    Parameter() 
    template typename<T> T GetValue() const { return any_cast<T>(_value); } 
    template typename<T> void SetValue(const T& value) { _value = value; } 
    string GetValueAsString() const = 0; 
    void SetValueFromString(const string& str) const = 0; 
private: 
    boost::any _value; 
} 

Có hai mức độ của các lớp thừa: Mức đầu tiên xác định loại và chuyển đổi sang/từ chuỗi (ví dụ ParameterInt hoặc ParameterString) Mức thứ hai định nghĩa hành vi và những người sáng tạo thực tế (ví dụ như bắt nguồn ParameterAnyInt và ParameterLimitedInt từ ParameterInt hoặc ParameterFilename từ GenericString)

tùy thuộc vào loại thực tôi muốn thêm chức năng bên ngoài hoặc các lớp học mà hoạt động này tùy thuộc vào loại thông số cụ thể mà không cần thêm các phương pháp ảo để các lớp cơ sở và không làm phôi lạ

Ví dụ: tôi sẽ muốn tạo ra các điều khiển gui thích hợp tùy thuộc vào loại tham số:

Widget* CreateWidget(const Parameter& p) 

Tất nhiên tôi không thể hiểu loại Parameter thực từ này trừ khi tôi sử dụng RTTI hoặc thực hiện nó tự ngã của tôi (với enum và trường hợp chuyển đổi), nhưng đây không phải là giải pháp thiết kế OOP phù hợp, bạn biết đấy.

Giải pháp cổ điển là thiết kế mẫu của khách http://en.wikipedia.org/wiki/Visitor_pattern

Vấn đề với mô hình này là tôi phải biết trước đó có nguồn gốc loại sẽ được thực hiện, vì vậy (đặt lại với nhau những gì được viết trong wikipedia và mã của tôi) chúng tôi sẽ có loại:

struct Visitor 
{ 
    virtual void visit(ParameterLimitedInt& wheel) = 0; 
    virtual void visit(ParameterAnyInt& engine) = 0; 
    virtual void visit(ParameterFilename& body) = 0; 
}; 

Có giải pháp nào để có được hành vi này theo bất kỳ cách nào khác mà không cần biết trước tất cả các loại cụ thể và không có khách truy cập ban đầu?


Edit:Dr. Pizza's solution seems the closest to what I was thinking, nhưng vấn đề là vẫn như nhau và phương pháp này là thực sự dựa vào dynamic_cast, rằng tôi đang cố gắng để tránh như một loại (ngay cả khi yếu) phương pháp RTTI

Có lẽ nó là tốt hơn để suy nghĩ đến một số giải pháp mà không cần trích dẫn mô hình khách truy cập và làm sạch tâm trí của chúng tôi. Mục đích chỉ là có chức năng như:

Widget* CreateWidget(const Parameter& p) 

cư xử khác nhau cho mỗi tham số "bê tông" mà không làm mất thông tin về loại hình của nó

Trả lời

0

Nếu tôi hiểu được điều này một cách chính xác ...

Chúng tôi đã có một đối tượng có thể sử dụng các tùy chọn phần cứng khác nhau. Để tạo thuận lợi cho điều này, chúng tôi đã sử dụng giao diện trừu tượng của Thiết bị. Thiết bị có một loạt các chức năng sẽ được kích hoạt trên một số sự kiện nhất định.Việc sử dụng sẽ giống nhau nhưng các cài đặt khác nhau của Thiết bị sẽ có chức năng đầy đủ tính năng hoặc chỉ trả lại ngay lập tức. Để làm cho cuộc sống trở nên dễ dàng hơn, các chức năng bị vô hiệu và đã loại trừ các trường hợp ngoại lệ khi có sự cố.

1

Tôi đã sử dụng this ("khách truy cập chu kỳ") để có hiệu quả tốt; nó làm cho việc thêm các lớp mới vào hệ thống phân cấp có thể mà không thay đổi các lớp hiện có, ở một mức độ nào đó.

+0

Thật đáng tiếc khi bài viết này dường như đã biến mất: nó đã khơi gợi sự quan tâm của tôi. Tôi cho rằng tám năm là vĩnh cửu trên Internet. – Nicole

+0

@Nicole http://web.archive.org/web/20080517124442/http://www.objectmentor.com/resources/articles/acv.pdf – DrPizza

+0

Cảm ơn bạn! Điều đó thật là tốt. – Nicole

0

Vì tính đầy đủ của:

đó là tất nhiên hoàn toàn có thể viết một thực hiện riêng của một bảng con trỏ multimethod cho đối tượng của bạn và tính toán các địa chỉ phương pháp bằng tay tại thời gian chạy. Có một số paper bởi Stroustrup về chủ đề triển khai multimethods (mặc dù trong trình biên dịch).

Tôi sẽ không thực sự khuyên bất cứ ai làm điều này. Việc triển khai thực hiện tốt là khá phức tạp và cú pháp để sử dụng nó có thể sẽ rất khó xử và dễ xảy ra lỗi. Nếu mọi thứ khác thất bại, điều này vẫn có thể là con đường để đi, mặc dù.

0

Tôi gặp sự cố khi hiểu yêu cầu của bạn. Nhưng Ill nhà nước - theo cách của tôi vì nó là - những gì tôi hiểu tình hình là:

  • Bạn có lớp Parameter trừu tượng, được subclassed cuối cùng để một số lớp bê tông (ví dụ: ParameterLimitedInt).

  • Bạn có một hệ thống GUI riêng biệt sẽ được chuyển các tham số này theo kiểu chung, nhưng bắt là cần phải trình bày thành phần GUI cụ thể cho loại cụ thể của lớp tham số.

  • Các hạn chế là bạn không muốn thực hiện RTTID và không muốn viết mã để xử lý mọi loại tham số cụ thể có thể có.

  • Bạn đang mở để sử dụng mẫu khách truy cập.

Với những người đang được yêu cầu của bạn, ở đây là làm thế nào tôi sẽ xử lý một tình huống như vậy:

tôi sẽ thực hiện mẫu người truy cập nơi accept() trả về một giá trị boolean. Lớp Parameter cơ sở sẽ thực hiện một hàm accept() ảo và trả về false.

Triển khai cụ thể của lớp Thông số sau đó sẽ chứa các hàm accept() sẽ gọi lượt truy cập của khách truy cập(). Họ sẽ trở lại sự thật.

Lớp khách truy cập sẽ làm cho việc sử dụng một lần templated() chức năng, do đó bạn sẽ chỉ ghi đè cho các loại Parameter bê tông bạn quan tâm để hỗ trợ:

class Visitor 
{ 
public: 
    template< class T > void visit(const T& param) const 
    { 
    assert(false && "this parameter type not specialised in the visitor"); 
    } 
    void visit(const ParameterLimitedInt&) const; // specialised implementations... 
} 

Vì vậy, nếu chấp nhận() trả về false, bạn biết loại bê tông cho Thông số đã không thực hiện mẫu khách truy cập nào (trong trường hợp có thêm logic bạn muốn xử lý trên cơ sở từng trường hợp). Nếu xác nhận() trong mô hình khách truy cập kích hoạt, mẫu của nó sẽ không kích hoạt kiểu Tham số mà bạn đã triển khai chuyên môn cho.

Một nhược điểm của tất cả những điều này là lượt truy cập không được hỗ trợ chỉ bị bắt khi chạy.

Các vấn đề liên quan