java - 在具有特定或可变参数的接口中编写方法?
问题描述
我正在编写与第 3 方 API 网关的集成,并努力使其尽可能解耦(并且能够在将来更改提供程序),我创建了 3 个接口,其中包含读取、写入的方法并从网关中删除(因为我需要使用很多方法,所以我不想把所有东西都塞进一个大接口中,违反接口隔离原则)。API Gateway 用于处理应用程序创建和其他 CRUD 操作。
而且我不确定前进的最佳方式是什么。我可以创建这样的界面
interface Api_Gateway_Create {
public function create_app( string $organization, string $developer_id, string $body );
// other methods.
}
然后,在做具体实现的时候,我会创建一个实现这个的类,当我需要使用它的时候,我需要提供三个参数。
这似乎有点束缚。如果当我更换提供者时,我不再需要$developer_id
? 我可以用一些默认值设置所有参数
interface Api_Gateway_Create {
public function create_app( string $organization,
string $developer_id = 'some-default-value',
string $body = 'some-default-value' );
// other methods.
}
但这意味着我最终会得到我可能不需要的参数,这可能会扰乱我的实现。
最后想到的是我可以放一个可变参数,然后让实现处理参数
interface Api_Gateway_Create {
public function create_app( ...$arguments_list );
// other methods.
}
在实施中我有
class Create_App_Implementation1 implements Api_Gateway_Create {
public function create_app( ...$arguments_list ) {
list( $organization, $developer_id, $body ) = $arguments;
// Some business logic.
}
}
或者
class Create_App_Implementation2 implements Api_Gateway_Create {
public function create_app( ...$arguments_list ) {
list( $organization, $app_key, $body ) = $arguments;
// Some business logic.
}
}
这样我就不需要关心我的提供者是否提供了这些参数,因为我只会实现我需要的那些。
然而,这提出了另一个问题。在消费代码中,比如说一个将create_app()
通过依赖注入使用方法的类,我需要特别注意传递正确的值。这不是未来的证明,因为我还需要更改消费类中的代码(在我看来,这似乎与接口的相反意图)。
对于第一个,我将永远不必更改使用代码,因为如果我期望相同的结果(基于相同的输入参数),我不在乎我正在使用哪个提供程序。但正如我已经提到的,这似乎有点限制。两个提供商可能有不同的处理方式。
有没有人不得不面对这种事情,处理这种事情的行业标准是什么?
我正在用 PHP 编写代码,但我认为 Java 也可以适用,因为它具有面向对象的特性。
解决方案
有没有人不得不面对这种事情?处理这种事情的行业标准是什么?
- 我确定他们有。
- 没有“行业标准”的方式来做到这一点。
(您可能应该从词汇表中删除诸如“行业标准”和“最佳实践”之类的短语。在我看来,它们对交流有害。阅读“没有最佳实践”并思考他在说什么。)
我对 PHP 不够熟悉,无法说出用那种语言解决这个问题的常用方法。
在 Java 中,有两种常见的方法:
为常见情况定义许多不同的方法(或构造函数)重载;例如
public interface CreateAppApi { public String create_app(String organization, String developerId, String body); public String create_app(String organization, String developerId); public String create_app(String developerId); }
如果参数都具有相同的类型,这将无法正常工作:不同的重载可能无法区分。
使用流利的构建器模式;例如定义这样的接口:
public interface CreateAppRequest { public CreateAppRequest organization(String value); public CreateAppRequest developer(String developerId); public CreateAppRequest body(String body); public String send(); }
并像这样使用它:
String result = new CreateAppRequestImpl().organization(myOrg) .developer(myId).body(someBody).send();
从 API 用户的角度来看,这很好用,而且很容易发展。(只需添加更多用于向 API 提供新参数并实现它们的方法。)缺点是有更多样板代码。
Java 支持可变参数,但它们不适合您描述的用例。(这适用于您有可变数量的值本质上表示相同事物的情况;例如,表示我们假设的“应用程序”的方法的字符串的内联列表。)
在 Python 中,没有方法重载……因为不需要它。相反: - 您可以使用位置或关键字参数,或它们的组合。- 你也有像*args
and这样的结构**kwargs
来传递任意参数而不显式声明它们。
一般来说,关键字参数更适合需要具有不同含义和(可能)类型的各种参数的 API。
所以在这个例子中,你可能会这样写:
class CreateAppRequest(SomeBaseClass):
def __init__(self, organization='defaultOrg', developer=None, body='',
**kwargs):
super(self, CreateAppRequest).__init__(**kwargs)
if developer is None:
raise Exception('developer is mandatory')
self.developer = developer
self.organization = organization
self.body = body
def send(self):
...
builder / fluent 方法也可以在 Python 中使用。
推荐阅读
- java - 如何将 PostgreSQL 函数返回的 PgObject 值映射到自定义 java 对象
- python - 在 YouTube 上搜索并返回 n 个链接
- c# - “错误:TrustFailure(身份验证失败,请参阅内部异常。)”尝试调用 ASP.NET api 时
- excel - VBA:为什么代码无法识别 Excel 工作表的名称
- angular - 刷新 DOM 元素不能作为例外的 Angular 工作
- python-3.x - 如何使用 python 打开浏览器并连接到共享点?
- ios - 为什么我的matchedGeometryEffect 基于右下角移动?
- excel - Excel VBA 代码以使用桌面、MS Office SSO 登录到 Fusion SaaS SSO
- nodemailer - Nodemailer starter 示例连接 ETIMEDOUT 错误
- android - 估计图像背景场景像素的动态颜色