問題描述
類設計決策 (Class design decision)
我有一個小難題,也許你可以幫我解決。
我今天一直在修改 ASP.NET 的 Membership 以添加一個間接級別。基本上,ASP.NET 的成員資格支持用戶和角色,所有授權規則都基於用戶是否屬於角色。
我需要做的是添加函數的概念,其中一個用戶將屬於一個(或多個角色),並且該角色將具有與之關聯的一個或多個功能,允許我們授權特定的基於用戶是否屬於分配了功能的角色的操作。
話雖如此,我的問題與它無關,這是一個通用的類設計問題。
我想在我的基本 RoleProvider 類中提供一個抽象方法來創建函數(並保留它),但我想讓它成為可選的以保存該函數的描述,所以我需要創建我的 CreateFunction 重載方法,一個簽名接受名稱,另一個接受名稱和描述。
我可以想到以下場景:
使用 abstract 修飾符創建兩個簽名。這樣做的問題是,實現者可能不尊重最佳實踐,即一個重載應該調用另一個參數歸一化的重載,並且邏輯應該只在最後一個(具有所有參數的那個)中。此外,要求開發人員實現這兩種方法也不是很好。
創建第一個像虛擬的,第二個像抽象的。從第一個調用第二個,允許實現者覆蓋行為。它有同樣的問題,實施者在覆蓋它時可能會做出“錯誤的決定”。
和之前一樣,但是不允許第一個被覆蓋(去掉 virtual 修飾符)。這裡的問題是實現者必須意識到可以使用空描述調用該方法並且必須處理這種情況。
我認為最好的選擇是第三個...
這種情況一般是如何處理的?當您設計一個抽像類並且它包含重載方法時。我認為這並不少見……
從第一個調用第二個,允許實現者覆蓋行為。它有同樣的問題,實施者在覆蓋它時可能會做出“錯誤的決定”。和之前一樣,但是不允許第一個被覆蓋(去掉 virtual 修飾符)。這裡的問題是實現者必須意識到可以使用空描述調用該方法並且必須處理這種情況。
我認為最好的選擇是第三個...
這種情況一般是如何處理的?當您設計一個抽像類並且它包含重載方法時。我認為這並不少見……
從第一個調用第二個,允許實現者覆蓋行為。它有同樣的問題,實施者在覆蓋它時可能會做出“錯誤的決定”。和之前一樣,但是不允許第一個被覆蓋(去掉 virtual 修飾符)。這裡的問題是實現者必須意識到可以使用空描述調用該方法並且必須處理這種情況。
我認為最好的選擇是第三個...
這種情況一般是如何處理的?當您設計一個抽像類並且它包含重載方法時。我認為這並不少見……
這裡的問題是實現者必須意識到可以使用空描述調用該方法並且必須處理這種情況。我認為最好的選擇是第三個...
這種情況一般是如何處理的?當您設計一個抽像類並且它包含重載方法時。我認為這並不少見……
這裡的問題是實現者必須意識到可以使用空描述調用該方法並且必須處理這種情況。我認為最好的選擇是第三個...
這種情況一般是如何處理的?當您設計一個抽像類並且它包含重載方法時。我認為這並不少見……
參考解法
方法 1:
I feel the best combination of DRYness and forcing the contract is as follows (in pseudocode):
class Base {
public final constructor(name) {
constructor(name, null)
end
public abstract constructor(name, description);
}
or, alternatively:
class Base {
public abstract constructor(name);
public final constructor(name, description) {
constructor(name)
this.set_description(description)
}
private final set_description(description) {
...
}
}
There's a rule in Java that supports this decision: "never call non‑final methods from a constructor."
方法 2:
To answer the first part of your post, check out AzMan (Authorization Manager), which, incidentally, is built into windows. It has the capability to specify operations which can be recombined into roles or assigned directly to users.
To answer the second part of your question, I wouldn't use an Abstract class. Instead just provide the functionality in the constructor and be done with it. It appeasr you want the specified behavior, and you don't want it to change. Why force descendents to provide the implementation.
(by juan、James A. Rosen、NotMe)