簡體   English   中英

設計問題:如何最好地使用構圖

[英]DESIGN PROBLEM: How to use composition the best

我正在做一個項目,對它的設計有些懷疑。 我怎樣才能最好地設計以下問題(在 JAVA 中):

Class A具有以下屬性:

  • HashSet of Pixels,其中每個像素的 x,y 坐標和值 v 介於 0-1 之間。
  • class B 的實例。

Class B與以下 function:

  • 一個 function 獲取一個像素並返回其左鄰居。

當我在 class 中時,AI 想在 A 中的每個像素上使用 B.function 並僅當它不存在時才將其添加到 HashSet 中。 問題是,我不想將主題集發送到ZC1C425268E68385D1AB5074C174F14F14Z,從ZC1C425268E68E68385D1AB5074C174C17A94F14的情況下返回新的Pixel新實例(如果已經存在),那么它可能已經存在了這一點,這是有多糟糕的。像素)。

我還有什么其他選擇?

由於您使用Set<Pixel>必須創建新的Pixel實例來檢查它是否存在於集合中。

如果在調用B.function方法后集合包含N個元素,您將創建額外的NPixel節點。 如果所有元素都是新的,您只需將它們添加到 set 中, Garbage Collection需要清除它們。 缺點之一是我們需要創建m (其中m <= N - 集合中已經存在的Pixel -s 的數量),然后我們需要通過GC收集它們。 m/N比率有多大取決於您的算法和您實際在做什么。

讓我們計算在集合中N = 1_000_000像素需要消耗多少 memory。 我們知道int4 bytesdouble8 bytes ,讓我們為 object 添加額外的8 bytes8 bytes作為參考。 它為Pixel object 的每個實例提供32 bytes 我們需要創建N個提供32MB的對象。 假設我們的比率是50% ,所以我們分配16MB只是為了檢查它是不需要的。

如果這是您無法支付的成本,則需要開發允許您按left-to-right的順序迭代Set<Pixel>的算法。 因此, Pixel X的左鄰居在X之前。

假設Pixel X(x, y)的左鄰居是像素X'(x - 1, y) Pixel B(0, y)沒有左鄰。 您需要使用TreeSet並在Pixel class 中實現Comparable<Pixel>接口。 簡單的實現可能如下所示:

@Override
public int compareTo(Pixel o) {
    return this.y == o.y ? this.x - o.x : this.y - o.y;
}

這允許您按從左到右的順序迭代集合: (0, 0), (1, 0), ...., (x - 1, y), (x, y), (x + 1, y), ... , (maxX, maxY) 因此,當您迭代它時,您可以檢查前一個元素是否是當前Pixel的左鄰居。 示例實現可能如下所示:

void addNeighboursIfNeeded() {
    Set<Pixel> neighbours = new HashSet<>(pixels.size());
    Pixel last = null;
    for (Pixel p : pixels) {
        if (p.getX() == 0 || p.isLeftNeighbour(last)) {
            // a left border pixel
            // or last checked element is a left neighbour of current pixel.
            last = p;
            continue;
        }
        // last element was not our left-neighbour so we need to call b method
        Pixel left = b.getLeft(p);
        neighbours.add(left);
        last = p;
    }
    // add all new neigbours
    pixels.addAll(neighbours);
}

這應該允許您保存分配給重復Pixel對象的 memory。

我可以在這里看到一些關於 object 面向編程的擔憂。

  1. 封裝違規:當您從 A 調用 B 的 function 對 A 的數據進行操作時(您通過不發送 HashMap 來避免這種情況),它違反了封裝(如果有原因,盡管它是可以接受的)。 是否可以將 function(在 A 的 HashSet 上操作)移動到 A? 這將保護 A 的 state 不被暴露。
  2. 類的擴散:有可能會有大量的Point類型的對象。 您可以考慮使用享元 GOF 設計模式,它將每個點的 state 外化並使其可重用。 並將大幅減少數量。
  3. 將大量點集合傳遞給 B 中的方法:如果您可以將方法從 B 轉移到 A,則該點得到解決。 無論如何 java 將通過引用傳遞此集合。 但在這種情況下,它對外部類的修改開放(需要注意這方面)。
  4. Point類型的抽象:如果 class Point 只有 state 而沒有任何行為,則會導致違反封裝。 您可以將方法getNeighbour()轉換為 Point 嗎? 因為它將使 Point 不可變(這是必不可少的)。 當然,實際算法可以委托給另一個 class (如果其獨立變化的職責並且具有算法層次結構,請在此處考慮 GOF 策略模式)。
  5. 集合中點的唯一性:您的集合將適當注意適當的 Hash 和 class 點的邏輯相等性。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM