2015-10-03 23 views
3

我有以下接口(一些方法中省略爲簡單起見):添加受保護的構造,讓子類提供不同的實現

public interface Container{ 

    public void put(String s, Object o); 
    public Object get(String s); 

} 

及其實施:

public class ContainerImpl implements Container{ 

    private Map<Stirng, Object> m; 

    public ContainerImpl(){ 
     m = new HashMap<>(); 
    } 

    //This constructor is used in the case if a client is not satisfied 
    //by the HashMap, e.g. in case of Enum it's better to use EnumMap 
    protected ContainerImpl(Map<String, Object> m){ 
     this.m = m; 
    } 

    public void put(String s, Object o){ 
     m.put(s, o); 
    } 
    public Object get(String s){ 
     m.get(s); 
    } 
} 

我的問題是關於是否提供這樣一個受保護的構造者與封裝相反。事實上,我們向客戶提供一些內部使用Map的知識。如果數據結構發生變化,我認爲,我們必須從作爲參數傳遞的映射執行轉換,這可能會導致一些錯誤。

+2

這也使內部地圖可以從外部訪問。 – Basilevs

+0

@Basilevs確實,好點。 –

回答

2

你必須在一個類的創建,使用和基本地圖的封裝責任。 如果你想跟隨SRP,試圖離開它接受Map作爲參數的唯一公共構造,使用工廠或後代來封裝數據:

/** 
* @param m - storage model. Should not be modified after call. 
*/ 
public ContainerImpl(Map<String, Object> m){  
    this.m = m; 
} 

/** A new instance with default storage model */ 
public static ContainerImpl createDefault() { 
    // Storage reference is isolated 
    return new ContainerImpl(new HashMap<>()); 
} 

或者,刪除所有構造函數,並提供:

protected abstract Map<String, Object> getStorage(); 
+0

SRP是什麼意思? –

+0

我雖然關於複製,但在這種情況下,我們必須知道地圖的具體類型。 –

+0

明白了,非常感謝。 –

1

我會建議使用這樣的事情:

protected ContainerImpl(Map<String, Object> m){ 
    this(); //default constructor, instantiates internal map 
    this.m.putAll(m); // copy all values 
} 

這樣你就不會影響到封裝,但你會提供一些方便。作爲替代,你可以提供一個工廠方法是這樣的:

protected ContainerImpl create(Map<String, Object> m){ 
    ContainerImpl impl = new ContainerImpl(); //default constructor, instantiates internal map 
    impl.m.putAll(m); // copy all values 
    return impl; 
} 
+1

儘管如此,這將不允許存儲模型的參數化。 – Basilevs

+1

@Basilevs什麼是「存儲模型的參數化」? – slartidan

+2

如果客戶想要將'Collections.synchronizedMap(new HashMap <>())'作爲底層存儲,客戶端如何使用你的類?底層實現的替代是什麼依賴注入是關於什麼的,並且這裏發生了什麼。 – Basilevs

3

如果提供這樣一個受保護的構造函數與封裝相反。

你是對的,它確實與ContainerImpl的封裝行爲相矛盾。

恕我直言,這是一個設計決定;無論是class的設計是爲了強制封裝還是暴露給客戶/呼叫者以支持各種結構。

例如:

答:ContainerImpl只有default-constructor暗示的Container內部存儲完全支配由它的concrete-implementation和來電無法選擇不同的存儲。

B:ContainerImpl

protected ContainerImpl(Map<String, Object> m) 

意味着呼叫者可以選擇Map基於存儲即TreeMapHashMapLinkedHashMap或自定義實現的性質。

關於選擇上述方法之一的決定將基於客戶的需求和性質。

相關問題