更新:
其实我今天上午将与您的特定情况下工作,是一个更容易保持想到了一个方法。我将在这里留下原始的两点,但我会推荐最后的选项,所以请跳到“更好的方法”部分。
创建一个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