班级设计决策

时间:2020-03-05 18:45:06  来源:igfitidea点击:

我有一个两难的困境,也许我们可​​以帮助我进行梳理。

我今天一直在努力修改ASP.NET的成员资格,以添加一个间接级别。基本上,ASP.NET的成员资格支持用户和角色,而所有授权规则都取决于用户是否属于角色。

我需要做的是添加"功能"的概念,其中用户将属于一个(或者多个)角色,并且该角色将具有一个或者多个与之相关联的功能,从而使我们可以根据用户是否属于来授权特定操作分配有功能的角色。

话虽如此,我的问题与它无关,这是一个通用的类设计问题。

我想在我的基本RoleProvider类中提供一个抽象方法来创建函数(并将其持久化),但是我想使其成为可选的以保存对该函数的描述,因此我需要创建一个带有重载的CreateFunction方法,一个签名接受名称,另一个接受名称和描述。

我可以想到以下情形:

  • 使用abstract修饰符创建两个签名。这样做的问题是,实现者可能不遵守最佳实践,即一个重载应调用已标准化参数的另一个重载,而逻辑应仅位于最后一个重载(具有所有参数的重载)中。此外,要求这两种方法都必须由开发人员实现是不好的。
  • 创建第一个类似虚拟的,第二个类似抽象的。从第一个调用第二个,允许实现者重写行为。它有同样的问题,实现者在覆盖它时可能会做出"错误的决定"。
  • 与以前相同,但不允许第一个被覆盖(删除虚拟修饰符)。这里的问题是,实现者必须意识到可以使用空描述来调用该方法,并且必须处理这种情况。

我认为最好的选择是第三个...

一般情况下如何处理?设计抽象类时,它包含重载方法。我认为这并不罕见。

解决方案

回答

我觉得DRYness和强制执行合同的最佳组合如下(使用伪代码):

class Base {
  public final constructor(name) {
    constructor(name, null)
  end

  public abstract constructor(name, description);
}

或者,或者:

class Base {
  public abstract constructor(name);

  public final constructor(name, description) {
    constructor(name)
    this.set_description(description)
  }

  private final set_description(description) {
    ...
  }
}

Java中有一条规则支持此决定:"切勿从构造函数中调用非最终方法。"

回答

要回答帖子的第一部分,请签出AzMan(授权管理器),它是内置在Windows中的。它具有指定可以重组为角色或者直接分配给用户的操作的功能。

退房

为了回答我们问题的第二部分,我不会使用Abstract类。相反,只需在构造函数中提供功能并完成即可。它似乎使我们想要指定的行为,并且我们不想更改它。为什么要强迫后代提供执行。