2013年5月16日

[C++] based 2D 座標與線段的基本架構

因為最近常需要寫一些在 2D 座標上的幾何演算法
但以前設計的架構實在不太好用,不好擴充 & 使用上也不是很方便
像是重用性不高 & 欠缺彈性,class 內也因為各種原因多了一大堆不再原本構想中的鬼東西
甚至在實作一些演算法時同一種演算法竟然要寫好幾個版本
寫到最後火氣都上來了...於是這幾天終於下定決定重新設計整個架構
以下是最後設計的架構(僅剩介面,實作都拿掉以保持整潔):
https://gist.github.com/shiniglion/5590182




基本構想如下:
1. 既然是 2D 平面座標,那表示最基本的 class 就僅只有 x , y 坐標
    如果有其他需要,那再以這個 class 為基礎繼承下去就好
    若有需要再多載四則運算的運算子
    當然,座標的 type 可能是整數或浮點數,甚至其他使用者自訂型別
    因此設計成 template 是比較適合的
     (請見 coordinate.hpp)

2. 因為有些演算法並不需要管是要 x 座標或 y 座標
    舉例來說,我要找一群座標點中,x 及 y 座標最大是多少
    最簡單的方法就是寫兩個 function 分別找 x 最大值及 y 最大值
    但這方法很明顯的欠缺彈性,且難以維護
    當演算法相當複雜時,維護起來可是會非常痛苦的
    因此,我又設計了另一個 class 將資料存取抽象化
    (請見 coordinate_access.hpp)

    其實這邊理想上是要用 function template,無奈 function template 不能使用偏特化
    因此退而求其次的改用 class template,並多載 () 運算子使之變成 Functor
    但這會帶來另一個問題:要使用還得要先產生一個 instance 才能用
    而且這種 instance 理應只需要存在一個即可
    因此我又另外創了個 access function template
    藉由兩者的結合來處理資料存取上的問題

3. 線段的設計想法大致同座標,基礎線段只會有起點與終點兩個
    然而線段會有多種變形,因此設計一個 class 叫 BasicSegment 當 base class
    而這些繼承後的線段可能會有共有的性質 (attribute)
    因此將之當成 template 的 type parameter,當使用 BasicSegment 時需指定 attribute class
    不過也有可能都不需要 attibute,因此設計了一個 BasicSegmentAttribute 其為 empty class
    (請見 basic_segment.hpp 及 segment_attribute.hpp)

4. 因為不論是 segment 或是 attribute,使用上有可能會需要到處被使用
    如果直接做 deep copy 其實是很浪費空間 & 效率的
    因此又另外設計了 handle class 裡面只有一個指向上述 class 的 pointer
    不過在 C++ 管理 pointer 最好是使用 smart pointer
    而且現在 C++ 的標準函示庫裡就有提供 std::shared_ptr 跟 std:auto_ptr 了
    沒理由不去使用他們,因此這 handle class 都是採用 std::shared_ptr 來管理
    (請見  basic_segment.hpp 及 segment_attribute.hpp 最後面即是相對應的 handle class)


利用上面的架構有做了一個簡單的測試,請見 inherit_segment.cpp
希望這樣可以提供未來的複用率以及擴充性

沒有留言:

張貼留言