cru*_*ush 5 java factory circular-dependency code-cleanup
我在一个项目中使用Netty(4.0.4.Final),并且我一直在遇到一个我需要考虑的循环依赖.这个问题主要涉及分解循环依赖的概念,但我会在熟悉的人中使用一些Netty术语.既然我的问题实际上并不在于Netty,我决定不对其进行标记.
下面,我发布了我的代码,省略了我认为不相关的部分.
我有一个MyServer类添加ChannelInboundHandlerAdapter到Bootstrap:
public class MyServer extends AbstractMyServer {
private Integer someInteger; //Using Integer just for example's sake.
public MyServer(MyServerInitializer initializer) {
//...
bootstrap.handler(initializer);
//...
}
public void updateInteger(Integer value) {
someInteger = value;
//Send an update packet to another server.
}
}
Run Code Online (Sandbox Code Playgroud)
MyServerInitializer需要添加ChannelInboundHandlerAdapter到ChannelPipeline:
public class MyServerInitializer extends ChannelInitializer<SocketChannel> {
private ChannelInboundHandlerAdapter handler;
public MyServerInitializer(ChannelInboundHandlerAdapter handler) {
this.handler = handler;
}
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(
new ObjectEncoder(),
new ObjectDecoder(),
handler);
}
}
Run Code Online (Sandbox Code Playgroud)
我也有一个MyServerHandler构造函数参数,MyServerInitializer在我说的情况下:
public class MyServerHandler extends ChannelInboundHandlerAdapter {
private MyServer server;
public MyServerHandler(MyServer server) {
this.server = server;
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
Integer obj = (Integer) msg; //Remember just using Integer for example. Think of it as an Object rather than an Integer.
server.updateInteger(obj);
}
}
Run Code Online (Sandbox Code Playgroud)
因此,循环依赖在初始化期间变得明显:
public static void main(String[] args) {
//I can't set a reference to MyServer instance here because it hasn't been created yet. I want to avoid the circular dependency here.
MyServerHandler handler = new MyServerHandler(...);
MyServerInitializer initializer = new MyServerInitializer(handler);
MyServer server = new MyServer(initializer);
}
Run Code Online (Sandbox Code Playgroud)
main()我可以拉的创造Integer someInteger出来的MyServer,在范围创建它main()的功能,再注入它的引用到MyServerHandler和MyServer.这当然MyServerHandler可以直接修改它,而不必经历MyServer.退缩是它已在main()现在的范围内宣布.我不想为每个可能基本上需要由Handler类修改的类成员执行此操作.
MyServerFactory我读到的一个概念是将构造与使用分开.这很有意义,所以我用下面的Factory模式实现了它.
public class MyServerFactory implements AbstractFactory<MyServer> {
public MyServer create() {
Integer someInteger = createInteger();
MyServerHandler handler = createHandler(someInteger);
MyServerInitializer initializer = createInitializer(handler);
return new MyServer(initializer);
}
/* creator methods for the different components above. */
}
Run Code Online (Sandbox Code Playgroud)
但是,这似乎只是简单地将代码移到了main()这个Factory类.
问题
Handler成MyServerInitializer也许这个新的- Handler不接受Integer作为参数.我是否必须Factory为此案例创建一个新的?Factory可能只会创建单个实例的有意义MyServer吗?粗体问题是我在StackOverflow上问这个问题的主要焦点.我觉得我必须在这里忽略更简单或更优雅的东西.我希望你们中的一些更有经验的用户可以提供一些见解.如果需要更多信息,请告诉我.
免责声明:我对 Netty 不太了解,这些只是阅读您的代码时的一些想法:
我没有看到任何问题MyServerInitializer。对或MyServerInitializer没有任何依赖性。没关系。如果 的构造函数使用 require而不是,情况会更糟。MyServerHandlerMyServerMyServerInitializerMyServerHandlerChannelInboundHandlerAdapter
如果可能,您应该将构造函数参数MyServer从MyServerInitializerfrom更改为ChannelInitializer<SocketChannel>。
问题是MyServerHandler依赖于MyServerwhileMyServer对 具有间接的运行时依赖MyServerHandler。我会尝试摆脱MyServer对MyServerHandler. 为此,您可以:
将该updateInteger()方法从MyServer另一个类中移至另一个类中,我们称之为IntegerUpdater。MyServerHandler应该使用IntegerUpdater而不是MyServer. IntegerUpdater应该不依赖于MyServer. 使用这种方式,您将不会有任何循环依赖。
MyServerHandler在和之间添加抽象MyServer。例如:
public interface IntegerMessageReceiver {
void handleMessage(Integer i);
}
Run Code Online (Sandbox Code Playgroud)-
public class MyServerHandler extends ChannelInboundHandlerAdapter {
private List<IntegerMessageReceiver> integerMessageReceivers;
public void addIntegerMessageReceiver(IntegerMessageReceiver imr) {
integerMessageReceivers.add(imr);
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
Integer obj = (Integer) msg;
for (IntegerMessageReceiver imr : integerMessageReceivers) {
imr.handleMessage(obj);
}
}
}
Run Code Online (Sandbox Code Playgroud)
-
public class MyServer extends AbstractMyServer implements IntegerMessageReceiver {
public void handleMessage(Integer i) {
...
}
...
}
Run Code Online (Sandbox Code Playgroud)
初始化:
MyServerHandler handler = new MyServerHandler();
MyServerInitializer initializer = new MyServerInitializer(handler);
MyServer server = new MyServer(initializer);
handler.addIntegerMessageReceiver(server);
Run Code Online (Sandbox Code Playgroud)
使用这种方法,您仍然会具有循环运行时依赖项,但至少您摆脱了MyServerin的直接编译时依赖项MyServerHandler。
| 归档时间: |
|
| 查看次数: |
1508 次 |
| 最近记录: |