Thiết kế C ++ hiện đại – Wikipedia

Thiết kế C ++ hiện đại: Các mẫu thiết kế và lập trình chung được áp dụng là một cuốn sách được viết bởi Andrei Alexandrescu, được xuất bản năm 2001 bởi Addison-Wesley. Nó được coi là "một trong những cuốn sách C ++ quan trọng nhất" của Scott Meyers. [1]

Cuốn sách sử dụng và khám phá một kỹ thuật lập trình C ++ được gọi là siêu lập trình mẫu. Trong khi Alexandrescu không phát minh ra kỹ thuật này, ông đã phổ biến nó cho các lập trình viên. Cuốn sách của ông chứa các giải pháp cho các vấn đề thực tế mà các lập trình viên C ++ có thể gặp phải. Một số cụm từ trong cuốn sách hiện được sử dụng trong cộng đồng C ++ như các thuật ngữ chung: C ++ hiện đại (trái ngược với phong cách C / C ++), thiết kế dựa trên chính sách và đánh máy.

Tất cả các mã được mô tả trong cuốn sách đều có sẵn miễn phí trong thư viện Loki của ông. Cuốn sách đã được tái bản và dịch sang nhiều ngôn ngữ kể từ năm 2001.

Thiết kế dựa trên chính sách [ chỉnh sửa ]

Thiết kế dựa trên chính sách còn được gọi là chính sách thiết kế lớp dựa trên chính sách hoặc lập trình dựa trên là thuật ngữ được sử dụng trong Modern C ++ Design cho cách tiếp cận thiết kế dựa trên một thành ngữ cho chính sách C ++ được gọi là . Nó đã được mô tả như là một biến thể thời gian biên dịch của mẫu chiến lược và có các kết nối với siêu lập trình mẫu C ++. Nó được phổ biến lần đầu tiên trong C ++ bởi Andrei Alexandrescu với Modern C ++ Design và với cột của ông Generic trong Tạp chí người dùng C / C ++ và nó hiện đang được liên kết chặt chẽ với C ++ và D vì nó yêu cầu trình biên dịch với sự hỗ trợ rất mạnh mẽ cho các mẫu, điều này không phổ biến trước khoảng năm 2003.

Các ví dụ trước đây của phương pháp thiết kế này, dựa trên mã chung được tham số hóa, bao gồm các mô-đun tham số (functor) của các ngôn ngữ ML, [2] và cấp phát C ++ cho chính sách quản lý bộ nhớ.

Thành ngữ trung tâm trong thiết kế dựa trên chính sách là một mẫu lớp (được gọi là lớp máy chủ ), lấy một số tham số loại làm đầu vào, được khởi tạo với các loại được người dùng chọn (gọi là chính sách các lớp ), mỗi lớp thực hiện một giao diện ngầm định cụ thể (được gọi là chính sách ) và gói gọn một số khía cạnh trực giao (hoặc chủ yếu là trực giao) của hành vi của lớp máy chủ được khởi tạo. Bằng cách cung cấp một lớp máy chủ kết hợp với một tập hợp các triển khai đóng hộp khác nhau cho mỗi chính sách, thư viện hoặc mô-đun có thể hỗ trợ số lượng kết hợp hành vi khác nhau, được giải quyết tại thời gian biên dịch và được chọn bằng cách trộn và khớp với các lớp chính sách được cung cấp khác nhau trong khởi tạo mẫu lớp máy chủ. Ngoài ra, bằng cách viết một triển khai tùy chỉnh của một chính sách nhất định, thư viện dựa trên chính sách có thể được sử dụng trong các tình huống yêu cầu các hành vi không lường trước của người thực hiện thư viện. Ngay cả trong trường hợp không sử dụng nhiều hơn một chính sách cho mỗi chính sách, việc phân tách một lớp thành các chính sách có thể hỗ trợ quá trình thiết kế, bằng cách tăng tính mô đun và làm nổi bật chính xác nơi các quyết định thiết kế trực giao được đưa ra.

