延伸阅读:策略模式;模板方法模式;控制反转(IoC)。
一种方法是提取必须倾听客户特定功能的逻辑并注入实现而不是将其烘焙到代码中。例如,使用一个接口:
public int GetAge(Person p)
{
return p.Age;
}
一位客户想谎报年龄,因此要求您将所有年龄加 1:
public int GetAge(Person p)
{
var age = p.Age;
// Imagine all this exists...
if (CustomerContext.CurrentCustomer == Customer.One)
{
age++;
}
return age;
}
这个想法是提取年龄的后处理:
public int GetAge(Person p, IAgePostProcessor ageProcessor)
{
var age = p.Age;
return ageProcessor.Process(age);
}
public interface IAgePostProcessor
{
int Process(int age);
}
然后除此之外,当您知道您所处的客户环境时,您可以决定在启动时配置策略。
对于那个客户,您提供了一个年龄 +1 的实现,对于其他所有人,您提供一个什么都不做的传递实现。
您可以利用其他 DI/IoC 框架(Ninject、Castle Windsor、StructureMap)来帮助处理这些东西。
或者,您的“界面”可能只是
Func<int, int>
:
public int GetAge(Person p, Func<int, int> postProcessAge)
{
if (postProcessAge == null)
postProcessAge = a => a; // Do nothing.
return postProcessAge(p.Age);
}
这再次将依赖关系移到此方法之外,并允许您在其他地方对逻辑做出决定,也许在启动时集中一次。
所有方法的好处是,您可以独立于用于证明每个客户满足验收标准的客户特定实施进行测试。