多阶段状态的嵌套类

时间:2015-06-16 14:30:41

标签: c# oop design-patterns

我想将嵌套类用于“开发状态”:

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
    ...
}  

我可以看到几个好处:

  • 封装,Profile仅在WebSvcClient
  • 的上下文中有意义
  • IDisposable单元
  • 只需将私有字段传递给Profile
  • ,就不需要第3课
  • 没有污染名称空间

但它被视为良好做法吗?

3 个答案:

答案 0 :(得分:1)

没有任何好处:

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

答案 1 :(得分:1)

我不认为这里有任何好处。

  
      
  • Encapsulation,Profile仅在WebSvcClient
  • 的上下文中有意义   

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

  
      
  • 单个IDisposable单位
  •   

它会导致更多问题,然后在这里解决。如果其他代码在处理完服务后保留配置文件怎么办?

  
      
  • 只需将私有字段传递给个人资料
  • ,就不需要第3个课程   

好吧,也许吧。无论如何,那堂课本来都很混乱。

  
      
  • 没有污染名称空间
  •   

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

作为替代方案,使用两个接口,或至少一个用于Profile部件。明确实施相关成员,以便仅通过IProfile参考提供 这可以通过铸造来规避,但如果这是一个问题,你应该与你的团队谈谈。这对于一个库来说很重要,但对于一个应用程序来说它不应该。

答案 2 :(得分:1)

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

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);
}

Etc ..

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

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

通过这种方式,您可以告诉API的用户他们需要做什么,以什么顺序访问所需的方法。你可以使用'流利的'代码使用它:

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

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

connected.Disconnect();