如果我理解您对模型原样的疑虑,它是功能性的,但它要求您对IdentificationStrategy
-- 的实例执行运行时类型检查,并且您希望避免这种情况。(不管这是否真的是不好的做法。)因此,鉴于每个员工都需要两者,我建议将它们视为单个Credentials
对象的单独组件。
您可以通过以下两种方式之一来实现。
我认为,更通用、或许更具前瞻性的方式是假设用户可以拥有 N 种身份识别方式,并且他们需要任意两种方式进行授权。因此,对于进入的每个IdentificationStrategy
对象,您将其添加到一组Credentials
:
public class Credentials {
public const int NumberOfDistinctIdsRequired = 2;
private List<IdentificationStrategy> ids = new List<IdentificationStrategy>();
public void AddIdentification(IdentificationStrategy id) {
if (ids.Count < NumberOfDistinctIdsRequired) {
// this .Contains() check should compare id's based on the raw, internal ID
// or hash -- NOT by the underlying user/employee.
if (!ids.Contains(id)) {
ids.Add(id);
}
}
}
public Employee AuthenticatedEmployee() {
// if we have the required number of authentication pieces,
// see whether they belong to the same employee
if (ids.Count == NumberOfDistinctIdsRequired) {
Employee rv;
for (int i = 0; i < NumberOfDistinctIdsRequired; i++) {
if (rv == null) {
rv = ids[i].getEmployee();
} else if (!rv.Equals(ids[i].getEmployee())) {
return null;
}
}
return rv;
} else {
return null;
}
}
}
或者,将一个视为 ID,将另一个视为密码。我认为,如果 ID 始终以相同的顺序呈现,则使用第一个呈现的 ID 作为实际ID
的 ID,使用第二个呈现的“ID”作为Password
. 在此模型中,您的Fingerprint
和QRCode
不再是IdentificationStrategy
. 并且无论哪个被视为Password
不需要能够返回一个Employee
,而是获取并根据Employee
返回的标识符进行验证。标识符甚至不需要立即出现在Employee
(但可能是)上。
假设 QRCode 是 ID 和指纹“密码”。所以......做这样的事情:
public class QRCode : Identifier {
public Employee GetEmployee() {
// return the employee stored under the GUID, Int, String, or whatever
}
}
public class Fingerprint : Password {
public bool Equals(Fingerprint p) {
// compare hashes or whatever.
}
}
public class Employee {
public Identifier Id;
private Password password;
public Boolean IsAuthenticated = false;
public Boolean Authenticate(Password p) {
if (password.Equals(p)) {
IsAuthenticated = true;
}
return IsAuthenticated;
}
}
或者将更多的工作卸载到Employee
课堂上。或者引入一个Credentials
将一个视为 anID
而另一个视为 a 的类Password
。关键是,如果两者都始终存在,则不需要将它们都视为身份识别形式。一个可用作标识符,另一个可用作身份验证器。