软件工程是一个不断发展的领域,这意味着将出现新的模式。这些设计模式帮助软件工程师简化了他们的编码过程,并在更短的时间内取得了更好的结果。其中一种模式是规范设计模式,在本文中,我们将研究 C 语言中的规范设计模式#
规范设计模式是一种软件设计模式,它允许开发人员创建可重用、可组合和可扩展的规范,这些规范可用于根据业务规则从集合中选择对象。此模式可用于验证复杂的业务规则,并以简洁明了的方式从大型集合中筛选对象。通过实施规范设计模式,软件工程师可以提高其代码的可读性、可维护性和可伸缩性。
在本指南中,我将深入解释规范设计模式。我将介绍此模式的优点和缺点,并提供使用 C# 编程语言实现规范设计模式的指南。我还将分享使用该模式和避免常见错误的最佳实践。在本文结束时,您将能够利用规范设计模式并将其应用于您的软件工程项目!
规范设计模式是一种设计模式,用于使程序员能够将评估特定条件的逻辑与程序的主要逻辑分开。此模式为开发人员提供了一种标准化的方法来定义可用于在程序中执行特定操作的条件,而不会弄乱代码的主要逻辑。
使用规范设计模式有很多好处,包括:
重要的是要记住,每种设计模式都有优点和缺点。了解规范设计模式的好处可以帮助您找到可能有益的机会。
以及所有有优点的东西......也有缺点!以下是使用规范设计模式的一些缺点:
缓解规范设计模式缺点的一种方法是创建可重用的规范。这样做可以确保规范可以组合和重用,而无需关注其实现细节。
感谢您阅读 Dev Leader 文章!免费订阅以接收新帖子并支持我的工作。
要开始在 C# 中实现规范设计模式,我们需要首先了解该模式的不同组件。这些组件将是:
规范接口用于创建可重用和可组合的规范。它定义了所有规范所需的合同。下面是 C# 中的规范接口示例:
public interface ISpecification<T>
{
bool IsSatisfiedBy(T entity);
}
该接口是一个“泛型”,参数化于一个类型,在我们的例子中,它可以表示域中我们想要根据规范进行验证的任何实体。该方法检查给定实体是否满足规范。TIsSatisfiedBy
规范类是实现规范接口的类。这些类定义用于评估实体的实际规范。这就是我们的逻辑和实现所在。
下面是一个示例,说明我们如何实现一个规范类,以便实体按出生日期进行筛选:Customer
public class CustomerByDateOfBirthSpecification : ISpecification<Customer>
{
private readonly DateTime _dateOfBirth;
public CustomerByDateOfBirthSpecification(DateTime dateOfBirth)
{
_dateOfBirth = dateOfBirth;
}
public bool IsSatisfiedBy(Customer entity)
{
return entity.DateOfBirth == _dateOfBirth;
}
}
如上面的示例所示,类的构造函数接收出生日期作为参数。调用该方法时,它会根据类的出生日期来评估该类的实例是否满足规范。CustomerByDateOfBirthSpecificationIsSatisfiedByCustomer
创建这些类后,请务必测试它们以确保它们按预期运行。
下面是一个示例,说明如何使用 NUnit 之类的东西来测试规范类:
[TestFixture]
public class CustomerByDateOfBirthSpecificationTest
{
private IReadOnlyList<Customer> _customers;
[SetUp]
public void SetUp()
{
_customers = new List<Customer>
{
new Customer { DateOfBirth = new DateTime(1992, 3, 17) },
new Customer { DateOfBirth = new DateTime(1990, 11, 28) },
new Customer { DateOfBirth = new DateTime(1995, 10, 5) }
};
}
[Test]
public void Should_ReturnTrue_When_CustomerMatchesSpecification()
{
// Arrange
CustomerByDateOfBirthSpecification specification = new(new DateTime(1990, 11, 28));
var customer = _customers[1];
// Act
var result = specification.IsSatisfiedBy(customer);
// Assert
Assert.IsTrue(result);
}
[Test]
public void Should_ReturnFalse_When_CustomerDoesNotMatchSpecification()
{
// Arrange
var specification = new CustomerByDateOfBirthSpecification(new DateTime(1993, 1, 1));
var customer = _customers[2];
// Act
var result = specification.IsSatisfiedBy(customer);
// Assert
Assert.IsFalse(result);
}
}
正如我们所看到的,我们首先设置了一个实体列表。然后,我们创建规范类的实例,并使用不同的客户和预期结果对其进行测试。这些测试确保我们的规范类正确可靠地工作。Customer
现在我们已经介绍了如何实现和测试规范设计模式,我们可以继续讨论最佳实践,以最大限度地提高模式的有效性。
在 C# 中使用规范设计模式时,必须遵循某些最佳实践才能有效且高效地使用该模式。
要将规范设计模式集成到现有代码库中,请务必确定该模式所关注的问题,并确定最适合规范的候选者。完成此操作后,您可以提取特定条件的现有逻辑并创建单独的规范类。通过这样做,您可以确保代码的主要逻辑不会变得混乱并且易于维护。
请记住也要考虑这种设计模式的缺点——如果你担心多个小类会弄乱你的代码库,请记住这一点。就我个人而言,我喜欢以这种方式拆分逻辑,但在你的情况下可能会觉得矫枉过正。
规范设计模式最重要的好处之一是它是可组合的。这意味着您可以将多个规范类合并为一个规范类。我们在这里谈论的关键词是构图——把你的遗产排除在外!
不过,请确保您谨慎地实现合成,尤其是在涉及大型合成的情况下。这样做将确保您不会创建任何可能对模式性能产生负面影响的复杂方案。
规范设计模式的一个显著好处是,无论业务逻辑如何,规范都可以在程序的不同部分中重用。为了有效地做到这一点,将规范类存储在一个单独的库中可能会有所帮助,该库可以从应用程序的任何部分访问。以这种方式重用规范使你能够删除重复的代码,编写更简洁的代码,并专注于应用程序的主要功能。当然,这将是具体情况,取决于您的意见。
下面是如何在 C# 的单个规范类中组合两个规范的示例:
public class CustomerIsVipAndFromUsaSpecification : ISpecification<Customer>
{
private readonly ISpecification<Customer> _isVip;
private readonly ISpecification<Customer> _isFromUSA;
public CustomerIsVipAndFromUsaSpecification(
ISpecification<Customer> isVip,
ISpecification<Customer> isFromUSA)
{
_isVip = isVip;
_isFromUSA = isFromUSA;
}
public IsSatisfiedBy(Customer entity)
{
return
_isVip.IsSatisfiedBy(entity) &&
_isFromUSA.IsSatisfiedBy(entity);
}
}
在上面的示例中,我们通过将两个规范组合成一个规范来创建一个新规范,该规范表示来自美国的 VIP 客户。的构造函数采用两个规范,并组成新的实现。通过采用这种方法,我们可以结合多种规格......甚至以通用的方式做到这一点!CustomerIsVipAndFromUsaSpecification_isVip_isFromUSA
在 C# 中实现规范设计模式时,使用这些最佳实践将使代码更高效、更易于维护、更不容易出错且可伸缩。
在本文中,我们探讨了 C# 中的规范设计模式,以及如何使用它来提高代码质量和可维护性。我分享了该模式的优点,例如它能够抽象复杂查询和提高可测试性,以及它的缺点,例如需要创建额外的代码和性能下降的可能性。
我还提供了有关如何在 C# 中有效实现该模式的指导,包括创建规范接口、创建规范类和测试代码。讨论了最佳实践,以帮助您有效地使用该模式并避免常见错误。记住——不要过度,对你的方法保持务实!