- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
很抱歉问了这么长的问题,但请耐心等待,我已尽力让我的问题尽可能易于理解。如果您认为它可以更简洁,请随时对其进行编辑。
我有一个客户端-服务器系统,其中客户端向服务器发送不同类型的请求,并根据请求返回响应。
客户端系统中的代码是:
int requestTypeA() {
Request request = new Request(TypeA);
Response response = request.execute();
// response for request of TypeA contains a int
return response.getIntResponse();
}
String requestTypeB() {
Request request = new Request(TypeB);
Response response = request.execute();
// response for request of TypeB contains a String
return response.getStringResponse();
}
为使上述代码正确运行,Request
类是:
class Request {
Type type;
Request(Type type) {
this.type = type;
}
Response execute() {
if (type == TypeA) {
// do stuff
return new Response(someInt);
}
else if (type == TypeB) {
// do stuff
return new Response("someString");
}
else if ...
}
}
和Response
是这样的:
class Response {
int someInt;
String someString;
Response(int someInt) {
this.someInt = someInt;
}
Response(String someString) {
this.someString = someString;
}
int getIntResponse() {
return someInt;
}
String getStringResponse() {
return someString;
}
}
上述方案有两个问题:
execute
方法将充满 if
、else if
block 。someString
未初始化的地方,例如它与 A 类请求的响应混淆了。关于第一个问题,我想到的解决方案是使用多态性。所以有一个父类 Request
并且对于每种类型的请求都有一个 Request
的子类,所以有一个 RequestTypeA
和 RequestTypeB
。所有类都覆盖了 execute
方法。
关于问题 2. 关于如何解决它我只有一个可能的想法:与 Request
类似,根据响应创建 Response
的子类,并有类似的东西这个。
interface Response {
}
class ResponseTypeA {
ResponseTypeA(int i) { ... }
int getIntResponse() { ... }
}
class ResponseTypeB {
ResponseTypeB(String s) { ... verify s is valid ... }
String getStringResponse() { ... }
}
现在我可以确定,如果响应类型为 ResponseTypeB
,它将包含一个有效的字符串。而我可以这样写客户端代码:
String requestTypeB() {
Request request = new Request(TypeB);
ResponseTypeB response = (ResponseTypeB) request.execute();
return response.getStringResponse();
}
现在我必须对 execute
的返回类型进行类型转换。
我的主要问题是:在上述情况下有没有办法避免类型转换?或者您是否知道针对上述问题的更好解决方案(设计模式?)?
最佳答案
试图将请求与响应分开是徒劳的。它们通过 API - R r = f(Q)
绑定(bind)在一起。
您有一个返回 int
的 RequestA
和一个返回 String
的 RequestB
。你显然可以做这样的事情:
class Conversation<Q,R> {
R request (Q q, Class<R> rType) {
// Send the query (Q) and get a response R
}
}
class ConversationA extends Conversation<RequestA, Integer> {
}
class ConversationB extends Conversation<RequestB, String> {
}
一个更充实的版本可能看起来像这样:
public class Test {
// Extend this to magically get a JSON-Like toString.
public static interface JSONObject {
public String asJSON();
}
class RequestA implements JSONObject {
@Override
public String asJSON() {
return "RequestA {}";
}
}
class RequestB implements JSONObject {
@Override
public String asJSON() {
return "RequestB {}";
}
}
static class Conversation<Q extends JSONObject, R> {
// Parser factory.
private static final JsonFactory factory = new JsonFactory();
// General query of the website. Takes an object of type Q and returns one of class R.
public R query(String urlBase, String op, Q q, Class<R> r) throws IOException {
// Prepare the post.
HttpPost postRequest = new HttpPost(urlBase + op);
// Get it all into a JSON string.
StringEntity input = new StringEntity(q.asJSON());
input.setContentType("application/json");
postRequest.setEntity(input);
// Post it and wait.
return requestResponse(postRequest, r);
}
private <R> R requestResponse(HttpRequestBase request, Class<R> r) throws IOException {
// Start a conversation.
CloseableHttpClient httpclient = HttpClients.createDefault();
CloseableHttpResponse response = httpclient.execute(request);
// Get the reply.
return readResponse(response, r);
}
private <R> R readResponse(CloseableHttpResponse response, Class<R> r) throws IOException {
// What was read.
R red = null;
try {
// What happened?
if (response.getStatusLine().getStatusCode() == 200) {
// Roll out the results
HttpEntity entity = response.getEntity();
if (entity != null) {
// Always make sure the content is closed.
try (InputStream content = entity.getContent()) {
red = parseAs(content, r);
}
}
} else {
// The finally below will clean up.
throw new IOException("HTTP Response: " + response.getStatusLine().getStatusCode());
}
} finally {
// Always close the response.
response.close();
}
return red;
}
private <R> R parseAs(InputStream content, Class<R> r) throws IOException {
JsonParser rsp;
// Roll it directly from the response stream.
rsp = factory.createJsonParser(content);
// Bring back the response.
return rsp.readValueAs(r);
}
}
static class ConversationA extends Conversation<RequestA, Integer> {
}
static class ConversationB extends Conversation<RequestB, String> {
}
public void test() throws IOException {
Integer a = new ConversationA().query("http://host/api", "JSON", new RequestA(), Integer.class);
String b = new ConversationB().query("http://host/api", "JSON", new RequestB(), String.class);
}
public static void main(String args[]) {
try {
new Test().test();
} catch (Throwable t) {
t.printStackTrace(System.err);
}
}
}
这源自 JSON
和 Apache HttpClient
的实际使用 - 然而,它可能无法像发布的那样工作,因为我已经删除了大部分错误处理并重试为简单起见的机制。这里主要是为了演示建议机制的使用。
请注意,尽管此代码中没有强制转换(根据问题的要求),但在 rsp.readValueAs(r)
的幕后可能会发生强制转换,您无法绕过JSON
。
关于java - 多态性,如何避免类型转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26151838/
我正在尝试编写一个相当多态的库。我遇到了一种更容易表现出来却很难说出来的情况。它看起来有点像这样: {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE
谁能解释一下这个表达式是如何工作的? type = type || 'any'; 这是否意味着如果类型未定义则使用“任意”? 最佳答案 如果 type 为“falsy”(即 false,或 undef
我有一个界面,在IAnimal.fs中, namespace Kingdom type IAnimal = abstract member Eat : Food -> unit 以及另一个成功
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: What is the difference between (type)value and type(va
在 C# 中,default(Nullable) 之间有区别吗? (或 default(long?) )和 default(long) ? Long只是一个例子,它可以是任何其他struct类型。 最
假设我有一个案例类: case class Foo(num: Int, str: String, bool: Boolean) 现在我还有一个简单的包装器: sealed trait Wrapper[
这个问题在这里已经有了答案: Create C# delegate type with ref parameter at runtime (1 个回答) 关闭 2 年前。 为了即时创建委托(dele
我正在尝试获取图像的 dct。一开始我遇到了错误 The function/feature is not implemented (Odd-size DCT's are not implemented
我正在尝试使用 AFNetworking 的 AFPropertyListRequestOperation,但是当我尝试下载它时,出现错误 预期的内容类型{( “应用程序/x-plist” )}, 得
我在下面收到错误。我知道这段代码的意思,但我不知道界面应该是什么样子: Element implicitly has an 'any' type because index expression is
我尝试将 SignalType 从 ReactiveCocoa 扩展为自定义 ErrorType,代码如下所示 enum MyError: ErrorType { // .. cases }
我无法在任何其他问题中找到答案。假设我有一个抽象父类(super class) Abstract0,它有两个子类 Concrete1 和 Concrete1。我希望能够在 Abstract0 中定义类
我想知道为什么这个索引没有用在 RANGE 类型中,而是用在 INDEX 中: 索引: CREATE INDEX myindex ON orders(order_date); 查询: EXPLAIN
我正在使用 RxJava,现在我尝试通过提供 lambda 来订阅可观察对象: observableProvider.stringForKey(CURRENT_DELETED_ID) .sub
我已经尝试了几乎所有解决问题的方法,其中包括。为 提供类型使用app.use(express.static('public'))还有更多,但我似乎无法为此找到解决方案。 index.js : imp
以下哪个 CSS 选择器更快? input[type="submit"] { /* styles */ } 或 [type="submit"] { /* styles */ } 只是好
我不知道这个设置有什么问题,我在 IDEA 中获得了所有注释(@Controller、@Repository、@Service),它在行号左侧显示 bean,然后转到该 bean。 这是错误: 14-
我听从了建议 registering java function as a callback in C function并且可以使用“简单”类型(例如整数和字符串)进行回调,例如: jstring j
有一些 java 类,加载到 Oracle 数据库(版本 11g)和 pl/sql 函数包装器: create or replace function getDataFromJava( in_uLis
我已经从 David Walsh 的 css 动画回调中获取代码并将其修改为 TypeScript。但是,我收到一个错误,我不知道为什么: interface IBrowserPrefix { [
我是一名优秀的程序员,十分优秀!