Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 26 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
26
Dung lượng
635,5 KB
Nội dung
CHƯƠNG III: CÁC MẪU CẤU TRÚC: COMPOSITE VÀ FLYWEIGHT Các mẫu cấu trúc Composite1 Flyweight áp dụng cho hệ thống có nhiều đối tượng liệu Mẫu Composite có ứng dụng rộng rãi, danh sách tổng hợp sử dụng mẫu Flyweight Mẫu Flyweight chia sẻ đối tượng giống hệt hậu trường để tiết kiệm nhớ Trong việc triển khai chúng, mẫu sử dụng tính C# sau đây: Generics Properties Structs Indexers Implicit typing Initializers Anonymous types Mẫu Composite Vai trò Mẫu composite xếp hệ thống phân cấp có cấu trúc để thành phần nhóm thành phần xử lý theo cách Hoạt động điển hình thành phần bao gồm thêm, xóa, hiển thị, tìm kiếm, nhóm Minh hoạ Ứng dụng máy tính chuyên nhóm liệu có nhiều ngày Xem xét danh sách nhạc iTunes album ảnh số Flickr iPhoto (Hình 3-1) Các mục đặt danh sách lớn, sau đưa vào cấu trúc riêng biệt Tổng hợp Hình 2-1 Hình minh họa mẫu Composite —iPhoto Nhìn vào ảnh chụp hình từ iPhoto, thấy có nhiều cách khác để xem hình ảnh nhập: thứ tự thời gian tên kiện Một ảnh xuất nhiều album (Ví dụ: "Blog", "HaLong", "2014") Tạo album hình thức đối tượng hỗn hợp khơng địi hỏi chép thực ảnh Trong ngữ cảnh này, điểm quan trọng mẫu Composite hoạt động thực ảnh album ảnh phải có tên hiệu ứng tương tự, việc triển khai khác Ví dụ, người sử dụng hiển thị hình ảnh album (có chứa hình ảnh) Tương tự vậy, xóa ảnh hay album hành xử theo cách Thiết kế Mẫu composite mẫu đơn giản nhất, giao diện Nó phải ứng phó với hai thứ: thành phần (Component) tổng hợp (Composites) thành phần Cả hai loại thống cho phù hợp với giao diện hoạt động chung Đối tượng Composite chứa Component, nhiều trường hợp, hoạt động Composite thực cách gọi hoạt động tương đương cho đối tượng Component Xem hình 3-2 với sơ đồ UML cho mẫu Các yếu tố cần thiết sơ đồ UML mẫu Composite là: IComponent Xác định thao tác cho đối tượng cấu, hành vi mặc định áp dụng đối tượng hai loại Hình 3-2 Sơ đồ UML mẫu Composite Operation Biểu diễn thao tác đối tượng tuân theo IComponent Component Thực thi thao tác áp dụng cho đối tượng mà phân tách thêm Composite Thực thi thao tác áp dụng cho đối tượng tổng hợp, sử dụng (hoặc truy cập) danh sách thành phần giữ chỗ sử dụng thao tác Component tương đương Client giao tiếp với giao diện IComponent, đơn giản hoá nhiệm vụ Câu hỏi Khớp yếu tố mẫu Composite với minh họa iPhoto Để kiểm tra xem bạn hiểu mẫu Composite, che cột trái bảng xem liệu bạn xác định đối tượng mục từ ví dụ minh họa (Hình 3-1), thể cột bên tay phải Sau kiểm tra câu trả lời bạn cột bên tay trái IComponent Một đơn vị nhìn thấy iPhoto Component Một ảnh đơn Composite Một album ảnh Operation Mở xem Thực Mặc dù minh họa đề cập vào ảnh album, thiết kế triển khai mẫu Composite hoàn toàn độc lập với kiểu thành phần xử lý Chúng ta thực tốt với nhóm người danh mục đầu tư tài khoản ngân hàng Các hoạt động tổng hợp, Ngược lại, phải lặp qua cấu trúc thành phần Để thực linh hoạt thành phần dạng kết nối thành phần yếu tố tổng hợp, sử dụng tính C# Generics Tính C#—Generics Generics phần mở rộng với hệ thống kiểu theo cấu trúc, lớp, giao diện, delegate (đại biểu) phương thức tham số với kiểu Ví dụ, kiểu chung List tạo với nhiều loại xây dựng List List Tất lớp chứa (collection) thư viện NET Framework sử dụng C # có sẵn dạng generic Chúng bao gồm Dictionary, Stack, Queue, List, cộng với biến thể chúng Ngoài cịn có phương pháp chung Sort BinarySearch Những yêu cầu dạng cần phải thực giao diện IComparer cho so sánh thành phần thực cách xác Để khai báo kiểu phương thức generic, sử dụng tham số generic dấu ngoặc nhọn, Kiểu generic dùng để khai báo thành phần generic, lần cách sử dụng định dạng , sử dụng bình thường kiểu, T Để xây dựng kiểu thực tế phương thức từ generic, khai báo kiểu thực tế cho thông số chung chung, Theo C# Language Specification phiên 3.0, Tháng chín 2007, mục 10.1.3 Bằng cách khai báo IComponent, Component, Composite kiểu chung chung, tạo thực thi mẫu Composite khởi tạo ví dụ thực tế Đối với mẫu Composite, khơng tạo chương trình, mà tạo khơng gian tên (namespace) có chứa hai lớp, Composite Component, giao diện, IComponent Bắt đầu với giao diện IComponent, khai báo generic cuả kiểu T Sau đó, hoạt động dự kiến sau: public interface IComponent { void Add(IComponent c); IComponent Remove(T s); IComponent Find(T s); string Display(int depth); T Item { get; set; } } Đối với mẫu Composite, khơng tạo chương trình, mà tạo khơng gian tên (namespace) có chứa hai lớp, Composite Component, giao diện, IComponent Tại Add, Remove, Find đề cập đến IComponent Remove Find đề cập đến T vậy? Sự khác biệt T gì? Nhớ lại đối tượng kiểu IComponent Component Composite có trạng thái liên quan IComponent, ngồi giá trị thực tế phần tử lưu trữ Các phần tử kiểu T, trường hợp Find Remove, truyền tham số yếu tố giá trị thực tế kiểu T Ví dụ, giao diện khởi tạo với T Image, truyền đối tượng Image tới Find ngược lại có tham chiếu đến đối tượng IComponent Đối tượng trả chứa đối tượng Image tìm kiếm thành cơng Dịng cuối giao diện thú vị giới thiệu cú pháp cho thuộc tính lớp Trước C# 3.0, cú pháp xuất giao diện Nó mở rộng đến lớp làm cho chương trình ngắn dễ đọc Tính C#—Thuộc tính (Properties) Bộ truy xuất (Accessors) Một thuộc tính (property) kiểm sốt cho phép truy cập đến trạng thái cục riêng đối tượng, trực tiếp đến trường qua số tính tốn Thuộc tính xác định hai truy cập: get và/hoặc set Hình thức phổ biến thuộc tính là: public type Field {get; set;} nơi mà Field định danh Khai báo tạo trường riêng tư làm cho truy cập để đọc ghi cơng khai thơng qua tên Field Bằng cách đặt thuộc tính giao diện, yêu cầu cách hiệu lớp phải cung cấp truy cập tài sản phương thức thông thường thực giao diện Thuộc tính bỏ qua truy xuất get set; thường bỏ qua set, làm cho thuộc tính đọc Thuộc tính tính tốn kết get set, trường hợp này, cú pháp mở rộng là: public type Field { get { statements; return expression; } set { statements including reference to value; } } Một thuộc tính thơng thường, khơng thiết, truy cập tới biến riêng kiểu Field value tham số tiềm ẩn lời gọi để thiết lập thuộc tính Theo C# Language Specification phiên 3.0, Tháng chín 2007, mục 10.7 Bây giờ, xem xét làm lớp Component thực thi phù hợp với giao diện IComponent, khơng gian tên hiển thị Ví dụ 3-1 Ví dụ 3-1 Code khơng gian tên - mẫu Composite 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 using System; using System.Collections.Generic; using System.Text; // for StringBuilder namespace CompositePattern { // The Interface public interface IComponent { void Add(IComponent c); IComponent Remove(T s); string Display(int depth); IComponent Find(T s); T Name { get; set; } } // The Component public class Component : IComponent { public T Name { get; set; } public Component(T name) { Name = name; } public void Add(IComponent c) { Console.WriteLine("Cannot add to an item"); } public IComponent Remove(T s) { Console.WriteLine("Cannot remove directly"); return this; } public string Display(int depth) { return new String('-', depth) + Name + "\n"; } public IComponent Find(T s) { if (s.Equals(Name)) return this; else return null; } } // The Composite public class Composite : IComponent { List list; public T Name { get; set; } public Composite(T name) { Name = name; list = new List(); } 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 public void Add(IComponent c) { list.Add(c); } IComponent holder = null; // Finds the item from a particular point in the structure // and returns the composite from which it was removed // If not found, return the point as given public IComponent Remove(T s) { holder = this; IComponent p = holder.Find(s); if (holder != null) { (holder as Composite).list.Remove(p); return holder; } else return this; } // Recursively looks for an item // Returns its reference or else null public IComponent Find(T s) { holder = this; if (Name.Equals(s)) return this; IComponent found = null; foreach (IComponent c in list) { found = c.Find(s); if (found != null) break; } return found; } // Displays items in a format indicating their level in the composite structure public string Display(int depth) { StringBuilder s = new StringBuilder(new String('-', depth)); s.Append("Set " + Name + " length :" + list.Count + "\ n"); foreach (IComponent component in list) { s.Append(component.Display(depth + 2)); } return s.ToString(); } } } Không gian tên bắt đầu với định nghĩa giao diện với bốn phương thức thuộc tính Sau cài đặt lớp Component Khơng phải tất phương thức IComponent có ý nghĩa với Component Thêm (Add) loại bỏ (Remove) thực Composite, đó, thơng báo lỗi đơn giản viết (xem phần "bài tập" tới có mở rộng điểm này) Trong phương thức Find Component (dòng 36-42), lớp dựa tham số kiểu thực cho T cần có phương thức Equals Nếu khơng, thực thể generic lỗi thời gian biên dịch Phương thức Display (dòng 32-35) giả định trường truy cập thuộc tính Name có phương thức ToString xác định Trong thực tế, kiểu "string-like" hoạt động đây, có khả phương thức Display cần định nghĩa sau (xem phần "Bài tập" tới.) Lớp Composite thực thi giao diện IComponent (dòng 45) Phương thức Find Remove Composite có nhiều cơng phu so với thứ khác Component để chúng xử lý cấu trúc tùy ý tổng hợp thành phần Chúng ta xem xét số điều thú vị hơn: Composite giữ dạng danh sách cấu trúc cục bao gồm Component Composite (dòng 47) Khi nội dung khơng có Composite, đối tượng tạo ra, danh sách Danh sách khai báo là: List list; Điều cho thấy kiểu generic mở sử dụng tham số đến kiểu generic Logic Remove (dòng 61-72) tìm đối tượng cấu trúc sau đó, có, loại bỏ khỏi cấu trúc danh sách tổ chức cục Composite (dịng 67): (holder as Composite).list.Remove(p); Biến holder có kiểu IComponent cần phải ép thành Composite trước danh sách truy cập Một kiểu generic mở sử dụng vòng lặp foreach, phương thức Find Display (dòng 82 94): foreach (IComponent c in list) { found = c.Find(s); Các gọi đến Find đến phương thức thích hợp, tùy thuộc vào kiểu thực c chạy Điều hỗ trợ ý tưởng mẫu Composite: Components Composites đối xử Đây việc thực mẫu Composite lý thuyết Ngoài mối quan tâm với phương thức Display, ba kiểu trước sử dụng chung với thành phần Do đó, đặt chúng khơng gian tên gọi CompositePattern để sử dụng ví dụ Ví dụ: Photo Library Trong ví dụ này, quan tâm đến việc thu thập tên tập tin hình ảnh số vào tập hợp đặt tên Chúng ta khơng sử dụng hình ảnh thật ví dụ này, tên tập tin chuỗi Client đưa tập miền cụ thể lệnh để tạo thao tác với thư viện Trung tâm thao tác thư viện, từ quan điểm người sử dụng, "nơi chúng có" Chúng ta bắt đầu với tập hợp rỗng gọi "Album" Một số lệnh rời khỏi hệ thống thành phần vừa điều chỉnh, thứ khác di chuyển trở lại thành phần tập hợp Những lệnh là: AddSet Thêm tập rỗng với tên để album AddPhoto Thêm ảnh đặt tên sau trỏ để album Find Tìm thành phần đặt tên (tập hình ảnh), trả null khơng tìm thấy Remove Loại bỏ thành phần đặt tên (tập hình ảnh) trở lại tập mà từ gỡ bỏ Display Hiển thị toàn cấu trúc Quit Thốt chương trình Như vậy, hai hoạt động mà làm việc Component Composites Find Remove Xem xét số ví dụ hoạt động hệ thống này, minh họa ví dụ 3-2 Các lệnh đầu vào hiển thị giữa, kết Display hiển thị bên trái, số bình luận xuất bên phải Các tập tin đầu vào có chứa tất lệnh Chương trình mong đợi tập tin phải gọi Composite.dat Ví dụ 3-2 Mẫu Composite—Chương trình Photo Library xuất AddSet Home AddPhoto Dinner.jpg AddSet Pets Going down another level AddPhoto Dog.jpg AddPhoto Cat.jpg Find Album Ensures Garden is at same level as Home AddSet Garden AddPhoto Spring.jpg AddPhoto Summer.jpg AddPhoto Flowers.jpg AddPhoto Trees.jpg Display Returns to start of Album Set Album length :2 Set Home length :2 Dinner.jpg Set Pets length :2 Dog.jpg Cat.jpg Set Garden length :4 Spring.jpg Summer.jpg Trees.jpg BetterFlowers.jpg Quit Lớp Client mà thực thi lệnh hiển thị ví dụ 3-3 Nó trình thơng dịch lệnh đơn giản mà làm tốt việc sử dụng C # 's chuyển đổi tính chuỗi Ví dụ 3-3 Ví dụ code mẫu Composite—Photo Library using System; using System.Collections.Generic; using System.IO; using CompositePattern; // The Client class CompositePatternExample { static void Main() { IComponent album = new Composite("Album"); IComponent point = album; string[] s; string command, parameter; // Create and manipulate a structure StreamReader instream = new StreamReader("Composite.dat"); { string t = instream.ReadLine(); Console.WriteLine("\t\t\t\t" + t); s = t.Split(); command = s[0]; if (s.Length > 1) parameter = s[1]; else parameter = null; switch (command) { case "AddSet": IComponent c = new Composite(parameter); point.Add(c); point = c; break; case "AddPhoto": point.Add(new Component(parameter)); break; case "Remove": point = point.Remove(parameter); break; case "Find": point = album.Find(parameter); Các phương thức Display Component Composite giả định kiểu T string-like Tạo phiên mẫu Composite T khơng phải kiểu chuyển đổi thành chuỗi (ví dụ dùng hình ảnh) điều tra xem liệu phương thưc Display ghi đè phương thức mở rộng không gian tên Client Trong lớp Composite, thay đổi List thành Dictionary Như mà điều ảnh hưởng đến thao tác Find? Mặc dù cố gắng để có giao diện cho thành phần tổng hợp, cách tiếp cận khác xem xét hoạt động thực phổ biến tách riêng thứ áp dụng, ví dụ, tổng hợp Sau có hai cấp độ giao diện, sau: interface IComponent { // Name, Display } interface IComposite where T : IComponent { // Add, Remove, Find } //1 Bây giờ, khơng có nhu cầu cho IComponent thành generic—một component mà có tên hiển thị Những căng thẳng sử dụng T sử dụng IComponent đi, q Lập trình lại ví dụ theo cách (Gợi ý: giao diện thứ hai sử dụng ràng buộc generic, dùng nhiều Chương 6.) Mẫu Flyweight Vai trò Mẫu Flyweight tăng cường cách hiệu chia sẻ thông tin chung đối tượng nhỏ xảy hệ thống với số lượng lớn Điều giúp làm giảm yêu cầu lưu trữ nhiều giá trị chép Mẫu Flyweight giúp phân biệt trạng thái nội ngoại sinh đối tượng Việc tiết kiệm lớn mẫu Flyweight xảy đối tượng sử dụng hai loại trạng thái nhưng: Trạng thái nội chia sẻ quy mô rộng, giảm thiểu yêu cầu lưu trữ Nguyên tác giả interface IComponent { // Name, Display } interface IComposite IComponent where T : IComponent { // Add, Remove, Find } Nhưng tra cứu từ khố where (http://msdn.microsoft.com/en-us/library/bb384067.aspx) MSDN khơng có IComponent chỗ gạch chân, gõ VS phải bỏ chỗ Trạng thái ngoại sinh tính được, nhằm tính toán giao dịch để lưu trữ Minh hoạ Xem xét phương diện hình ảnh ứng dụng Thư viện ảnh, thảo luận mẫu Composite Tại thời điểm, chúng tơi muốn có trang đầy đủ hình ảnh hiển thị, khơng có thời gian trễ nhận thấy được, chúng tơi muốn cuộn lên xuống thông qua thư viện Điều ngụ ý phải có nhiều hình ảnh nên cài đặt sẵn vào nhớ giữ ứng dụng hình ảnh chạy Với ứng dụng Photo Group, chức xếp hình ảnh theo nhóm Các hình ảnh thuộc nhiều nhóm khác nhau, số lượng hình ảnh hiển thị tăng nhiều Nếu tất hình ảnh khơng đủ nhớ, thực tế chúng thuộc nhóm khác có nghĩa ảnh cụ thể gọi lên để hiển thị thời gian khơng đều, dẫn đến nhiều q trình đọc đĩa Xem xét minh họa hình 3-3 Với cửa sổ nhỏ hơn, hai nhóm cuộn qua cửa sổ vào thời điểm nhóm Food xuất hiện, địi hỏi phải có ba số hình ảnh tái nạp hiển thị Trạng thái không chia sẻ đối tượng tập hợp nhóm mà thuộc Trạng thái bên ngồi hình ảnh thực tế, lớn chiếm khoảng MB Tuy nhiên, có phương thức namespace System.Drawing để chuyển đổi hình ảnh vào hình ảnh thu nhỏ khoảng KB Điều thành trạng thái nội đối tượng, đủ nhỏ phép tất hình ảnh lại nhớ thời điểm Thơng qua thơng tin nhóm, ứng dụng hiển thị hình ảnh kết hợp khác Bằng cách sử dụng nạp đĩa, hiển thị hình ảnh với kích thước hồn chỉnh ban đầu Thiết kế Xem xét sơ đồ UML hình 3-4 Như giải thích phần trước, mơ hình Flyweight dựa vào khả phân chia trạng thái ứng dụng thành ba loại Các intrinsicState nằm đối tượng Flyweight Lớp Flyweight thực thi giao diện IFlyweight, xác định hoạt động phần cịn lại hệ thống dựa Khách hàng trì unSharedState từ điển tất Flyweights, mà nhận từ FlyweightFactory có cơng việc để đảm bảo giá trị tạo Cuối cùng, extrinsicState không xuất hệ thống vậy; có nghĩa phải tính thời gian chạy cho trường hợp instrinsicState, theo yêu cầu Các yếu tố mẫu Flyweight gồm: Client Tính tốn trì trạng thái khơng chia sẻ đối tượng IFlyweight Định nghĩa giao diện mà qua Flyweights nhận hành động theo trạng thái nội Hình 3-3 Hình minh họa mẫu Flyweight—Photo Group Hình 3-4 Sơ đồ UML mẫu Flyweight FlyweightFactory Tạo quản lý đối tượng Flyweight đặc biệt Flyweight Lưu trữ trạng thái nội có nghĩa chia sẻ tất các đối tượng Có lựa chọn thiết kế khác Ví dụ, hình 3-4, Flyweight thể tính tốn extrinsicState Tuy nhiên, Client làm việc tính tốn thơng qua extrinsicState cho Flyweight tham số cho Operation Ngồi ra, chúng tơi dự tính unSharedState từ điển giá trị liên quan đến Flyweights; Tuy nhiên, unSharedState có cấu trúc phức tạp hơn, bảo vệ lớp riêng Trong trường hợp này, đứng bên cạnh lớp Flyweight thực giao diện IFlyweight Câu hỏi Khớp yếu tố mẫu Flyweight với minh họa Photo Group Để kiểm tra xem bạn hiểu mẫu Flyweight, che cột trái bảng xem liệu bạn xác định đối tượng mục từ ví dụ minh họa (Hình 3-1), thể cột bên tay phải Sau kiểm tra câu trả lời bạn cột bên tay trái Client IFlyweight FlyweightFactory Flyweight Ứng dụng Photo Group Thơng số kỹ thuật hình ảnh Đăng ký hình ảnh độc Trình tạo vẽ (hình ảnh thu nhỏ (thumbnail)) intrinsicState Thumbnail extrinsicState Hình ảnh đầy đủ unSharedState Thơng tin nhóm Thực Việc thực mô hình Flyweight giúp sử dụng hai tính thú vị từ C# 1.0 ba từ C# 3.0 Đó là: Structs (Cấu trúc) Indexers (Chỉ mục) Implicit typing for local variables and arrays (Kiểu tiềm ẩn cho biến cục mảng) Object and collection initializers (Bộ khởi tạo) Anonymous types (Kiểu nặc danh) Ngoài ra, sử dụng generic collections từ C# 2.0, thảo luận phần mẫu Composite Tôi giới thiệu tính phần văn sau Mẫu bao gồm ba loại: IFlyweight, Flyweight, FlyweightFactory Như mẫu Composite, đặt chúng không gian tên sử dụng không gian tên ví dụ lý thuyết cho mẫu Bởi kiểu giao diện, chúng hàm tạo chúng phải khai báo public Chúng ta bắt đầu với giao diện: public interface IFlyweight { void Load (string filename); void Display (PaintEventArgs e, int row, int col); } Phương thức Load nạp vào nhớ ảnh thu nhỏ hình ảnh sử dụng tên tập tin Phương thức Display hiển thị hình ảnh thu nhỏ Sau đó, cần phải thêm tiếp tục tùy chọn Display để hiển thị phiên đầy đủ hình ảnh (trạng thái bên ngồi nó) Bây giờ, xem xét tính bốn tính chúng ta: structs (cấu trúc) Tính C#—Structs C# có hai kiểu cấu trúc để định nghĩa thuộc tính hoạt động: class tiếng struct biết đến Các cấu trúc tương tự lớp kiểu chứa thành viên liệu thành viên chức Tuy nhiên, biến cấu trúc trực tiếp chứa liệu cấu trúc, biến lớp chứa tham chiếu đến liệu Thể lớp cấu trúc đối tượng Tuy nhiên, cấu trúc gán giá trị giá trị gán chuyển, tham chiếu đến đối tượng thực, trường hợp đối tượng khởi tạo từ lớp Cấu trúc nhẹ thực thi mà khơng chi phí Chúng đặc biệt hữu ích cho cấu trúc liệu nhỏ Những hạn chế cấu trúc chúng kế thừa từ kiểu khác; chúng có thể, ngược lại, thực thi giao diện Theo C# Language Specification phiên 3.0, Tháng chín 2007, mục 11 Một Flyweight ứng cử viên lý tưởng cho cấu trúc; Flyweights nhỏ, chúng không kế thừa từ thứ (mặc dù kiểu làm thực thi giao diện) Đây cấu trúc Flyweight chúng ta: public struct Flyweight : IFlyweight { } // Intrinsic state Image pThumbnail; public void Load(string filename) { pThumbnail = new Bitmap("images/" + filename) GetThumbnailImage(100, 100, null, new IntPtr()); } public void Display(PaintEventArgs e, int row, int col) { e.Graphics.DrawImage(pThumbnail, col * 100 + 10, row * 130 + 40, pThumbnail.Width, pThumbnail.Height); } Như mong muốn, Load sử dụng hình ảnh tên tập tin định, khơng giữ lại intrinsicState nó; giữ hình thu nhỏ Các tính tốn thực để xác định vị trí hình thu nhỏ hình thể hình 3-3 Chúng rõ ràng cải thiện cách sử dụng số Chú ý, thông tin hàng cột có nguồn gốc từ unSharedState nhóm, giữ Client Tiếp theo, xem xét factory (nhà máy, éo biết dịch nữa) Chúng ta xem xét thêm Factory chương 6, bây giờ, tơi nói dạng đơn giản chúng, chúng tạo đối tượng theo điều kiện cụ thể Ở đây, quan tâm kiểm tra xem đối tượng tồn trước thêm vào sưu tập Trước bắt đầu code, xem xét nhanh indexers Bây giờ, đưa lớp FlyweightFactory: 10 11 12 13 14 15 16 17 18 19 20 21 public class FlyweightFactory { // Keeps an indexed list of IFlyweight objects in existence Dictionary flyweights = new Dictionary(); public FlyweightFactory() { flyweights.Clear(); } public IFlyweight this[string index] { get { if (!flyweights.ContainsKey(index)) flyweights[index] = new Flyweight(); return flyweights[index]; } } } Trong dòng 4-5, Dictionary khai báo, ánh xạ chuỗi đến flyweights Trên dòng 17-18, Dictionary truy cập cách sử dụng mục phần định nghĩa Dictionary Dịng 17 ví dụ việc sử dụng truy cập set, dòng 18 gọi truy xuất get Đây phần thành viên khai báo dòng 12-20, nơi xác định mục riêng cho lớp FlyweightFactory Dịng 12 xác định kiểu trả kiểu khóa, dịng 16-18 cho phần thân truy xuất get Nó bắt đầu cách kiểm tra xem có Flyweight với khóa Nếu khơng, cấp phát Trong hai trường hợp, trả phần tử từ điển với số xác Tính C#—Indexers Một mục (indexer) thành viên cho phép đối tượng lập mục cách sử dụng cú pháp tương tự mảng Nó sử dụng với sưu tập để lập mục đối tượng sưu tập sử dụng [index] thay Key (index) Hơn nữa, truy cập indexer kiểm tra liệu giá trị số tồn trước, cách sử dụng phương thức containsKey Bộ mục liên quan đến thuộc tính chia sẻ cú pháp truy xuất, get set Một indexer định nghĩa là: modifiers return-type this[key-type key] { get { } set { } } Nội dung khối get phải trả lại giá trị kiểu return-type Nội dung khối set sử dụng tham số ẩn value Nếu kiểu có mục xác định đối tượng kiểu sử dụng, như: obj[index] = x; x = obj[index]; Chỉ mục định nghĩa cho mảng (tất nhiên) cho tất collections thư viện NET Framework sử dụng C # Theo C# Language Specification phiên 3.0, Tháng chín 2007, mục 10.9 Cứ tiếp tục, thấy FlyweightFactory khởi tạo sau: static FlyweightFactory album = new FlyweightFactory( ); truy cập sau: album[filename].Load(filename); Như vậy, mục cung cấp truy cập collection (bộ sưu tập) cho đối tượng chứa collection riêng tư Ví dụ: Photo Group Bây giờ, xem xét ứng dụng tạo ra hình 3-4 Mã nó, đứng trước khơng gian tên FlyweightPattern phát triển trên, thể ví dụ 3-4 Hướng dẫn biên soạn khơng gian tên riêng rẽ với chương trình có sử dụng có thảo luận mẫu Facade Chương Ví dụ 3-4 Ví dụ mẫu Flyweight—Photo Group bao gồm không gian tên FlyweightPattern using System; using System.Collections.Generic; using System.Drawing; using System.Windows.Forms; namespace FlyweightPattern { // Flyweight Pattern Judith Bishop Sept 2007 public interface IFlyweight { void Load(string filename); void Display(PaintEventArgs e, int row, int col); } public struct Flyweight : IFlyweight { // Intrinsic state Image pThumbnail; public void Load(string filename) { pThumbnail = new Bitmap("images/" + filename) GetThumbnailImage(100, 100, null, new IntPtr()); } public void Display(PaintEventArgs e, int row, int col) { e.Graphics.DrawImage(pThumbnail, col * 100 + 10, row * 130 + 40, pThumbnail.Width, pThumbnail.Height); } } public class FlyweightFactory { // Keeps an indexed list of IFlyweight objects in existence Dictionary flyweights = new Dictionary(); public FlyweightFactory() { flyweights.Clear(); } public IFlyweight this[string index] { get { if (!flyweights.ContainsKey(index)) flyweights[index] = new Flyweight(); return flyweights[index]; } } } } //============== End of namespace, start of program using System; using System.Collections.Generic; using System.Drawing; using System.Windows.Forms; using FlyweightPattern; class Client { // Shared state - the images static FlyweightFactory album = new FlyweightFactory(); // Unshared state - the groups static Dictionary allGroups = new Dictionary(); public void LoadGroups() { var myGroups = new[] { new {Name = "Garden", Members = new [] {"pot.jpg", "spring.jpg", "barbeque.jpg", "flowers.jpg"}}, new {Name = "Italy", Members = new [] {"cappucino.jpg","pasta.jpg", "restaurant.jpg", "church.jpg"}}, new {Name = "Food", Members = new [] {"pasta.jpg", "veggies.jpg", "barbeque.jpg","cappucino.jpg","lemonade.jpg" }}, new {Name = "Friends", Members = new [] {"restaurant.jpg", "dinner.jpg"}} }; // Load the Flyweights, saving on shared intrinsic state foreach (var g in myGroups) { // implicit typing allGroups.Add(g.Name, new List()); foreach (string filename in g.Members) { allGroups[g.Name].Add(filename); album[filename].Load(filename); } } } public void DisplayGroups(Object source, PaintEventArgs e) { // Display the Flyweights, passing the unshared state int row; foreach (string g in allGroups.Keys) { int col; e.Graphics.DrawString(g, new Font("Arial", 16), new SolidBrush(Color.Black), new PointF(0, row * 130 + 10)); foreach (string filename in allGroups[g]) { album[filename].Display(e, row, col); col++; } row++; } } } class Window : Form { ... tính bốn tính chúng ta: structs (c? ??u tr? ?c) Tính C# —Structs C# c? ? hai kiểu c? ??u tr? ?c để định nghĩa thu? ?c tính hoạt động: class tiếng struct biết đến C? ?c cấu tr? ?c tương tự lớp kiểu chứa thành viên... th? ?c, trường hợp đối tượng khởi tạo từ lớp C? ??u tr? ?c nhẹ th? ?c thi mà khơng chi phí Chúng đ? ?c biệt hữu ích cho c? ??u tr? ?c liệu nhỏ Những hạn chế c? ??u tr? ?c chúng khơng thể kế thừa từ kiểu kh? ?c; chúng... thành viên ch? ?c Tuy nhiên, biến c? ??u tr? ?c tr? ?c tiếp chứa liệu c? ??u tr? ?c, biến lớp chứa tham chiếu đến liệu Thể lớp c? ??u tr? ?c đối tượng Tuy nhiên, c? ??u tr? ?c gán giá trị giá trị gán chuyển, tham chiếu đến