Bài giảng Lập trình hướng đối tượng - Nguyên lý thiết kế và mẫu thiết kế

Tầng cao nhất: mô tả hình dạng và cấu trúc toàn thể của phần mềm

Tầng tiếp theo: kiến trúc liên quan tới mục đích sử dụng của phần mềm

Tầng tiếp theo: kiến trúc của các module và các kết nối giữa chúng.

mẫu thiết kế, package, component, class

đây là tầng chúng ta quan tâm trong chương này

 

ppt37 trang | Chuyên mục: Lập Trình Hướng Đối Tượng | Chia sẻ: dkS00TYs | Lượt xem: 2263 | Lượt tải: 3download
Tóm tắt nội dung Bài giảng Lập trình hướng đối tượng - Nguyên lý thiết kế và mẫu thiết kế, để xem tài liệu hoàn chỉnh bạn click vào nút "TẢI VỀ" ở trên
 cùng một khoảng thời gian module “khởi tạo” để khởi tạo các giá trị Giải quyết: mỗi đối tượng nên có constructor và destructor void initializeData() { font = "times"; windowSize = "200,400"; foo.name = "Not Set"; foo.size = 12; foo.location = "/usr/local/lib"; } Các mức độ kết dính 4. Kết dính qui trình – procedural cohesion liên kết các thành phần có quan hệ về mặt quy trình hoặc thuật toán mỗi thành phần hoạt động trên các dữ liệu khác nhau có thể tách thành các module theo trình tự thời gian. 5. Kết dính tuần tự – sequential cohesion một chuỗi thao tác trên cùng một dữ liệu theo thứ tự nhất định, output của một thao tác là input cho thao tác tiếp theo. Các mức độ kết dính 6. Kết dính thông tin – communication cohesion module thực hiện một số hành động, mỗi hành động có đầu vào và mã độc lập, nhưng tất cả sử dụng cùng một cấu trúc dữ liệu. v.d. cấu trúc sales_region_table và các thao tác: init_table(), update_table(), print_table() 7. Kết dính chức năng – functional cohesion mọi thành phần của module đều nhằm phục vụ một nhiệm vụ rõ ràng duy nhất. v.d. một hàm thực hiện đúng một thao tác get_engine_temperature(), add_sales_tax() Các mức độ ghép cặp Theo thứ tự từ cao đến thấp Ghép cặp nội dung – Internal Data Coupling Ghép cặp điều khiển – Control Coupling Ghép cặp dữ liệu chung – Common/Global-data Coupling Ghép cặp cấu trúc – Stamp/Data-structure Coupling Ghép cặp dữ liệu – Data Coupling (tốt nhất) Không ghép cặp – các module độc lập nếu tất cả các module đều độc lập thì chương trình không hoạt động Các mức độ ghép cặp Ghép cặp nội dung một module trực tiếp sửa đổi dữ liệu của một module khác Ghép cặp điều khiển một module dùng cờ điều khiển để bảo module kia phải thực hiện nhiệm vụ gì Các mức độ ghép cặp Ghép cặp điều khiển class Lamp { static const int ON = 0; void setLamp( int setting ) { if ( setting == ON ) //turn light on else if ( setting == 1 ) // turn light off else if ( setting == 2 ) // blink } } ... Lamp reading = new Lamp(); reading.setLamp( Lamp.ON ); reading.setLamp)( 2 ); class Lamp { void on() {//turn light on } void off() {//turn light off } void blink() {//blink } } ... Lamp reading = new Lamp(); reading.on(); reading.blink(); Các mức độ ghép cặp Ghép cặp dữ liệu chung hai module liên lạc với nhau qua dữ liệu toàn cục Ghép cặp cấu trúc liên lạc bằng một cấu trúc dữ liệu được truyền làm tham số một tham số lưu trữ tất cả truyền nhiều thông tin hơn cần thiết Ghép cặp dữ liệu (tốt nhất) liên lạc bằng truyền tham số, nhưng chỉ truyền những thông tin cần thiết Cohesion & Coupling Tóm lại một module được coi là kết dính tốt nếu mọi thứ đều hướng về một mục đích trung tâm một module được coi là ghép cặp tốt nếu nó chỉ phụ thuộc tốt thiểu vào các module khác không cần biết về cài đặt của một module nào khác gọi các phương thức public chứ không sử dụng các thành viên dữ liệu của lớp khác chỉ dùng đến ít phương thức của các lớp khác, quy trình gọi chúng cũng đơn giản Kiến trúc phần mềm và sự phụ thuộc Thoái hóa thiết kế Ban đầu: thiết kế đẹp, gọn, thuyết phục Yêu cầu thay đổi, chương trình thay đổi theo thiết kế mất dần tính trong sáng code ngày càng khó bảo trì muốn thiết kế lại thiết kế lại, mọi chuyện lại như cũ lại muốn thiết kế lại Triệu chứng thoái hóa từ bên trong cứng nhắc phần mềm khó sửa đổi, kể cả những sửa đổi đơn giản, mỗi thay đổi kéo theo một chuỗi các sửa đổi khác tại các phần phụ thuộc. dễ đổ vỡ xu hướng đổ vỡ nhiều nơi mỗi khi được sửa đổi thường đổ vỡ tại những nơi không có liên quan về khái niệm bất động các thành phần không tái sử dụng được bầy nhầy khi cần sửa, khó khăn nếu vừa sửa vừa bảo vệ chất lượng thiết kế sửa theo kiểu hack thì dễ hơn. Nguyên nhân của thoái hóa sự thay đổi của yêu cầu theo hướng mà thiết kế ban đầu không dự tính trước tạo ra các phụ thuộc mới không dự tính trước 4 dấu hiệu thoái hóa đều là kết quả trực tiếp hoặc gián tiếp của các phụ thuộc không hợp lý giữa các module kiến trúc phụ thuộc xuống cấp thì khả năng bảo trì phần mềm cũng giảm theo. để chặn trước xuống cấp của kiến trúc phụ thuộc: tạo các tường lửa ngăn chặn không cho các quan hệ phụ thuộc vượt qua hầu hết các nguyên lý và kỹ thuật thiết kế HĐT phục vụ mục đích trên Nguyên lý mở đóng(The Open Closed Principle - OCP) A module should be open for extension but closed for modification các module nên được thiết kế sao cho chúng có thể được mở rộng mà không cần sửa mã nguồn. chỉ cần thêm code mới chứ không cần sửa code cũ trừu tượng hóa là chìa khóa cho nguyên lý này. Một số kỹ thuật để đạt được OCP đa hình động đa hình tĩnh (template) The Open Closed Principle - OCP struct Modem { enum Type {hayes, courrier, ernie) type; }; struct Hayes { Modem::Type type; // Hayes related stuff }; struct Courrier { Modem::Type type; // Courrier related stuff }; struct Ernie { Modem::Type type; // Ernie related stuff }; void logOn(Modem& m, string& pno, string& user, string& pw) { if (m.type == Modem::hayes) DialHayes((Hayes&)m, pno); else if (m.type == Modem::courrier) DialCourrier((Courrier&)m, pno); else if (m.type == Modem::ernie) DialErnie((Ernie&)m, pno) // ...you get the idea } The Open Closed Principle - OCP Nhược điểm: mỗi khi có thêm một loại modem được bổ sung vào chương trình thì: hàm logOn() phải bị sửa cài đặt của mỗi modem phải được biên dịch lại do phụ thuộc kiểu Modem::Type mỗi lần cần làm gì đó liên quan đến modem thì phải cần tới một chuỗi if-else mỗi khi cần sửa quy trình thao tác với modem hoặc bổ sung loại modem mới, phải duyệt toàn bộ chương trình tìm các chuỗi if-else nói trên để sửa. The Open Closed Principle - OCP Đa hình động MODEM + dial()+ send()+ recv()+ hang up() ... ERNIE’S MODEM “function”logOn The Open Closed Principle - OCP Đa hình động module dưới đây có thể được mở rộng (thêm các loại modem mới) mà không cần sửa code class Modem { public: virtual void Dial(const string& pno) = 0; virtual void Send(char) = 0; virtual char Recv() = 0; virtual void Hangup() = 0; }; void logOn(Modem& m, string& pno, string& user, string& pw) { m.Dial(pno); // you get the idea. } The Open Closed Principle - OCP Đa hình tĩnh – sử dụng template module dưới đây có thể được mở rộng (thêm các loại modem mới) mà không cần sửa code template void logOn(MODEM& m, string& pno, string& user, string& pw) { m.Dial(pno); // you get the idea. } Nguyên lý thay thếLiskov Substitution Principle - LSP Subclasses should be substitutable for their base classes Lớp con cần thay thế được lớp cha một user của lớp cha cần tiếp tục hoạt động bình thường nếu được truyền một lớp dẫn xuất của lớp đó void user(Base& b); ... Derived d; user(d); class HinhChuNhat { public: virtual void setChieuDai(int cd) {chieuDai = cd}; virtual void setChieuRong(int); virtual int getDienTich(); private: int chieuDai; int chieuRong; }; void f(HinhChuNhat & h) { h.setChieuDai(3); h.setChieuRong(2); assert (6 == h.getDienTich()); } class HinhVuong : public HinhChuNhat { public: void setChieuDai(int cd) { canh = cd}; void setChieuRong (int cd) { canh = cd}; private: int canh; }; Nguyên lý phụ thuộc nghịchDependency Inversion Principle - DIP Depend upon Abstractions. Do not depend upon concretions Phụ thuộc vào cái trừu tượng, không phụ thuộc vào cái cụ thể. phụ thuộc vào các giao diện hoặc các hàm và lớp trừu tượng, không phụ thuộc vào các hàm và lớp cụ thể OCP là mục đích của thiết kế hướng đối tượng, còn DIP là cơ chế thực hiện là nguyên lý thiết kế cho COM, COBRA, EJB,… Dependency Inversion Principle Cấu trúc phụ thuộc của một kiến trúc thủ tục Dependency Inversion Principle Cấu trúc phụ thuộc của một kiến trúc hướng đối tượng Dependency Inversion Principle Lý do: những gì cụ thể hay thay đổi, những gì trừu tượng ít thay đổi hơn nhiều những thứ trừu tượng là những khớp nối, nơi thiết kế có thể mở rộng hoặc chuyển hướng mà không phải sửa đổi chúng (OCP). Lưu ý: vẫn có thể dựa vào những thứ cụ thể nhưng bền vững, chẳng hạn thư viện string.h của C tuy nhiên, nếu phải chuyển sang UNICODE thì sẽ rất rắc rối Nguyên lý tách giao diệnInterface Segregation Principle - ISP Many client specific interfaces are better than one general purpose interface nếu ta có một lớp có nhiều loại client, thay vì chất tất cả các phương thức các client cần vào trong lớp đó, ta tạo các giao diện cụ thể cho mỗi loại client và cho lớp đó đa thừa kế chúng. Mỗi khi cần sửa một trong các phương thức dành cho client A, các phương thức dành cho client B và client C có thể bị ảnh hưởng có thể phải biên dịch lại và triển khai lại Interface Segregation Principle - ISP Interface Segregation Principle - ISP Các nguyên lý về kiến trúc góiPrinciples of Package Architecture Các nguyên lý về kết dính gói REP. quản lý phiên bản theo gói thì cũng tái sử dụng theo gói CCP. các lớp cùng thay đổi thì cũng cùng gói CRP. các lớp không được cùng tái sử dụng thì không nên nhóm lại với nhau Các nguyên lý về ghép cặp gói ADP. các quan hệ phụ thuộc giữa các gói không được tạo chu trình SDP. một gói chỉ nên phụ thuộc vào các gói có độ bền vững cao hơn SAP. các gói bền vững nên là các gói trừu tượng Mẫu thiết kế Khi làm theo các nguyên lý kể trên, người ta thấy một số cấu trúc được lặp đi lặp lại. Mẫu thiết kế là lời giải tốt đã được dùng nhiều cho một bài toán thường gặp Abstract Server Khi một client phụ thuộc trực tiếp vào một server, nguyên lý DIP bị vi phạm thay đổi đối với server sẽ lan tới client client không thể dễ dàng sử dụng các server tương tự Giải pháp: chèn một giao diện trừu tượng vào giữa client và server có thể dùng các cài đặt mới của server cho một client cũ Khi không thể chèn giao diện trừu tượng, có thể dùng một ADAPTER để kết nối giao diện trừu tượng với server các phương thức của adapter chỉ gọi hàm của server, lấy kết quả và trả về giá trị theo dạng mong muốn. Adapter Kết luận các nguyên lý thiết kế và mẫu thiết kế nhằm hỗ trợ xây dựng các kiến trúc phần mềm linh hoạt, vững chãi, tái sử dụng được, và phát triển được đã giúp đỡ rất nhiều trong việc phát triển phần mềm đây mới chỉ là giới thiệu sơ qua phải đọc thêm tài liệu để có cái nhìn đầy đủ. rất quan trọng 

File đính kèm:

  • pptBài giảng Lập trình hướng đối tượng - Nguyên lý thiết kế và mẫu thiết kế.ppt
Tài liệu liên quan