private 和 protected 構造函數的選擇
實現單例模式的時候經常要把構造函數標記為private 和protected以防止外部直接通過new操作符 構造一個新的實例
眾所周知 private 和protected的主要區別就是 后者允許子類調用被標記為protected的方法
另外一個常識: 使用new操作符構造一個子類的過程中 .net會先構造一個父類出來 ,如此遞歸 直到object對象
那么也就是說 標記為protected的時候 實際上還是可以通過繼承的方式間接的構造父類對象
代碼如下: (new ClassB的同時也間接的new ClassA了)
public class ClassA
{
protected ClassA()
{
}
}
public class ClassB : ClassA
{
public ClassB()
{
}
}
private則沒有這個問題, 但是! 標記為private以后實際上也就意味著沒有類型可以繼承private了
當然你可以編寫如下代碼: (但是編輯器會告訴你 'ClassA.ClassA()' is inaccessible due to its protection level)
public class ClassA
{
private ClassA()
{
}
}
public class ClassB : ClassA
{
public ClassB()
{
}
}
原因就是構造ClassB的時候沒法調用ClassA的構造函數
從開發角度講,如果一個類設計的時候就不想被繼承或者不能被繼承,那么應該標記為Sealed , 以防止別人不小心繼承了這個類,那么這里的ClassA應該被標記為密封的
那么如果是為了單例模式 private是一個比較好的選擇, 密封類并protected也是一個可以使用的實現
有的時候屏蔽構造函數并不是想使用單例模式 ,而且想通過這種方式規范調用方的行為
代碼如下:
public class ClassA
{
protected ClassA()
{
}
public ClassA Create()
{
//這里可以做特殊操作 例如給ClassA的屬性賦初始值,或者寫點日志什么的,反正你愛干嘛干嘛
return new ClassA();
}
}
那么這個時候我個人還是建議 使用protected的構造函數,因為這樣不會剝奪被繼承的能力
在我 "某項目要調用現有的100多個DLL " 這個項目中 目前就需要用到這樣的能力,通過Create這樣創建出來的ClassA 實際上是ClassA的一個子類, 其中做了一個特別的處理
.net中的 System.Net.WebRequest.Create 方法 就是這樣的一個例子
PS: private構造函數的問題就是間接剝奪了被繼承的可能,如果這樣 建議把類型標記為密封的
PS: 如果不想剝奪被繼承的能力,那么就使用protected吧
浙公網安備 33010602011771號