我有一个基本抽象类,需要一个身份验证算法。我有两个这样的实现,一个将哈希密码并将其与存储的哈希进行比较,另一个将使用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)
{
...
}
}
解决此问题的最佳方法是什么?是否有其他已知的模式已经解决了这个问题?或者任何人都有一个好主意?
答案 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 进行检查/投票:)