當多個對象之間形成網狀耦合(每個對象都直接引用其他對象)時,系統難以維護。中介者模式引入一個中介者對象,將網狀結構轉為星形結構:同事對象不再直接通信,而是通過中介者轉發,降低耦合,集中控制交互邏輯。
| 角色 | 職責 |
|---|---|
| Mediator (抽象中介者) | 定義同事對象通信接口,如 changed(Colleague c) |
| ConcreteMediator (具體中介者) | 實現協調邏輯,持有所有同事引用,知曉具體交互細節 |
| Colleague (抽象同事類) | 持有中介者引用,定義通用行為,需通信時調用 mediator.changed(this) |
| ConcreteColleague (具體同事類) | 實現具體業務,發起/響應通信 |
無主板時,CPU、顯卡、聲卡、光驅需兩兩直接連接、協議適配,極其複雜。有主板後,所有組件只與主板連接,主板負責數據分發、協議轉換。
public abstract class Colleague {
protected Mediator mediator;
public Colleague(Mediator mediator) { this.mediator = mediator; }
public Mediator getMediator() { return mediator; }
}
public class CDDriver extends Colleague {
private String data = "";
public CDDriver(Mediator m) { super(m); }
public String getData() { return data; }
public void readCD() {
data = "One Piece,海賊王我當定了"; // 視頻,音頻
getMediator().changed(this); // 通知主板
}
}
public class CPU extends Colleague {
private String videoData, soundData;
public CPU(Mediator m) { super(m); }
public String getVideoData() { return videoData; }
public String getSoundData() { return soundData; }
public void executeData(String data) {
String[] arr = data.split(",");
videoData = arr[0]; soundData = arr[1];
getMediator().changed(this); // 通知主板處理完畢
}
}
public class VideoCard extends Colleague {
public VideoCard(Mediator m) { super(m); }
public void showData(String data) { System.out.println("您正在觀看的是:" + data); }
}
public class SoundCard extends Colleague {
public SoundCard(Mediator m) { super(m); }
public void soundData(String data) { System.out.println("畫外音:" + data); }
}
public interface Mediator {
void changed(Colleague c);
}
public class MainBoard implements Mediator {
private CDDriver cdDriver;
private CPU cpu;
private VideoCard videoCard;
private SoundCard soundCard;
public void setCdDriver(CDDriver cd) { this.cdDriver = cd; }
public void setCpu(CPU cpu) { this.cpu = cpu; }
public void setVideoCard(VideoCard vc) { this.videoCard = vc; }
public void setSoundCard(SoundCard sc) { this.soundCard = sc; }
@Override
public void changed(Colleague c) {
if (c instanceof CDDriver) opeCDDriverReadData((CDDriver) c);
else if (c instanceof CPU) opeCPU((CPU) c);
}
private void opeCDDriverReadData(CDDriver cd) {
cpu.executeData(cd.getData()); // 數據傳給 CPU
}
private void opeCPU(CPU cpu) {
videoCard.showData(cpu.getVideoData());
soundCard.soundData(cpu.getSoundData());
}
}
public class Client {
public static void main(String[] args) {
MainBoard mb = new MainBoard();
CDDriver cd = new CDDriver(mb);
CPU cpu = new CPU(mb);
VideoCard vc = new VideoCard(mb);
SoundCard sc = new SoundCard(mb);
mb.setCdDriver(cd);
mb.setCpu(cpu);
mb.setVideoCard(vc);
mb.setSoundCard(sc);
cd.readCD(); // 觸發全鏈路
}
}
您正在觀看的是:One Piece 畫外音:海賊王我當定了
| 優點 | 缺點 |
|---|---|
| 鬆耦合:同事對象互不引用,單獨復用容易 | 中介者膨脹:交互邏輯集中導致中介者類過於龐大、難維護 |
| 集中控制:修改交互只需改中介者,符合開閉原則 | 單點故障:中介者故障導致整個系統通信癱瘓 |
| 多對多 → 一對多:結構清晰,易於理解 | 間接性能開銷:多一次轉發調用 |