Sơ đồ lớp mẫu Extension Object rút gọn

Một phần của tài liệu (LUẬN VĂN THẠC SĨ) Phát triển mẫu thiết kế phần mềm và ứng dụng (Trang 95 - 98)

Trong cách tiếp cận này, Subject duy trì một từ điển ánh xạ các tên mở rộng tới các sự mở rộng của nó. Client có thể đăng ký một sự mở rộng trong Subject bởi việc gọi AddExtension (extensionName, extension). Cách tiếp cận từ điển cho phép client thêm vào sự mở rộng bên ngoài mới theo yêu cầu và không yêu cầu ConcreteSubject biết trƣớc tất cả các sự mở rộng của nó. Một đối tƣợng đƣợc cƣ trú với các sự mở rộng khác nhau khi cần thiết.

Việc xác định các sự mở rộng. Các sự mở rộng cần một cách duy nhất để xác định chúng. Một cách tiếp cận đơn giản là việc sử dụng string. Các string yêu cầu một vài kiến trúc để tránh việc lặp. Một cách để ép buộc tính duy nhất trong C++ là sử dụng RTTI và phép toán typeid để xác định một cách duy nhất một giao diện. Trong trƣờng hợp này GetExtension lấy một type_info nhƣ là một tham số. Để yêu cầu cho sự mở rộng nhất định, client chuyển tiếp type_info của lớp AbstractExtension. Phép toán typeid đƣợc sử dụng để thu đƣợc một type_info tƣơng ứng.

AbstracsExtension*extension; Subject* subject;

