java - 需要提取一个接口,但是在实现中有一种方法是额外的
问题描述
我编写消息传输,允许将消息从一个对象传输到另一个对象。所以它有像send
和这样的方法receive
我有两种实现:
- InMemoryTransport 在线程之间传输消息并基于阻塞队列
- SocketTransport 通过套接字传输消息
InMemoryTransport
执行:
public class InMemoryTransport {
private ConcurrentHashMap<String, BlockingQueue<Parcel>> parcelList = new ConcurrentHashMap<>();
public void send(Parcel parcel) {
parcelList.computeIfAbsent(parcel.getReceiverName(), (n) -> new LinkedBlockingQueue<>()).add(parcel);
}
public Parcel receive(String recipient) {
Parcel poll;
try {
poll = parcelList.computeIfAbsent(recipient, (n) -> new LinkedBlockingQueue<>()).take();
} catch (InterruptedException e) {
return null;
}
return poll;
}
}
SocketTransport
执行:
public class SocketParcelTransport {
private ConcurrentHashMap<String, SocketWraper> listeners = new ConcurrentHashMap<>();
public void register(String compomentName, Socket socket) throws IOException {
listeners.putIfAbsent(compomentName, new SocketWraper(socket));
}
public void send(Parcel message) {
try {
listeners.get(message.getReceiverName()).getOutputStream().writeObject(message);
listeners.get(message.getReceiverName()).getOutputStream().flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public Parcel receive(String recipient) {
try {
return (Parcel) listeners.get(recipient).getInputStream().readObject();
} catch (IOException e) {
// ignore. Just return null in case of io exception
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
class SocketWraper {
// main idea of this class is to create input and output stream from socket
public ObjectInputStream getInputStream() throws IOException {
...
}
public ObjectOutputStream getOutputStream() {
...
}
}
}
所以,我想为这两个实现提取一个接口。两种实现都有两个相同的方法,可以很容易地提取:void send(Parcel parcel)
和Parcel receive(String recipient)
但是SocketParcelTransport
有方法void register(String name, Socket socket)
。我不知道该怎么办。
我可以制作方法register(String compomentName)
,InMemoryTransport
但我应该将什么作为第二个参数传递?传递BlockingQueue<Parcel>
将是一个非常糟糕的主意,因为我想封装这些细节。
如果我不会提取void register(String compomentName, Socket socket)
到界面,我该如何使用SocketParcelTransport
?因为当你使用 DI - 你只使用接口
更新1:
在接口中创建默认方法,所以接口看起来像
public interface ParcelTransport {
default <T> void register(String componentName, T dataSource) {
// do nothing
};
void send(Parcel message);
Parcel receive(String recipient);
}
在这种情况下,我的 SocketParcelTransport 将如下所示,我该如何传递Socket
给register()
public class SocketParcelTransport implements ParcelTransport {
@Override
public <T> void register(String componentName, T dataSource) {
Socket socket = dataSource; // how Can I pass socket here??
}
如果我将界面更改为
public interface ParcelTransport<T> {
default void register(String componentName, T dataSource) {
// do nothing
};
...
在那种情况下,我的InMemoryTransport
班级会给我警告raw use of parametrized class
public class ThreadsParcelTransport implements ParcelTransport {
...
}
解决方案
- 只需创建两个接口(一个扩展另一个接口)。第一个将有内部的常用方法,第二个将有额外的方法。
- 默认接口方法(将侦听器列表移动到接口)
推荐阅读
- asp.net - Razor 页面部分视图:模型未定义
- three.js - Three.js:使用实例化几何处理每个实例的纹理偏移
- actions-on-google - 价格对象交易 API 中的纳米十进制表示法通过以 0 开头的数字出错
- javascript - 触发jquery后如何获取返回值?
- r - 在登录R之前提取数据
- php - 是什么导致 PHP 中的 fopen() 函数将第一个参数(即 URL)中的“&”转换为“&”
- vue.js - 试图弄清楚如何使用 Axios 在 Vue.js 上发出 GET 请求,但没有这样做
- python - 从 dev_appserver 连接到 Firebase 时出错:VerifiedHTTPSConnection 对象没有属性 _tunnel_host
- c++ - 静态初始化惨败只发生在 C++ 中吗?
- aframe - 组合多个不同的 Aframe 代码