Thiết kế phần mềm hướng đối tượng

15 411 0
Thiết kế phần mềm hướng đối tượng

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

Thiết kế phần mềm HDT GVHD: Thầy Nguyễn Trần Thi Văn Nhóm 4: Vũ Minh Hải 07110037 Lâm Chí Hiền 07110041 Nguyễn Công Hiếu 07110045 Chiếng Mành Sâm 07110100 Prototype pattern I. Prototype pattern là gì? 1. Thuộc nhóm Creational Patterns(Abstract factory, Builder, Factory method, Prototype và Singleton). 2. Prototype là mẫu thiết kế chỉ định ra một đối tượng đặc biệt để khởi tạo, nó sử dụng một thể nghiệm sơ khai rồi sau đó sao chép ra các đối tượng khác từ mẫu đối tượng này. II. Mục đích và ý nghĩa,tính chất: Prototype Pattern giúp cho việc khởi tạo object bằng một object nguyên mẫu (prototype), là copy của object “mẫu” đó. Ý tưởng của mẫu là chúng ta được cung cấp một object và sẽ dùng chính object này để như là một hình mẫu (template) khi cần tạo lập một đối tượng mới. Việc tạo lập object mới sẽ dựa trên object mẫu mà không sử dụng toán tử new hoặc constructor … được cụng cấp bởi ngôn ngữ lập trình. Lý do là chúng ta không biết được thông tin nội tại chi tiết bên trong object và object có thể che dấu và chỉ cung cấp ra bên ngoài một lượng thông tin giới hạn. Do vậy ta không thể dùng toán tử new và sao chép những dữ liệu được object cung cấp (vốn không đầy đủ) cho một object mới. Cách tốt nhất là để cho chính object “mẫu” tự xác định thông tin và dữ liệu sao chép. Tính chất: • Tần suất sử dụng thấp hoặc trung bình • Đặc trưng chủ yếu của prototype là dùng phương thức clone() để sao chép đối tượng. • Có liên quan chặc chẽ với mẫu Abstract Factory III. Cấu trúc: - Prototype: Cung cấp interface để copy chính bản thân nó (phương thức clone()) - ConcreatePrototype: Implement interface được cung cấp bởi Prototype để copy chính bản thân nó. (thể hiện cụ thể phương thức clone()) - Client: Tạo một object mới bằng cách yêu cầu prototype copy chính bản thân nó. IV. Ưu và nhược điểm: Prototype ẩn đi những lớp con rời rạc từ phía client, do vậy làm giảm đi số lớp con mà client cần biết. Hơn thế nữa pattern này làm cho client hoạt động với những lớp con cụ thể mà không phải thay đổi gì. Sau đây là một vài lợi ích khác của prototype pattern: - Thêm và loại bỏ lớp concreate lúc run-time: Prototype hợp nhất quá trình khởi tạo một object mới vào trong hệ thống đơn giản chỉ bằng cách đăng ký một thực thể nguyên mẫu với client. Điều đó linh động hơn một chút so với các mẫu kiến tạo khác bởi vì client có thể cài đặt và loại bỏ các nguyên mẫu tại thời điểm run-time. - Khởi tạo object mới bằng cách thay đổi một vài attribute của object (các object có ít điểm khác biệt nhau): Một hệ thống linh động sẽ để cho chúng ta tự define một hành động nào đó thông qua sự kết hợp với một object (nghĩa là một phương thức của một class) hơn là define một class mới. Client có thể thể hiện một tác động khác bằng cách ủy quyền cho lớp prototype. Đồng thời cách thức khởi tạo này cũng giúp cho chúng ta khai báo một “lớp mới” mà không phải lập trình gì cả. Thực tế thì việc copy một nguyên mẫu giống như việc khởi tạo một object từ một class mới. Prototype pattern giúp giảm số lớp mà hệ thống cần dùng. - Khởi tạo object mới bằng cách thay đổi cấu trúc: Rất nhiều ứng dụng xây dựng hệ thống từ nhiều phần và các phần con. Các phần con lại khởi tạo từ nhiều phần con khác (chia nhỏ bài toán). Prototype pattern cũng hỗ trợ điều này. Nghĩa là các phần có đó có thể được khởi tạo từ việc copy một nguyên mẫu từ một “cấu trúc” khác. Miễn là các phần kết hợp đều thể hiện Clone() và được sử dụng với cấu trúc khác nhau làm nguyên mẫu. - Giảm việc phân lớp: Đôi khi hệ thống quá phức tạp vì có quá nhiều class, và cây thừa kế của lớp khởi tạo có quá nhiều lớp song song cùng mức. Prototype pattern rõ ràng làm giảm số lớp và sự phức tạp của cây thừa kế (class hierarchy) Một điểm hạn chế của prototype pattern là đôi khi việc phải implement mỗi phương thức clone() của mỗi lớp con của Prototype sẽ gặp khó khăn. Ví dụ như việc implement clone() sẽ khó khăn khi mà những object nội hàm của chúng không hỗ trợ việc copy hoặc có một reference (không copy được reference) V. Implementation (ex) using System; using System.Collections.Generic; namespace DoFactory.GangOfFour.Prototype.RealWorld { class MainApp { static void Main() { ColorManager colormanager = new ColorManager(); colormanager["red"] = new Color(255, 0, 0); colormanager["green"] = new Color(0, 255, 0); colormanager["blue"] = new Color(0, 0, 255); colormanager["angry"] = new Color(255, 54, 0); colormanager["peace"] = new Color(128, 211, 128); colormanager["flame"] = new Color(211, 34, 20); Color color1 = colormanager["red"].Clone() as Color; Color color2 = colormanager["peace"].Clone() as Color; Color color3 = colormanager["flame"].Clone() as Color; Console.ReadKey(); } } abstract class ColorPrototype { public abstract ColorPrototype Clone(); } class Color : ColorPrototype { private int _red; private int _green; private int _blue; // Constructor public Color(int red, int green, int blue) { this._red = red; this._green = green; this._blue = blue; } // Create a shallow copy public override ColorPrototype Clone() { Console.WriteLine( "Cloning color RGB: {0,3},{1,3},{2,3}", _red, _green, _blue); return this.MemberwiseClone() as ColorPrototype; } } class ColorManager { private Dictionary<string, ColorPrototype> _colors = new Dictionary<string, ColorPrototype>(); public ColorPrototype this[string key] { get { return _colors[key]; } set { _colors.Add(key, value); } } } } Out put Cloning color RGB: 255, 0, 0 Cloning color RGB: 128,211,128 Cloning color RGB: 211, 34, 20 VI. Các mẫu liên quan: • Đôi khi các thiết kế trong Creational Patterns chồng chéo lên nhau. Có những trường hợp cả hai (Phototype và Abstract Factory) đều phù hợp. Trường hợp khác lại bổ sung cho nhau.,cụ thể : Abstract Factory có thể lưu trữ một tập hợp các bản mẫu (Phototype) để từ đó nhân bản và trả lại các đối tượng sản phẩm .Abstract Factory, Builder , và Prototype có thể sử dụng Singleton trong việc triển khai thực hiện.Các lớp Abstract Factory thường được thực hiện với Factory Methods ( tạo thông qua kế thừa ), nhưng chúng cũng có thể được thực hiện bằng cách sử dụng Phototype( tạo thông qua các ủy quyền cho các đối tượng tự sao chép chính bản thân nó ) • Thông thường ,các thiết kế bắt đầu bằng cách sử dụng FactoryMethod (ít phức tạp, khả năng tùy biến cao, các lớp con nhiều),và có thể cải tiến thành Abstract Factory, Phototype hoặc Builder (linh hoạt hơn và cũng phức tạp hơn ) khi nhà thiết kế cần sự linh hoạt nhiều hơn. • Phototype không yêu cầu lớp con ,nhưng lại cần một hàm khởi tạo (hàm clone() copy đối tượng). Factory Method lại yêu cầu lớp con nhưng không cần hàm khởi tạo. • Phototype thường có lợi khi được sử dụng trong những thiết kế composite và decorator pattern . • Các nguyên tắc có thể là bạn sẽ cần phải sao chép một đối tượng khi bạn muốn tạo ra một đối tượng trong thời gian chạy mà nó là một bản sao thực sự của đối tượng mà bạn đang sao chép. Bản sao thực sự có nghĩa là tất cả các thuộc tính của đối tượng vừa được tạo phải giống với đối tượng được sao chép. Nếu bạn có thể khởi tạo sử dụng new() , bạn sẽ nhận được một đối tượng với tất cả các thuộc tính có giá trị ban đầu.Ví dụ, nếu bạn đang thiết kế một hệ thống cho các giao dịch tài khoản ngân hàng thực hiện, sau đó bạn sẽ muốn tạo một bản sao của các đối tượng nắm giữ thông tin tài khoản của bạn, thực hiện các giao dịch trên nó, và sau đó thay thế các đối tượng ban đầu với một trong những sửa đổi. Trong trường hợp này, bạn sẽ muốn sử dụng clone () thay vì new(). VII. Một số ví dụ cụ thể: • Ví dụ, nếu bạn đang thiết kế một hệ thống cho các giao dịch tài khoản ngân hàng thực hiện, sau đó bạn sẽ muốn tạo một bản sao của các đối tượng nắm giữ thông tin tài khoản của bạn, thực hiện các giao dịch trên nó, và sau đó thay thế các đối tượng ban đầu với một trong những sửa đổi. Trong trường hợp này, bạn sẽ muốn sử dụng clone () thay vì new(). • Xây dựng cho một trò chơi có sử dụng một mê cung với các vật cản khác nhau mà nhân vật phải vượt qua. Ta cần một phương pháp nhanh chóng tạo ra các bản đồ phức tạp bằng cách sử dụng các đối tượng: bức tường, cửa, lối đi, phòng Thay vì cứng nhắc dùng hàm khởi tạo (new()) cho từng đối tượng, ta dùng cách hay hơn là sử dụng prototype, phương thức createMaze(tạo mê cung ) sẽ nhận tham số từ những bản mẫu phòng, tường, Vì thế bản đồ dễ dàng thay đổi bằng cách thay thế những đối tượng mẫu với những bản đồ khác nhau. Client là phương thức createMaze(tạo mê cung ) và các lớp ConcretePrototype sẽ tạo ra bản sao cho các đối tượng khác nhau. • Giả sử chúng ta đang làm một phân tích bán hàng trên một tập hợp các dữ liệu từ cơ sở dữ liệu. Thông thường, ta sẽ sao chép thông tin từ cơ sở dữ liệu, đóng gói nó vào một đối tượng và phân tích trên đối tượng đó. Nhưng nếu có thể có những phân tích khác trên cùng một bộ dữ liệu,ta phải đọc cơ sở dữ liệu một lần nữa và tạo ra một đối tượng mới. Điều đó thật sự không cần thiết và hao tổn nhiều tài nguyên. . Nếu chúng ta sử dụng các mô hình prototype : đối tượng được sử dụng trong phân tích đầu tiên sẽ được nhân bản và được sử dụng cho các phân tích khác. Khách hàng là ở đây một trong những phương pháp gói gọn thông tin từ CSDL vào một đối tượng. The ConcretePrototype classes will be classes that, from the object created after extracting data from the database, will copy it into objects used for analysis. Các lớp ConcretePrototype sẽ sao chép các đối tượng đó vào để thực hiện các phân tích. VIII. Một số điểm cần lưu ý khi thực hiện: • Sử dụng một prototype manager: Khi ứng dụng có nhiều nguyên mẫu .Những nguyên mẫu đó có thể được tạo ra và phá hủy động, một bản của nguyên mẫu nên được giữ lại.Vì thế cần phải có một prototype manager để quản lý các nguyên mẫu với từng khóa nhất định, tìm kiếm một nguyên mẫu với một khóa nào đó, loại bỏ một nguyên mẫu đã tồn tại, v .v Các client sẽ sử dụng giao diện của prototype manager để thao tác với nguyên mẫu tại thời gian chạy và phải yêu cầu sự cho phép trước khi sử dụng phương pháp Clone (). Không có sự khác biệt nhiều giữa việc sử dụng một nguyên mẫucó prototype manager và factory method sử dụng các nhà máy khởi tạo.Có lẽ sự khác biệt chỉ ở sự thực thi. • Thực thi Clone(): Một vấn đề nhỏ xuất hiện khi nói về deep or shallow a clone (nhân bản sâu và nông): deep-clone sao chép các biến trong đối tượng gốc còn shallow-clone chia sẻ các biến đó giữa bản gốc và bản sao. Thông thường shallow-clone là đủ và đơn giản nhưng khi sao chép những bản mẫu phức tạp ta nen dùng deep-clone để bản sao và bản mẫu có thể độc lập với nhau và bản sao có các thành phần của nó là bản sao của bản mẫu. • Khởi tạo bằng sao chép: Có những trường hợp khi các thành phần bên trong của bản sao nên được khởi tạo sau khi bản sao được tạo ra. Điều này xảy ra bởi vì các thành phần đó chưa được "khởi tạo" bằng phương pháp Clone(). Trong trường hợp này việc khởi tạo nên được thực hiện bằng cách sử dụng thiết lập và cài đặt lại các phương thức của lớp mẫu thử nghiệm hoặc sử dụng một phương thức khởi tạo lại các thông số của thành phần đó. • Chú ý: -Prototype Manager - thường là một Hashtable giữ đối tượng để nhân bản. Khi sử dụng nó, nguyên mẫu trở thành một factory method có sử dụng sao chép thay vì khởi tạo. - Deep Clones và Shallow Clones- khi chúng ta nhân bản đối tượng phức tạp, trong đó có các đối tượng khác, chúng ta phải đảm bảo rằng chúng cũng được nhân bản. Ta có thể sao chép các đối tượng con (deep-clone) hoặc chúng ta có thể cùng tham chiếu cho chúng, và chia sẻ chúng giữa các đối tượng sao chép. - Khởi tạo nội bộ - có những tình huống nhất định khi đối tượng cần phải được khởi tạo sau khi bản sao được tạo ra. Singleton pattern I. Định nghĩa: II. Động lực III. Trường hợp sử dụng IV. Cấu trúc V. Ưu nhược điểm VI. Cách thực hiện VII. Ví dụ VIII. Pattern lien quan I. Định nghĩa: • Vấn đề đặt ra: Ta hãy xem xét về một đối tượng quản lý tài nguyên trong các ứng dụng. Mỗi ứng dụng có một bộ quản lý tài nguyên, nó cung cấp các điểm truy cập cho các đối tượng khác trong ứng dụng. Các đối tượng (ta gọi là đối tượng khách) có thể thực hiện lấy ra từ bộ quản lý tài nguyên những gì chúng cần và thay đổi giá trị nằm bên trong bộ quản lý tài nguyên đó. Để truy cập vào bộ quản lý tài nguyên đối tượng khách cần phải có một thể nghiệm của bộ quản lý tài nguyên, như vậy trong một ứng dụng sẽ có rất nhiều thể nghiệm của bộ quản lý tài nguyên được tạo ra. class ResourceManager { private: int x; public: ResourceManager(){x =0; } void SetX(int _x){ x = _x;} void GetX(){ return x;} } class ClientObject1 { public: void DoSomething() { ResourceManager rm; printf(“x = %d”,rm.GetX()); x = 100; } } class ClientObject2 { public: void DoSomething() { ResourceManager rm; printf(“x = %d”,rm.GetX()); x = 500; } } Trong ví dụ trên hàm DoSomething() của ClientObject1 khi truy cập vào đối tượng thuộc lớp ResourceManager sẽ in ra màn hình X = 0; và đặt vào đó x = 100; Sau đó hàm Dosomething() của ClientObject2 khi truy cập vào đối tượng thuộc lớp ResourceManager sẽ in ra màn hình X = 0 và đặt vào đó x = 500; Rõ ràng là tài nguyên mà các đối tượng khách truy cập vào không thể hiện sự thống nhất lẫn nhau. Điều mà lẽ ra khi giá trị x trong ResourceManager bị ClientObject1 thay đổi thì ClientObject2 phải nhận biết được điều đó và in ra màn hình X=100 . Nhưng theo logic cài đặt ở trên thì khi đối tượng thuộc lớp ClientObject1 truy cập đến ResourceManager nó tạo ra một Instance và đặt thuộc tính x = 100; Đối tượng ClientObject2 truy cập đến ResourceManager nó tạo ra một Instance và đặt thuộc tính x = 500. Hai Instance này hoàn toàn độc lập nhau về vùng nhớ do đó mà tài nguyên x mà nó quản lý cũng là 2 tài nguyên độc lập với nhau.Vấn đề đặt ra là phải tạo ra một bộ quản lý tài nguyên hoàn hảo tạo ra mọi thể nghiệm giống nhau tại nhiều nơi nhiều thời điểm khác nhau trong ứng dụng.Singleton cung cấp cho ta một cách giải quyết vấn đề này. • Singleton đảm bảo rằng một class có duy nhất một thực thể (instance) hay đối tượng (object) và cung cấp một cách thức truy nhập toàn cục để có thể từ bất kỳ đâu cũng lấy được instance duy nhất đó. Chúng ta cũng gọi thực thể duy nhất đó là thực thể chính (solely) của class đó. • Đối với một vài class thì việc chỉ có duy nhất một instance (object) là rất quan trọng. Mặc dù có rất nhiều máy in trong hệ thống nhưng chỉ có một printer spooler. Cũng chỉ có một file system và một windows manager. Cũng như trong thiết kế connection pool thì chỉ có một connection pool quản lý nhiều connection. Hộp thoại Find, một ví dụ cụ thể cho Singleton Pattern chỉ một hộp thoại duy nhất xuất hiện dù chọn menu nhiều lần. II. Động lực: • Làm thế nào để chúng ta đảm bảo một class chỉ có một thể hiện duy nhất và dễ dàng truy nhập được? Một object toàn cục có thể làm cho nó dễ dàng truy nhập được nhưng không ngăn cấm bạn tạo thêm nhiều object khác. • Một giải pháp tốt hơn là làm cho class đó tự bản thân nó có thể điều khiển được thực thể chính của nó. Class đó có thể đảm bảo rằng không có thực thể khác được tạo ra (bằng cách chặn đứng các yêu cầu tạo object mới) và cung cấp cách thức để truy nhập được thực thể chính của nó. Đó là singleton pattern. III. Trường hợp sử dụng: • Trong trường hợp chỉ cần một thể hiện duy nhất của một lớp. • Khi thể hiện duy nhất khả mở thông qua việc kế thừa, người dùng có thể sử dụng thể hiện kế thừa đó mà không cần thay đổi các đoạn mã của chương trình. IV. Cấu trúc: V. Ưu nhược điểm: • Quản lý việc truy cập tốt hơn vì chỉ có một thể hiện đơn nhất. • Cho phép cải tiến lại các tác vụ (operations) và các thể hiện (representation) do pattern có thể được kế thừa và tùy biến lại thông qua một thể hiện của lớp con • Quản lý số lượng thể hiện của một lớp, không nhất thiết chỉ có một thể hiện mà có số thể hiện xác định. • Khả chuyển hơn so với việc dùng một lớp có thuộc tính là static, vì việc dùng lớp static chỉ có thể sử dụng một thể hiện duy nhất, còn Singleton Pattern cho phép quản lý các thể hiện tốt hơn và tùy biến theo điều kiện cụ thể. VI. Cách thực hiện: Thực hiện Singleton Pattern theo các bước sau: • Định nghĩa một thuộc tính private và static trong lớp Singleton: instance. • Định nghĩa tất cả các constructor thành protected hoặc private để người dùng không thể tạo thực thể trực tiếp từ lớp. • Định nghĩa một accessor public và static trong lớp: getInstance(). • Thực hiện "lazy initialization" (khởi tạo chậm, khởi tạo khi yêu cầu) trong getInstance(): trả về một thể hiện mới hay một giá trị rỗng (null) tùy thuộc vào một biến boolean, biến này như một cờ hiệu dùng báo xem lớp đó đã có thể hiện hay chưa. • Clients chỉ dùng getInstance() để tạo đối tượng của lớp Singleton. • Thừa kế cũng được hỗ trợ, nhưng không che (overridden) các phương thức static: lớp cơ sở phải được khai báo là friend với lớp dẫn xuất (để truy xuất đến protected constructor).  Thực hiện (Implement) của một mẫu singleton phải đáp ứng các thể hiện duy nhất và nguyên tắc truy cập toàn cầu. Nó đòi hỏi một cơ chế để truy cập các thành viên lớp singleton mà không tạo ra một lớp đối tượng và cơ chế để tồn giá trị của các thành viên lớp giữa các đối tượng lớp.Các mẫu singleton được thực hiện bằng cách tạo ra một lớp với một phương thức để tạo ra một thể hiện mới của lớp nếu không tồn tại. Nếu một thể hiện đã tồn tại, nó chỉ đơn giản trả về một tham chiếu đến đối tượng đó. Để chắc chắn rằng đối tượng không thể khởi tạo bất kỳ cách nào khác, các Constructors được thực hiện bảo vệ (make Protected) (bởi vì tái sử dụng và kiểm tra các đơn vị có thể cần truy cập vào các Constructor ). Lưu ý những khác biệt giữa một trường hợp tĩnh đơn giản của một lớp và một singleton: mặc dù singleton có thể được thực hiện như một thể tĩnh, nó cũng có thể được xây dựng uể oải (lazily constructed), không đòi hỏi bộ nhớ hoặc các nguồn lực cho đến khi cần thiết. Một khác biệt đáng chú ý là các lớp thành viên tĩnh không thể thực hiện một giao diện, trừ khi có giao diện đơn giản chỉ là một dấu hiệu. Vì vậy, nếu lớp này phải thực hiện một hợp đồng biểu diễn bằng một giao diện, nó thực sự có phải là một singleton. [...]... System.out.println(this._strName); VIII Pattern lien quan: • Abstract Factory: thường dùng để trả về các đối tượng duy nhất • Builder: dùng tạo một đối tượng phức tạp, trong đó Singleton được dùng để tạo một đối tượng truy xuất tổng quát • Prototype: dùng để sao chép một đối tượng, hoặc tạo ra một đối tượng khác từ prototype (nguyên mẫu) của nó, trong đó Singleton được dùng để chắc chắn chỉ có một prototype... MySingleton(); }; MySingleton::MySingleton() { //… Singleton::Register(“MySingleton”, this); } Static MySingleton theSingleton; VII Ví dụ: • Implement 1 class cho phép lấy duy nhất 1 đối tượng kết nối tới 1 database (chia sẻ kết nối – phù hợp các ứng dụng web) namespace SamplePatterns.Signleton { public class ClsConnection { // Instance of object private static SqlConnection instance; // Connection string . Singleton). 2. Prototype là mẫu thiết kế chỉ định ra một đối tượng đặc biệt để khởi tạo, nó sử dụng một thể nghiệm sơ khai rồi sau đó sao chép ra các đối tượng khác từ mẫu đối tượng này. II. Mục đích. trả về các đối tượng duy nhất. • Builder: dùng tạo một đối tượng phức tạp, trong đó Singleton được dùng để tạo một đối tượng truy xuất tổng quát. • Prototype: dùng để sao chép một đối tượng, hoặc. một đối tượng quản lý tài nguyên trong các ứng dụng. Mỗi ứng dụng có một bộ quản lý tài nguyên, nó cung cấp các điểm truy cập cho các đối tượng khác trong ứng dụng. Các đối tượng (ta gọi là đối

Ngày đăng: 06/05/2015, 14:58

Từ khóa liên quan

Tài liệu cùng người dùng

Tài liệu liên quan