多阶段状态的嵌套 类

Nested classes for a multiple-phase state

我想使用嵌套 classes 作为 "developing state":

public class WebSvcClient : IDisposable
{
    //
    // 10 private fields required by all methods
    ...

    public Profile Profile { get; private set; }
    public void Authenticate()
    {
        this.Profile = new Profile();
    }
    public class Profile
    {
        // public methods that do require authentication
        ...
    }

    // public methods that don't require authentication
    ...
}  

我可以看到几个好处:

但这被认为是好的做法吗?

没有好处:

  • 封装是关于修饰符的。您的嵌套 class 及其方法是 public。如果你不从外部到达嵌套class,你可以使用私有class进行污染。
  • IDisposable 单元仅与实施者 class 相关。嵌套的 class 不会受到影响。
  • 污染不是来自名称空间,而是来自糟糕的设计和糟糕的命名习惯。请记住,您不是唯一的开发人员。下一个开发人员必须了解您的代码,因此他们应该通过浏览文件名轻松查看代码。或者他们必须逐个文件检查所有代码。

我认为这里没有任何收获。

  • Encapsulation, Profile makes sense only in the context of WebSvcClient

但是在另一个 class 中使用私有字段,即使它是嵌套的,也会破坏封装。

  • Single IDisposable unit

它引起的问题比在这里解决的问题多。如果在处理服务后其他代码保留配置文件怎么办?

  • Lack of need for 3rd class just to pass the private fields to Profile

好吧,也许吧。 class 无论如何都会很乱。

  • No pollution of namespace

无论如何,这不是真正的问题。


作为替代方案,使用两个接口,或至少一个用于配置文件部分。显式实现相关成员,以便它们只能通过 IProfile 引用使用。
这可以通过铸造来规避,但如果这是一个问题,您应该与您的团队交谈。这对图书馆很重要,但对应用程序不重要。

考虑使用表示状态的接口,以及可以从一种状态转换到另一种状态的方法:

public interface INew {
    // transition to initialized state
    IInitialized Init();
}

public interface IInitialized {
    // connect to get a connected object
    IConnected Connect(string connection);
}

public interface IConnected {
    // disconnect reverts back in state
    IInitialized Disconnect();

    // methods only available when connected
    bool GetValue(string name);
    void SetValue(string name, bool value);
}

等等

您可以在公共 class 上实现这些接口,或者为每个状态使用不同的 class。您将需要某种工厂来创建初始实例。

当您完全控制实际状态(没有意外断开等)时,这很有效。

通过这种方式,您可以告诉 API 的用户他们需要做什么,按什么顺序才能访问所需的方法。您可以使用 'fluent' 代码来使用这个:

var newMachine = Factory.NewMachine();
var connected = newMachine
    .Init()
    .Connect(connectionString);

connected.GetValue("test");
...

connected.Disconnect();