There is no control tower here. Each Flight keeps a list of all the other flights and checks them itself before landing. The ISSUE comments in Main.java use the same numbers as the sections below.
The setup
class Flight {
private final String code;
private final List<Flight> otherFlights = new ArrayList<>();
private boolean onRunway;
void addPeer(Flight other) {
otherFlights.add(other);
}
...
}And someone has to link every flight to every other flight:
for (Flight a : flights) {
for (Flight b : flights) {
if (a != b) {
a.addPeer(b);
}
}
}The a != b check skips a flight linking to itself. Three flights make six links. Ten flights make ninety.
What goes wrong
1. The runway rule lives in every flight
void requestLanding() {
for (Flight other : otherFlights) {
if (other.isOnRunway()) {
System.out.println(code + ": runway busy with " + other.code() + ", circling");
return;
}
}
onRunway = true;
...
}Flight should only model a plane. Here it also decides airport policy. When BLR starts using a second runway, you must change Flight, the class every plane shares.
2. Every flight shouts to every other flight
for (Flight other : otherFlights) {
other.hear(code + " is on the runway");
}One landing sends a message to every other plane. With 30 planes in the area, that is 29 calls per event, and most planes do not care.
3. Nobody owns the waiting order
When 6E-512 clears the runway, nobody tells AI-803 to land. Nothing remembers that it was waiting. It must call requestLanding() again and again. If QP-1104 retries at the same moment, both can see a free runway. In real code with threads, that is a race (the result depends on who is faster).
4. Adding one flight means rewiring everyone
A SpiceJet flight joins. It needs every existing flight in its list, and every existing flight needs it in theirs. Miss one addPeer call and that pair of flights can land on top of each other.
5. Testing is painful
To test "AI-803 waits while 6E-512 is landing", you need real Flight objects for both, linked to each other. You cannot swap in a fake, because flights depend on the concrete Flight class, not on an interface.
What the run prints
6E-512: landing now
AI-803 heard: 6E-512 is on the runway
QP-1104 heard: 6E-512 is on the runway
AI-803: runway busy with 6E-512, circling
6E-512: cleared the runway
AI-803 heard: 6E-512 has left the runway
QP-1104 heard: 6E-512 has left the runway
AI-803: landing now
6E-512 heard: AI-803 is on the runway
QP-1104 heard: AI-803 is on the runway
Notice that AI-803 only lands because Main calls requestLanding() a second time. The system itself never told it to.
The smell in one line
When objects hold lists of their siblings and loop over them to decide what to do, the coordination logic needs its own home. That home is the mediator.
Run this version
From the repository root:
mkdir -p out
javac -d out src/DesignPatterns/BehaviouralPatterns/MediatorPattern/Before/Main.java
java -cp out DesignPatterns.BehaviouralPatterns.MediatorPattern.Before.MainWatch AI-803 in the output. It circles once and lands only because Main asks again. That second request shows what is missing: no object remembers the waiting order or owns the handoff.