我在这里遇到的困境是什么是什么,什么不是循环参考......以及如何在肯定的情况下摆脱它。
假设我有一个Main
类来实例化两个不同的类,其中每个类都需要在另一个类中执行一个方法:
MyMain {
AlarmManager alarmManager;
DatabaseManager databaseManager;
MyMain() {
alarmManager = new AlarmManager(dataBaseManager);
databaseManager = new DatabaseManager (alarmManager);
}
AlarmManager getAlarmManager() {
return alarmManager;
}
DatabaseManager getDatabasetManager() {
return databaseManager;
}
}
班级:
AlarmManager {
DatabaseManager dataBaseManager;
onAlarm(alarm) {
dataBaseManager.saveInHistorical(alarm);
sendAlarm(alarm);
}
sendAlarm(alarm) {
socketWriter(alarm);
}
}
DatabaseManager{
AlarmManager alarmManager;
onDatabaseConnectionError() {
saveInHistorical(databaseAlarm);
alarmManager.sendAlarm(databaseAlarm);
}
saveInHistorical(historical) {
connection.store(historical);
}
}
我想你通过查看代码得到了这个想法。如果有警报,我们会在AlarmManager中收到警报,但需要将其保存在历史数据库中。但是,如果我们与历史数据库存在连接错误,我们还需要发送警报。
这真的是一个循环引用,其中main有报警但是报警也有主要和数据库/ main相同?你会如何解决它?
答案 0 :(得分:2)
CAD开发时遇到了类似的问题。在每个电子CAD中,您都有一些组件端口和信号线,用于表示端口之间的连接。线路和端口是多对多连接:每条线路必须保持一个绑定在一起的端口列表,并且端口必须注意连接到它们的线路。因此,每次用户想要连接两个端口时,他都会创建一条线并通过
将线连接到每个端口line.add(port)
port.add(line)
这两项操作必须始终一起执行。这意味着它们必须被抽象为一个过程:调用line.add(port)
会自动调用port.add(line)
,并且通过对称,port.add(line)
应该调用line.add(port)
。好吧,我们处于恶性循环中,正是你在问题中所拥有的那个!
line.add
,隐藏了它所调用的port.add
,在我的网表操作API之后。这样,port.add
不需要再调用line.add
,因为我们知道我们只在port.add
,因为line.add
已经发生了。
我可以通过引入公开port.add
和line.add
来恢复对称性,这会调用API私有line.onAdd(port)
和port.onAdd(line)
回调。这似乎也是微不足道的。然而,你是对的问这个问题。我鼓励你提出我的回应,但不接受。我想知道正确的(OOP)答案。
答案 1 :(得分:0)
试试这个:
MyMain() {
alarmManager = new AlarmManager();
databaseManager = new DatabaseManager();
alarmManager.setDatabaseManager(databaseManager);
databaseManager.setAlarmManager(alarmManager);
}
您的alarmManager类有一个setDatabaseManager方法。
您的databaseManager类有一个setAlarmManager方法。
答案 2 :(得分:0)
Gilbert有一个很好的方法,但另一种方法是让alarmManager和databaseManager都引用彼此的MyMain
而不是。 e.g。
AlarmManager {
MyMain myMain; // set in the constructor, could be final
onAlarm(alarm) {
myMain.getDataBaseManager().saveInHistorical(alarm);
sendAlarm(alarm);
}
sendAlarm(alarm) {
socketWriter(alarm);
}
}
DatabaseManager{
MyMain myMain; // set in the constructor, could be final
onDatabaseConnectionError() {
saveInHistorical(databaseAlarm);
myMain.getAlarmManager().sendAlarm(databaseAlarm);
}
saveInHistorical(historical) {
connection.store(historical);
}
}