更新:
其實我今天上午將與您的特定情況下工作,是一個更容易保持想到了一個方法。我將在這裏留下原始的兩點,但我會推薦最後的選項,所以請跳到「更好的方法」部分。
創建一個ThrowIfReadOnly
方法,它在罐子上做什麼。這個重複性稍低,避免了嵌套。
使用接口。有一個IPage
實現您想要的功能,使每個公共方法返回IPage
,然後有兩個實現,一個EditablePage
和一個ReadOnlyPage
。只要有人試圖修改它,ReadOnlyPage
只會引發異常。還要在IPage
接口上放置IsReadOnly
屬性(或State
屬性),以便消費者可以實際檢查狀態而不必捕捉異常。
選項(2)的更多或更少的如何IList
和ReadOnlyCollection<T>
一起工作。這樣可以節省您在每個方法開始時進行檢查的麻煩(從而消除了忘記驗證的風險),但需要您維護兩個類。
- 更好的方法 -
一個適當的技術規範將有很大的幫助澄清這一問題。我們在這裏真正擁有的是:
- A 系列任意「寫」動作;
- 每個動作具有相同結果,依賴於國家:
- 要麼採取動作(未發表/再加工),或失敗/(只讀)空操作。
真的有什麼需要抽象是沒有這麼多的行動本身,但執行說行動。因此,功能性善良的點點將幫助我們在這裏:
public enum PublishingState
{
Unpublished,
Published,
Reworking
}
public delegate void Action();
public class PublishingStateMachine
{
public PublishingState State { get; set; }
public PublishingStateMachine(PublishingState initialState)
{
State = initialState;
}
public void Write(Action action)
{
switch (State)
{
case PublishingState.Unpublished:
case PublishingState.Reworking:
action();
break;
default:
throw new InvalidOperationException("The operation is invalid " +
"because the object is in a read-only state.");
}
}
}
現在它變得幾乎微不足道寫的類本身:
public class Page
{
private PublishingStateMachine sm = new
PublishingStateMachine(PublishingState.Unpublished);
private string title;
private string category;
// Snip other methods/properties
// ...
public string Title
{
get { return title; }
set { sm.Write(() => title = value; }
}
public string Category
{
get { return category; }
set { sm.Write(() => category = value; }
}
public PublishingState State
{
get { return sm.State; }
set { sm.State = value; }
}
}
這不僅會更多或更少的貫徹落實國家模式,但不需要爲不同的狀態維護單獨的類或甚至單獨的代碼路徑。例如,如果您想要將InvalidOperationException
變爲無操作,只需從Write
方法中刪除throw
語句。或者,如果你想添加一個額外的狀態,如Reviewing
或類似的東西,你只需要添加一條case
行。
這不會爲你處理或任何真正複雜的動作是做取決於國家(不僅僅是「成功」或「失敗」等)不同的事物狀態轉換,但它聽起來並不像你需要的。所以這給你一個插入狀態的實現,它幾乎不需要額外的代碼來使用。
當然,還是有依賴注入/ AOP的選擇,但顯然還有很多與該方法相關的開銷,我可能不會用它的東西那麼簡單。
謝謝,我在想選項2,它可以很好地工作 – hackerhasid 2010-01-07 22:24:04
我想這就是我一直在尋找的答案。我非常喜歡這個語法,謝謝! – hackerhasid 2010-01-11 14:59:49