简单的网关 - 代理模式






4.77/5 (21投票s)
一个简单的支付网关示例。
引言
我曾经使用过几次这种方法将类似的 API 整合到应用程序中。可以把它看作是一个网关。我会尽量保持简洁明了。查看示例代码也会对你有所帮助。我同时也假设你对反射和 Web 服务有所了解。
你为什么要实现这样的东西?
好吧(当然,这只是假设),想象一下你得到一个只接受 Visa 卡的第三方支付解决方案。好的,你已经实现了 Visa 支付提供商。现在,你的一些客户希望使用万事达卡支付。而且,你可能会怀疑在未来,有人也想使用美国运通卡。
你可以根据需要将每个支付提供商添加到你的代码中,但这很快就会变得混乱。而松散耦合的 API 封装器(在这个例子中是代理封装器)在一个“网关”中可以让你随意添加和删除支付提供商。甚至可以添加一些业务逻辑,以决定哪个提供商对你的用户来说最便宜... 所以,如果你从一开始就实现了“网关”,那么在你的应用程序生命周期中添加新的支付提供商就像呼吸一样简单,至少更容易和更干净。
这是一个创建 API 网关的快速示例。在这个例子中,我使用了两个 Web 服务,但库也可以用类似的方式插入。
设计
查看上图,我将简要介绍解决方案的实体。我将主要关注网关和 API 1 和 2 实体。
- 解决方案:这通常是你的应用程序的业务逻辑。
- 网关:你的应用程序和 API 封装器之间的连接。
- API 1 & 2:这些是 API 代理 1 & 2 的封装器。
- API 代理:这些代表我们的支付网关提供商。这些是我们将会使用的服务。
网关
我将首先介绍网关,然后是 API 封装器,之后,我将解释它们是如何连接起来的。
接口是真正将网关组合在一起的部分。如上图所示,网关和 API 封装器都实现了该接口。那么,让我们一起创建一个接口。
在我的示例中,我创建了 IGateway
public interface IGateway
{
bool ValidateUser(Userobj user);
string GetUserAddress(Userobj user);
}
我在网关中使用反射来调用 API 封装器。通过实现一个接口,我们将确切地知道要调用什么方法,要传递哪些参数,以及期望返回什么。
在这个例子中,我想验证一个用户并获取他的地址。现在我们已经定义了我们需要什么,我们可以定义我们的接口。让我们把它添加到网关中。
public class Gateway: IGateway
{
IGateway proxy;
public Gateway(String dllNamePath)
{
LoadIGhostAssembly(dllNamePath);
}
void LoadIGhostAssembly(String dllNamePath)
{
Assembly asm = Assembly.LoadFrom(dllNamePath);
Type[] typesInAssembly = asm.GetTypes();
foreach(Type t in typesInAssembly)
{
if (t.GetInterface(typeof(IGateway).FullName) != null)
{
proxy = (IGateway)Activator.CreateInstance(t);
}
}
}
//IGateway Members
public bool ValidateUser(Userobj user)
{
return proxy.ValidateUser(user);
}
public string GetUserAddress(Userobj user)
{
try
{
return proxy.GetUserAddress(user);
}
catch { return "Facility doesn't exist"; }
}
}
LoadIGhostAssembly
是我们在哪里获取正确的 API 封装器来调用的地方。我的业务逻辑将传递 Visa 或 Mastercard 库的位置,这取决于你想使用哪一个。如上图所示,API 封装器也实现了 IGhost
接口。我们将实例化正确的引用,并创建一个到 API 封装器接口方法的直接映射。
API 封装器
我创建了一个新的库并添加了一个实现我的接口的类。现在,我将使用我想要的 Web 服务(在示例代码中称为 WebServiceMasterCard
和 WebServiceVisa
),并将其与我的接口方法相匹配。
public class Proxy : Global.IGateway
{
#region IGateway Members
public bool ValidateUser(Global.Userobj user)
{
try
{
ProxyWebServiceVisa.localhost.Service1 apiProxy =
new ProxyWebServiceVisa.localhost.Service1();
return apiProxy.CheckUser(user.UserID);
}
catch { return false; }
}
public string GetUserAddress(Global.Userobj user)
{
ProxyWebServiceVisa.localhost.Service1 apiProxy =
new ProxyWebServiceVisa.localhost.Service1();
return apiProxy.UserAddress(user.UserID, user.FirstName, user.LastName);
}
#endregion
}
对你想要添加到你的网关的每个支付提供商重复此操作。
粘合剂
这是我将如何从我的应用程序调用网关
UserGateway.Gateway gateway =
new UserGateway.Gateway("c:\\temp\\ProxyWebServiceMasterCard.dll");
gateway.ValidateUser(user)
gateway.GetUserAddress(user)
正如你所看到的,我调用网关并传递我需要的所需服务。只要所有 API 封装器都实现了正确的接口,你就可以添加任意数量的封装器,甚至可以删除一些。我硬编码了库的位置,但我通常将其添加到 XML、数据库或公共目录中,这样代码就不需要在每次需要向网关添加服务时重新编译。一旦你指定了要使用的库,网关将使用反射创建它的一个实例,通过方法映射,你可以调用你想要的任何方法。
而且,只需创建你想要的任意数量的 API 封装器,只要它们实现了你的接口,你的网关就会识别它们。
更新:这同时也是代理模式实现的一个示例,我在构思时并不知道我已经实现了它。请查看 代理模式 以获取更多详细信息。