如何为实现相同接口的两个 类 创建双向适配器?
How to make bidirectional adapter for two classes that implement the same interface?
interface Server
{
void accept(String xml);
void send();
}
class ServerThatUsesXML implements Server
{
Server server;
@Override
public void accept(String xml) {
if (xml.equals("XML"))
System.out.println("Data accepted successfully.");
else
System.out.println("There was a problem in processing the data.");
}
@Override
public void send() {
server.accept("XML");
}
}
class ServerThatUsesJSON implements Server
{
Server server;
@Override
public void accept(String json) {
if (json.equals("JSON"))
System.out.println("Data accepted successfully.");
else
System.out.println("There was a problem in processing the data.");
}
@Override
public void send() {
server.accept("JSON");
}
}
class Converter
{
public String convertToXML(String json)
{
return "XML";
}
public String convertToJSON(String xml)
{
return "JSON";
}
}
class Adapter implements Server
{
Server xml, json;
Converter converter = new Converter();
public Adapter(Server xml, Server json) {
this.xml = xml;
this.json = json;
}
@Override
public void accept(String input) {
// converter.convertTo...
}
@Override
public void send() {
// converter.convertTo...
}
}
public class Main {
public static void main(String[] args) {
ServerThatUsesXML xml = new ServerThatUsesXML();
ServerThatUsesJSON json = new ServerThatUsesJSON();
xml.server = json;
json.server = xml;
xml.send(); // There was a problem in processing the data.
json.send(); // There was a problem in processing the data.
Adapter adapter = new Adapter(xml, json);
xml.server = adapter;
json.server = adapter;
xml.send();
json.send();
// Both calls should print "Data accepted successfully.".
}
}
在这个例子中,我有两台服务器。不幸的是,一台服务器使用 XML
,而另一台服务器使用 JSON
。他们都必须相互沟通。所以我制作了一个实现 Server
接口并包含两个服务器的适配器。我希望每当 ServerThatUsesXML
向适配器发送内容时,适配器将其转换为 JSON
并将其转发给 ServerThatUsesJSON
。将 JSON
请求转换为 XML
请求也是如此。
问题在于,由于两台服务器实现了相同的接口,因此两台服务器具有相同的方法和相同的签名。因此,例如,当我在 Adapter
上调用 accept
时,Adapter
将不知道请求来自何处以及请求应采用哪种方式。我应该将它传递给 JSON
服务器吗?还是我应该将它传递给 XML
服务器?
我有两个解决方案,但它们看起来不太干净...所以我想问一下是否有更好的方法来解决这个问题。
第一个解决方案:检查文本的格式。如果是 XML
文本,将其转换为 JSON
并将其发送到 ServerThatUsesJSON
。从 JSON
转换为 XML
的请求也是如此。这种方法可能是最糟糕的,因为它不检查发件人并仅根据文本格式转发请求。它还通过文本检查格式。这样效率不高。
第二种解决方案:制作两个适配器,一个接受XML
并发送JSON
,另一个接受JSON
并发送XML
。然后将第一个传递给ServerThatUsesXML
。并将第二个传递给 ServerThatUsesJSON
。这个解决方案看起来比第一个更好(至少它更有效)。
我的问题是:我可以创建两个 accept
函数,例如 accpetXML
和 acceptJSON
并在 accept
函数中,具体取决于调用者的类型,我要么调用 XML
版本,要么调用 JSON
版本。代码应如下所示:
public void accept(String input, ....)
{
if (senderType == ServerThatUsesXML)
acceptJSON(converter.convertToJSON(input));
else
acceptXML(converter.convertToXML(input));
}
GoF 在第 143 页提到 "two-way adapters"。
Specifically, they're useful when two different clients need to view an object differently.
然而,对于Server
界面,不同的客户端以完全相同的方式查看它。只有一个接口可以适配而不是两个,所以这是双向适配器可能不适合的线索。
GoF 中的示例显示了使用多重继承的双向 class 适配器。
Multiple inheritance is a viable solution in this case because the interfaces of the adapted classes are substantially different. The two-way class adapter conforms to both of the adapted classes and can work in either system.
很明显,这告诉我们双向 class 适配器不适合 Server
用例。我认为有足够的证据可以得出这样的结论:用相同的接口适配两个 classes 根本不是双向适配器的可行用途。虽然 GoF 没有提到双向 object 适配器(使用组合而不是多重继承),但它似乎遇到了一个 API 的不同输入格式的相同问题。
顺便说一句,不同字符串格式的问题更多是Stringly Typed 编程的影响。它可以通过使用对象而不是原语编程来解决。如果服务器反序列化它们的输入,问题就消失了。这是一个令人惊讶的常见问题:服务器有类型信息(因为它们知道接受什么格式)但是它们通过将序列化数据(例如字符串)传递给必须处理不同格式的另一个对象来丢弃该信息。
回到适配器模式的主题,您可以实现不同的(单向)适配器:一个专门用于转换为 JSON 的 XML 服务器,另一个专门用于 JSON 转换为 XML 的服务器。此解决方案类似于将 Converter
传递给每个 Server
并使 String 格式成为 Server
的问题的注释,这与避免传播字符串的反序列化解决方案本质上相同。
interface Server
{
void accept(String xml);
void send();
}
class ServerThatUsesXML implements Server
{
Server server;
@Override
public void accept(String xml) {
if (xml.equals("XML"))
System.out.println("Data accepted successfully.");
else
System.out.println("There was a problem in processing the data.");
}
@Override
public void send() {
server.accept("XML");
}
}
class ServerThatUsesJSON implements Server
{
Server server;
@Override
public void accept(String json) {
if (json.equals("JSON"))
System.out.println("Data accepted successfully.");
else
System.out.println("There was a problem in processing the data.");
}
@Override
public void send() {
server.accept("JSON");
}
}
class Converter
{
public String convertToXML(String json)
{
return "XML";
}
public String convertToJSON(String xml)
{
return "JSON";
}
}
class Adapter implements Server
{
Server xml, json;
Converter converter = new Converter();
public Adapter(Server xml, Server json) {
this.xml = xml;
this.json = json;
}
@Override
public void accept(String input) {
// converter.convertTo...
}
@Override
public void send() {
// converter.convertTo...
}
}
public class Main {
public static void main(String[] args) {
ServerThatUsesXML xml = new ServerThatUsesXML();
ServerThatUsesJSON json = new ServerThatUsesJSON();
xml.server = json;
json.server = xml;
xml.send(); // There was a problem in processing the data.
json.send(); // There was a problem in processing the data.
Adapter adapter = new Adapter(xml, json);
xml.server = adapter;
json.server = adapter;
xml.send();
json.send();
// Both calls should print "Data accepted successfully.".
}
}
在这个例子中,我有两台服务器。不幸的是,一台服务器使用 XML
,而另一台服务器使用 JSON
。他们都必须相互沟通。所以我制作了一个实现 Server
接口并包含两个服务器的适配器。我希望每当 ServerThatUsesXML
向适配器发送内容时,适配器将其转换为 JSON
并将其转发给 ServerThatUsesJSON
。将 JSON
请求转换为 XML
请求也是如此。
问题在于,由于两台服务器实现了相同的接口,因此两台服务器具有相同的方法和相同的签名。因此,例如,当我在 Adapter
上调用 accept
时,Adapter
将不知道请求来自何处以及请求应采用哪种方式。我应该将它传递给 JSON
服务器吗?还是我应该将它传递给 XML
服务器?
我有两个解决方案,但它们看起来不太干净...所以我想问一下是否有更好的方法来解决这个问题。
第一个解决方案:检查文本的格式。如果是 XML
文本,将其转换为 JSON
并将其发送到 ServerThatUsesJSON
。从 JSON
转换为 XML
的请求也是如此。这种方法可能是最糟糕的,因为它不检查发件人并仅根据文本格式转发请求。它还通过文本检查格式。这样效率不高。
第二种解决方案:制作两个适配器,一个接受XML
并发送JSON
,另一个接受JSON
并发送XML
。然后将第一个传递给ServerThatUsesXML
。并将第二个传递给 ServerThatUsesJSON
。这个解决方案看起来比第一个更好(至少它更有效)。
我的问题是:我可以创建两个 accept
函数,例如 accpetXML
和 acceptJSON
并在 accept
函数中,具体取决于调用者的类型,我要么调用 XML
版本,要么调用 JSON
版本。代码应如下所示:
public void accept(String input, ....)
{
if (senderType == ServerThatUsesXML)
acceptJSON(converter.convertToJSON(input));
else
acceptXML(converter.convertToXML(input));
}
GoF 在第 143 页提到 "two-way adapters"。
Specifically, they're useful when two different clients need to view an object differently.
然而,对于Server
界面,不同的客户端以完全相同的方式查看它。只有一个接口可以适配而不是两个,所以这是双向适配器可能不适合的线索。
GoF 中的示例显示了使用多重继承的双向 class 适配器。
Multiple inheritance is a viable solution in this case because the interfaces of the adapted classes are substantially different. The two-way class adapter conforms to both of the adapted classes and can work in either system.
很明显,这告诉我们双向 class 适配器不适合 Server
用例。我认为有足够的证据可以得出这样的结论:用相同的接口适配两个 classes 根本不是双向适配器的可行用途。虽然 GoF 没有提到双向 object 适配器(使用组合而不是多重继承),但它似乎遇到了一个 API 的不同输入格式的相同问题。
顺便说一句,不同字符串格式的问题更多是Stringly Typed 编程的影响。它可以通过使用对象而不是原语编程来解决。如果服务器反序列化它们的输入,问题就消失了。这是一个令人惊讶的常见问题:服务器有类型信息(因为它们知道接受什么格式)但是它们通过将序列化数据(例如字符串)传递给必须处理不同格式的另一个对象来丢弃该信息。
回到适配器模式的主题,您可以实现不同的(单向)适配器:一个专门用于转换为 JSON 的 XML 服务器,另一个专门用于 JSON 转换为 XML 的服务器。此解决方案类似于将 Converter
传递给每个 Server
并使 String 格式成为 Server
的问题的注释,这与避免传播字符串的反序列化解决方案本质上相同。