gpt4 book ai didi

java - 多态性,如何避免类型转换?

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:43:21 25 4
gpt4 key购买 nike

很抱歉问了这么长的问题,但请耐心等待,我已尽力让我的问题尽可能易于理解。如果您认为它可以更简洁,请随时对其进行编辑。

我有一个客户端-服务器系统,其中客户端向服务器发送不同类型的请求,并根据请求返回响应。

客户端系统中的代码是:

 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;
}
}

上述方案有两个问题:

  1. execute 方法将充满 ifelse if block 。
  2. 可能是当返回错误响应时,例如一个 someString 未初始化的地方,例如它与 A 类请求的响应混淆了。

关于第一个问题,我想到的解决方案是使用多态性。所以有一个父类 Request 并且对于每种类型的请求都有一个 Request 的子类,所以有一个 RequestTypeARequestTypeB。所有类都覆盖了 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)在一起。

您有一个返回 intRequestA 和一个返回 StringRequestB。你显然可以做这样的事情:

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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com