模板方法模式,每个实现需要不同的参数?

时间:2014-05-06 20:03:49

标签: c# design-patterns template-method-pattern

我有一个基本抽象类,需要一个身份验证算法。我有两个这样的实现,一个将哈希密码并将其与存储的哈希进行比较,另一个将使用Windows活动目录。

但在实际进行哈希检查或Windows身份验证之前,我必须完全实现额外的工作流逻辑。因此,无论身份验证算法如何,必须始终以相同的方式修改或使用failedPasswordCount,lastAuthenticationAttemptDate,IsUserApproved等内容。

在我看来,这个问题可以使用模板方法模式解决,但实现我的两种身份验证方法所需的信息因使用的方法而异。

public abstract class User
{
    public bool Authenticate() // my template method
    {
        lastAuthenticationAttemptDate = DateTime.UtcNow();
        if(IsUserApproved)
        {
            if(DoAuthenticate()) // implemented by childs
            {
                return true;
            }
            else
            {
                failedPasswordCount++;
                return false;
            }
        }
    }

    public abstract DoAuthenticate();
}

public UserWindowsLogon : User
{
    public override bool DoAuthenticate(string windowsDomain, string password)
    {
         ...
    }
}

public UserApplicationLogon : User
{
    public override bool DoAuthenticate(string password)
    {
         ...
    }
}

解决此问题的最佳方法是什么?是否有其他已知的模式已经解决了这个问题?或者任何人都有一个好主意?

3 个答案:

答案 0 :(得分:4)

您可以通过这种方式保持基础接口的“DoAuthenticate()”清除参数

public UserWindowsLogon : User
{
    public string windowsDomain;
    public string password;
    public override bool DoAuthenticate()
    {
         // Check and use windowsDomain/password values here
    }
}

public UserApplicationLogon : User
{
    public UserApplicationLogon(string password) : base()
    {
         this.password = password;
    }

    private string password;
    public override bool DoAuthenticate()
    {
         // use password value here
    }
}

并提供在实例化User派生对象时使用的参数值。

答案 1 :(得分:3)

假设您的客户端代码知道该做什么(应该应用哪些实际参数),您可以轻松地在身份验证中引入类层次结构,从而可以在此类层次结构的基类上声明合同。

public abstract DoAuthenticate( AuthenticationContext context );
...

public UserWindowsLogon : User
{
  public override bool DoAuthenticate( AuthenticationContext context )
  { 
     if ( context is UserWindowsAuthenticationContext )
     {
        // proceed
     }
  }
}

public UserApplicationLogon : User
{
  public override bool DoAuthenticate( AuthenticationContext context )
  {
     if ( context is UserAplicationAuthenticationContext )
     {
        // proceed
     }
   } 
}

public abstract class AuthenticationContext { }

public class UserWindowsAuthenticationContext : AuthenticationContext
{
   public string windowsDomain;
   public string password;
}

public class UserApplicationAuthenticationContext : AuthenticationContext
{
   public string password;
}

答案 2 :(得分:1)

这实际上是Strategy pattern(策略是身份验证/验证机制)符合Composite pattern

的示例

验证通常是复合模式。当你将其分解时,你想要将你希望的 分离到你想要的,你得到:

If foo is valid
then do something.

这里我们有抽象是有效的

我刚刚写了一篇关于你的案例here的文章。如果你觉得这个答案最令人讨厌,那么给 IT 进行检查/投票:)