Mặc dù việc lắp ráp các thành phần phần mềm từ các mô đun có thể thay thế được khác xa với khái niệm mới, thiết kế dựa trên chính sách thể hiện sự đổi mới trong cách áp dụng khái niệm đó ở mức độ (tương đối thấp) để xác định hành vi của một lớp riêng lẻ. Các lớp chính sách có một số điểm tương đồng với các cuộc gọi lại, nhưng khác ở chỗ, thay vì chỉ bao gồm một hàm duy nhất, một lớp chính sách thường sẽ chứa một số hàm (phương thức) liên quan, thường được kết hợp với các biến trạng thái hoặc các phương tiện khác như các kiểu lồng nhau. Một lớp máy chủ dựa trên chính sách có thể được coi là một loại siêu dữ liệu, lấy một tập hợp các hành vi được biểu thị bằng các kiểu làm đầu vào và trả về làm đầu ra một kiểu biểu thị kết quả của việc kết hợp các hành vi đó thành một tổng thể hoạt động. (Tuy nhiên, không giống như các siêu giao thức MPL, đầu ra thường được biểu thị bằng chính lớp máy chủ được khởi tạo, chứ không phải là một loại đầu ra lồng nhau.)

Một tính năng chính của thành ngữ là, thông thường (mặc dù không thực sự cần thiết), lớp máy chủ sẽ xuất phát từ (biến nó thành một lớp con của) mỗi lớp chính sách của nó bằng cách sử dụng ( công khai) nhiều di sản. (Các lựa chọn thay thế chỉ dành cho lớp máy chủ chỉ chứa một biến thành viên của từng loại lớp chính sách hoặc khác để kế thừa các lớp chính sách một cách riêng tư; tuy nhiên việc kế thừa công khai các lớp chính sách có một lợi thế lớn là lớp chính sách có thể thêm các phương thức mới, được kế thừa bởi lớp máy chủ được khởi tạo và có thể truy cập được đối với người dùng của nó, mà chính lớp máy chủ không cần biết đến.) Một đặc điểm đáng chú ý về khía cạnh này của thành ngữ chính sách là, liên quan đến lập trình hướng đối tượng, các chính sách đảo ngược mối quan hệ giữa lớp cơ sở và dẫn xuất lớp – trong khi trong các giao diện OOP được biểu diễn theo truyền thống bởi các lớp cơ sở (trừu tượng) và việc triển khai các giao diện của các lớp dẫn xuất, trong thiết kế dựa trên chính sách, lớp dẫn xuất (đại diện) biểu diễn các giao diện và các lớp cơ sở (chính sách) thực hiện chúng. Cũng cần lưu ý rằng trong trường hợp chính sách, quyền thừa kế công khai không thể hiện mối quan hệ is-is giữa máy chủ lưu trữ và các lớp chính sách. Mặc dù điều này theo truyền thống sẽ được coi là bằng chứng của lỗi thiết kế trong bối cảnh OOP, nhưng điều này không áp dụng trong bối cảnh của thành ngữ chính sách.

Một nhược điểm của các chính sách trong hiện tại của họ là giao diện chính sách không có biểu diễn trực tiếp, rõ ràng trong mã, mà được định nghĩa ngầm, thông qua cách gõ vịt và phải được ghi lại một cách riêng biệt và thủ công. Ý tưởng chính là sử dụng phân tích biến đổi phổ biến để phân chia loại thành giao diện và triển khai cố định, lớp dựa trên chính sách và các chính sách khác nhau. Bí quyết là để biết những gì đi vào lớp chính, và những chính sách nào nên tạo ra. Bài viết được đề cập ở trên đưa ra câu trả lời sau: bất cứ nơi nào chúng ta cần đưa ra quyết định thiết kế có thể hạn chế, chúng ta nên hoãn quyết định đó, chúng ta nên ủy thác nó cho một chính sách có tên thích hợp.

