7

我在扩展应用程序时遇到问题。这是一个考勤记录系统。目前,每个员工都通过一张带有二维码的卡记录考勤。现在他们想加入指纹识别,直到他们要求两种形式的识别必须在系统中共存时才出现问题。因此,系统必须能够感知员工的二维码,以及他的指纹。

我有以下课程:

通过 .equalsTo(id) 方法在 QrIdStrategy 中修复它的方法是:

equalsTo(id){
  if (id == isKindOf (QrIdStrategy))
    if (this.getEmployeeId () == id.getEmployeeId ())
      return true;

  return false;
}

但是我知道询问对象的类是一种不好的做法,并且不想这样做。我该如何解决?

我想到了访问者模式,但是我仍然有比较两个不同类型的类的问题(因为系统可以扫描这两种类型中的任何一种)

在此处输入图像描述

4

3 回答 3

2

也许第一张图已经显示了我要说的内容,但这归结为多态性。

创建一个抽象类(例如IdentificationStrategy,使用类似的方法equlasTo())。派生两个类:QRStrategy以及FingerPrintStrategy从每个类中的IdentificationStrategy和实现equlasTo()方法。

现在,代码中有一个地方可以让您知道是否要创建QRStrategyor的实例FingerPrintStrategy。只需将该对象的实例分配给IdentificationStrategy类型变量(例如,我们将其命名为 'foo' )。当您equlasTo()在“foo”上调用该方法时,您不再关心对象类型。

于 2013-05-10T09:52:52.997 回答
1

关于你的第一个灵魂

问题是 QrId 和 FingerprintId 没有任何共同之处。IdentificationStrategy 显示您想比较它们,但您不能。解决方案可能是getUniversalID() : string向 IdentificationStrategy 添加类似的东西并在派生类中实现它们。然后你可以有:

matchWithLocation(IdentificationStrategy identificationStrategy)
{
    return this.identificationStrategy.getUniversalId()
        == identificationStrategy.getUniversalID();
}

但是,您可能会发现 getUniversalId 的实现(确保不同类型的 ID 不会冲突)有问题。

关于您的第二个解决方案

在这种情况下,对访问者的一个很好的改编是添加方法getQr() : QrIdStrategygetFingerprint() : FingerprintStrategy员工(因为员工使用这两种识别方法,正如你提到的),更改equalsTo(id: IdentificationStrategy)check(employee: Employee). 那么QrStrategy.check将是:

    return this.getEmployeeId() == employee.getQr().getEmployeeId()

并且FingerprintStrategy.check将是:

    return this.getMatchingViaFramework() == employee.getFingerprint().getMatchingViaFramework()
于 2013-05-07T14:19:17.897 回答
0

如果我理解您对模型原样的疑虑,它是功能性的,但它要求您对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. 在此模型中,您的FingerprintQRCode不再是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。关键是,如果两者都始终存在,则不需要将它们都视为身份识别形式。一个可用作标识符,另一个可用作身份验证器。

于 2013-05-10T15:28:15.453 回答