extension = subject.GetExtension(typeid((AbstractExtension)); Xác định sự mở rộng trừu tƣợng. Trong C++ tất cả các thành viên của AbstractExtension đƣợc khai báo là thuần ảo. Trong Java, nó đƣợc xác định nhƣ là một giao diện.

Việc giải phóng các đối tƣợng mở rộng. Một vấn đề thực thi khác trong các môi trƣờng đƣợc thu thập không vô nghĩa là sự giải phóng của các đối tƣợng mở rộng. Subject kiểm soát một tham chiếu tới một đối tƣợng mở rộng và do đó không có điều khiển lên trên thời gian tồn tại của sự mở rộng. Một cách tiếp cận là xem xét các sự mở rộng đƣợc sở hữu bởi Subject và phá hủy chúng khi đối tƣợng Subject bị phá hủy. Một sự thay thế là sự sử dụng việc đếm tham chiếu. Client phải tăng một sự đếm tham chiếu khi chúng truy cập một sự mở rộng và giảm nó ngay khi chúng đƣợc thực hiện với nó.

Mã ví dụ: class Subject{ public:

virtual Extension* GetExtension(const char* name); };

Extension* Subject::GetExtension(const char* name){ return 0;

}

class ConcreteSubject: public Subject { public:

private:

SpecificExtension* specificExtension; };

Extension* ConcreteSubject::GetExtension(const char* name){ if (strcmp(name, "SpecificExtension" == 0) {

if (specificExtension == 0)

specificExtension = new SpecificExtension(this); return specificExtension; } return Subject::GetExtension(name); } //Mã Client để truy cập sự mở rộng SpecificExtension* extension; Subject* subject; extension = dynamic_cast<SpecificExtension*>( subject->GetExtension("SpecificExtension") ); if (extension){

// use the extension interface }

Hỗ trợ cho các giao diện có thể mở rộng là phổ biến trong các kiến trúc tài liệu phức hợp. Cả OpenDoc và OLE đều cung cấp kỹ thuật tƣơng ứng. Trong OpenDoc, ODObjec cung cấp giao diện cho việc truy cập các sự mở rộng. OLE xây dựng trên Component Object Model (COM). Trong COM tất cả các giao diện của một đối tƣợng đƣợc truy cập bởi kỹ thuật QueryInterface.

Trong framework giao diện ngƣời dùng của Taligent’s CommonPoint, lớp Tview chịu trách nhiệm quản lý phần trực quan của tình trạng thực màn hình. Tview là một sự trừu tƣợng chính của framework giao diện ngƣời dùng đồ họa. Nó có thể đƣợc mở rộng với các giao diện thêm vào và các cƣ xử mà không phải phân lớp. Tview có các thuộc tính. Một thuộc tính có thể đƣợc gắn kết vào một view và một client có thể truy vấn một view cho một thuộc tính xác định. Để mở rộng một view với cách cƣ xử thêm vào, client thực thi một lớp con Attribute và gắn một thực thể vào một view. Chẳng hạn một TnameAttribute có thể đƣợc sử dụng để gắn một giao diện cho việc gán một tên vào một view. Tview sử dụng cách tiếp cận từ điển để quản lý tập các sự mở rộng.

Visitor tập trung cách cƣ xử và cho phép thêm vào các cƣ xử mới vào một phân cấp lớp mà không phải thay đổi nó. Visitor có ích giống nhƣ mẫu Extension Object. Điểm khác nhau là mẫu Extension Object không yêu cầu một phân cấp lớp ổn định và

Decorator sử dụng tốt nhất trong các tình huống khi giao diện eo hẹp và một số thao tác đã có cần đƣợc tăng thêm.

Adapter hỗ trợ việc tƣơng thích một giao diện đang tồn tại. Mẫu Extension Object hỗ trợ các giao diện thêm vào. Extension Object và Adapter có thể cùng làm việc trong tình huống khi mà một đối tƣợng cần đƣợc làm tƣơng thích với một giao diện mở rộng.

4.1.4. Mẫu đối tượng kiểu

Mẫu đối tƣợng kiểu (Type Object pattern) phân tách các bản thể từ các lớp của chúng cốt để các lớp đó có thể đƣợc thực thi nhƣ là các bản thể của một lớp. Type Object cho phép các “lớp” mới đƣợc tạo ra một cách động tại lúc thực thi, cho phép một hệ thống cung cấp kiểu bản thân của nó và do đó hệ thống sẽ nhỏ gọn hơn, đơn giản hơn.

Tên khác: Power Type, Item Descriptor, Metaobject.

Đôi khi một lớp không chỉ yêu cầu một số lƣợng không biết trƣớc các bản thể cũng nhƣ số lƣợng không biết trƣớc các lớp con. Mặc dù một hệ thống đối tƣợng có thể tạo ra các bản thể mới theo yêu cầu, nó thƣờng không thể tạo ra các lớp mới mà không phải biên dịch lại. Một thiết kế trong đó một lớp có một số lƣợng không biết các lớp con có thể đƣợc chuyển đổi thành một thiết kế trong đó lớp đó có một số lƣợng không biết trƣớc các thực thể.

Hãy xem xét một hệ thống theo dõi các băng đĩa trong một bản kiểm kê của một cửa hàng cho thuê băng video. Hệ thống hiển nhiên sẽ yêu cầu một lớp gọi là Videotape. Mỗi bản thể của Videotape sẽ biểu diễn một một băng đĩa trong bản kiểm kê của cửa hàng. Dẫu sao, bởi vì nhiều băng đĩa là tƣơng tự, các bản thể Videotape sẽ chứa rất nhiều thông tin dƣ thừa. Cho ví dụ, tất cả các bản copy của Star Wars có cùng một tiêu đề, giá thuê, …. Các thông tin này là khác nhau đối với The Terminator nhƣng tất cả các copy của The Terminator có cùng dữ liệu. Do đó việc lặp lại thông tin này trên tất cả các copy của Star Wars hay của The Terminator là không cần thiết.

Một cách để giải quyết vấn đề này là tạo ra một lớp con của Videotape cho mỗi movie. Do đó sẽ có 2 lớp con là StarWarsTape và TerminatorTape. Bản thân lớp đó sẽ giữ thông tin cho movie đó. Do đó thông tin thông dụng của tất cả các copy của Star Wars sẽ đƣợc lƣu trữ chỉ một lần. Khi đó, Videotape sẽ là một lớp trừu tƣợng. Hệ thống sẽ không thể tạo các bản thể của nó. Thay vì đó, khi cửa hàng mua một băng đĩa mới và bắt đầu cho thuê chúng, hệ thống sẽ tạo ra một thực thể của lớp đó cho phim đó. Vì vậy nếu một băng đĩa mới là The Terminator, hệ thống sẽ tạo một bản thể của TerminatorTape.

Giải pháp này làm việc nhƣng chƣa tốt. Một vấn đề là nếu cửa hàng lƣu trữ rất nhiều phim khác nhau, Videotape sẽ yêu cầu một số lƣợng lớn các lớp con. Một vấn đề

khác là điều gì sẽ xảy ra khi hệ thống đƣợc triển khai và cửa hàng bắt đầu lƣu trữ một phim mới, chẳng hạn Independence Day. Không có lớp IndependenceDayTape trong hệ thống. Nếu developer không đoán trƣớc đƣợc vấn đề này, họ phải sửa đổi mã nguồn để thêm vào một lớp mới IndependenceDayTape, biên dịch lại hệ thống và triển khai. Nếu Developer đoán trƣớc đƣợc điều này, anh ta sẽ tạo ra một lớp con đặc biệt của Videotape chẳng hạn nhƣ UnknownTape. Và cửa hàng sẽ tạo một thực thể của nó cho tất cả các băng đĩa của phim mới. Vấn đề với UnknownTape là nó thiếu sự linh hoạt mà Videotape có. Khi videotape yêu cầu các lớp con, nó sẽ là UnknownTape, vì vậy UnknownTape không phải là giải pháp tốt.

Thay vào đó, bởi vì số lƣợng kiểu của băng đĩa là không biết, mỗi kiểu của băng đĩa cần là một thực thể của một lớp. Dẫu sao, mỗi băng đĩa cần là một thực thể của một kiểu băng đĩa. Ngôn ngữ đối tƣợng dựa trên lớp hỗ trợ cho các bản thể của của các lớp nhƣng không hỗ trợ các bản thể của các bản thể của các lớp. Vì vậy để thực thi giải pháp này trong một ngôn ngữ dựa trên lớp điển hình, bạn cần thực thi 2 lớp: một biểu diễn một kiểu của videotape (movie) và một biểu diễn của một videotape (Videotape). Mỗi bản thể của Videotape sẽ có một con trỏ tới thực thể Movie tƣơng ứng của nó.

Một phần của tài liệu (LUẬN VĂN THẠC SĨ) Phát triển mẫu thiết kế phần mềm và ứng dụng (Trang 95 - 98)

Tải bản đầy đủ (PDF)

(113 trang)