Các lớp chính sách có thể chứa triển khai, định nghĩa kiểu và vv. Về cơ bản, người thiết kế lớp mẫu chính sẽ xác định những gì các lớp chính sách sẽ cung cấp, những điểm tùy chỉnh nào họ cần thực hiện.

Có thể là một nhiệm vụ tế nhị để tạo ra một bộ chính sách tốt, chỉ cần đúng số (ví dụ: mức tối thiểu cần thiết). Các điểm tùy chỉnh khác nhau, thuộc về nhau, nên đi vào một đối số chính sách, chẳng hạn như chính sách lưu trữ, chính sách xác thực, v.v. Các nhà thiết kế đồ họa có thể đặt tên cho chính sách của họ, đại diện cho các khái niệm và không phải là các chính sách đại diện cho các hoạt động hoặc chi tiết triển khai nhỏ.

Thiết kế dựa trên chính sách có thể kết hợp các kỹ thuật hữu ích khác. Ví dụ, mẫu phương thức mẫu có thể được giải thích lại cho thời gian biên dịch, để một lớp chính có thuật toán khung, tại các điểm tùy chỉnh – gọi các hàm thích hợp của một số chính sách.

Điều này sẽ đạt được một cách linh hoạt bởi các khái niệm [3] trong các phiên bản tương lai của C ++.

Ví dụ đơn giản [ chỉnh sửa ]

Trình bày dưới đây là một ví dụ đơn giản (có thể) của chương trình hello world C ++, trong đó văn bản được in và phương pháp in được phân tách sử dụng chính sách. Trong ví dụ này, HelloWorld là một lớp máy chủ lưu trữ hai chính sách, một chính sách để chỉ định cách hiển thị một tin nhắn và một cho thông điệp thực sự được in. Lưu ý rằng việc triển khai chung là trong run () và do đó mã không thể được biên dịch trừ khi cả hai chính sách (in và thông báo) được cung cấp.

 #include    #include      mẫu   < typename   OutputPolicy   typename   LanguagePolicy   :   private   OutputPolicy   private   LanguagePolicy   {      bằng cách sử dụng   OutputPolicy  ::  19659042] bằng cách sử dụng   LanguagePolicy  ::  tin nhắn ;     công khai :       // Phương thức hành vi       void   chạy  () ] const       {          // Hai phương thức chính sách           print  ( message  ());      }  };     class   OutputPolicyWrite   {  được bảo vệ :       mẫu  < typename   MessageType >       void   print  ( ] &&   tin nhắn )   const       {[1 9659061] std  ::  cout   <<   tin nhắn   <<   std  ::  endl ;      } [196590] };    class   LanguagePolicyEnglish   {  được bảo vệ :       std  ::  chuỗi    () ] {          return   "Xin chào, thế giới!" ;      }  };     class   LanguagePolicyGerman   {  được bảo vệ  ] std  ::  chuỗi   tin nhắn  ()   const       {          return   "Hallo Welt!" ;      }       ]};     int   main  ()   {      / * Ví dụ 1 * /       typedef   HelloWorld  < OutputPolicyWriteToCout 19659028] LanguagePolicyEnglish >   HelloWorldEnglish ;         HelloWorldEnglish   hello_world ;       hello_world  ].  chạy  ();   // in "Xin chào, Thế giới!"         / * Ví dụ 2        * Không giống như vậy, nhưng sử dụng chính sách ngôn ngữ khác * /       typedef   HelloWorld  < OutputPolicyWriteToCout   LanguagePolicyGerman >   HelloWorldGerman ; ].  chạy  ();   // in "Hallo Welt!"  }  

Các nhà thiết kế có thể dễ dàng viết thêm OutputPol khâu bằng cách thêm các lớp mới với chức năng in thành viên () như Đầu ra mới.

Xem thêm [ chỉnh sửa ]

Tài liệu tham khảo [ chỉnh sửa ]

Liên kết ngoài