原创文章,如有转载,请注明出处:http://blog.csdn.net/yihui823/article/details/6833131
前段时间,看到别人的一段代码,其实没什么逻辑,却做的丰富异常。
代码运行极其不稳定,却无从下手去改动。后来下定决心重写了。
昨晚有空,把原来不良代码抽取出来,供大家参考。
package testpj;
import java.util.Timer;
import java.util.TimerTask;
/**
* 高耦合的展示类
* @author yihui823
*/
public class CouplingTester {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Connect conn = new Connect();
Listener l = new Listener(conn);
conn.setListener(l);
l.onConnFailed("first connect");
//循环查看Connect的对象
while(true) {
System.out.println(l.getConnect().hashCode());
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
}
}
}
/**
* 模拟一个连接类
*/
private static class Connect extends Thread {
//监听器
private Listener listener;
/**
* 设置监听器
* @param listener 监听器
*/
public void setListener(Listener listener) {
this.listener = listener;
}
/**
* 线程方法,开始进行连接.
*/
public void run() {
//假设连接失败
try {
//保持连接
Thread.sleep(2000);
listener.onConnFailed("Connecting error!");
System.out.println("连接失败.");
} catch (InterruptedException ex) {
}
//假设连接成功
// System.out.println("连接成功.");
// while (true) {
// try {
// //保持连接
// Thread.sleep(2000);
// System.out.println("保持连接.");
// } catch (InterruptedException ex) {
// }
// }
}
}
/**
* 模拟监听器
*/
private static class Listener {
private Connect conn;
private Timer timer = null;
public Listener(Connect conn) {
this.conn = conn;
}
public Connect getConnect() {
return conn;
}
/**
* 连接失败时调用
* @param msg 失败消息
*/
public void onConnFailed(String msg) {
System.out.println("Connect failued : " + msg);
timer = new Timer();
ConnectTask ct = new ConnectTask(timer, conn);
timer.schedule(ct, 3000, 100);
}
}
/**
* 一个连接任务类
*/
public static class ConnectTask extends TimerTask {
private Connect conn;
private Timer timer = null;
public ConnectTask(Timer timer, Connect conn) {
this.timer = timer;
this.conn = conn;
}
public void run() {
if (conn.isAlive()) {
System.out.println(conn.hashCode() + " is still alive.");
if (timer != null) {
timer.cancel();
timer = null;
}
} else {
System.out.println(conn.hashCode() + " is not alive.");
conn = new Connect();
conn.setListener(new Listener(conn));
conn.start();
}
}
}
}
Connect类里的run方法,原来是做连接用的,这里用简单的代码去模拟了。
我们可以看到,这段代码的逻辑,其实是要做一个重连接。
也就是说,当连接断了之后,自动触发onConnFailed事件,然后再次去做连接。
在这个例子里面,Connect里面保存了Listener,而Listener里面又保存了Connect,
ConnectTask里面也保存了Connect。三个类紧紧的耦合在一起,
一个简单的逻辑有两个线程在运作。其结果,是一旦有一次失败了,
则会多一个Timer在后台持续运行,而这个Timer不会被标记停止。
这里主要的问题,就是三个类的高耦合。而良好的代码,是需要做到:高内聚,低耦合的。也就是说,类与类之间的关系,越松散越好,最好能相互独立。
解耦改动的方法:
1,Connect里面设置Listener。但是,Listener里面,不记录Connect实例。
2,在onConnFailed事件中,只是做启动连接的动作,不要启动线程。再次连接之前,暂停一段时间即可。
具体代码就不贴出来了。重点就是:不要高耦合。