中介者模式
案例介紹:
編寫信息管理模塊:
界面組件之間存在較爲複雜的交互關係:如果刪除一個客戶,要在客戶列表(List)中刪掉對應的項,客戶選擇組合框(ComboBox)中客戶名稱也將減少一個;如果增加一個客戶信息,客戶列表中需增加一個客戶,且組合框中也將增加一項。
如果實現界面組件之間的交互一個問題?
(1) 當用戶單擊“增加”按鈕、“刪除”按鈕、“修改”按鈕或“查詢”按鈕時,界面左側的“客戶選擇組合框”、“客戶列表”以及界面中的文本框將產生響應。
(2) 當用戶通過“客戶選擇組合框”選中某個客戶姓名時,“客戶列表”和文本框將產生響應。
(3) 當用戶通過“客戶列表”選中某個客戶姓名時,“客戶選擇組合框”和文本框將產生響應。
於是開發人員根據組件之間的交互關係繪製瞭如圖20-3所示初始類圖:
設計方案存在如下問題:
(1) 系統結構複雜且耦合度高:每一個界面組件都與多個其他組件之間產生相互關聯和調用,若一個界面組件對象發生變化,需要跟蹤與之有關聯的其他所有組件並進行處理,系統組件之間呈現一種較爲複雜的網狀結構,組件之間的耦合度高。
(2) 組件的可重用性差:由於每一個組件和其他組件之間都具有很強的關聯,若沒有其他組件的支持,一個組件很難被另一個系統或模塊重用,這些組件表現出來更像一個不可分割的整體,而在實際使用時,我們往往需要每一個組件都能夠單獨重用,而不是重用一個由多個組件組成的複雜結構。
(3) 系統的可擴展性差:如果在上述系統中增加一個新的組件類,則必須修改與之交互的其他組件類的源代碼,將導致多個類的源代碼需要修改,同樣,如果要刪除一個組件也存在類似的問題,這違反了“開閉原則”,可擴展性和靈活性欠佳。
由於存在上述問題,Sunny公司開發人員不得不對原有系統進行重構,那如何重構呢?大家想到了“迪米特法則”,引入一個“第三者”來降低現有系統中類之間的耦合度。由這個“第三者”來封裝並協調原有組件兩兩之間複雜的引用關係,使之成爲一個鬆耦合的系統,這個“第三者”又稱爲“中介者”,中介者模式因此而得名。
你中有我,我中有你,不利於鬆耦合
中介者模式基本介紹
- 中介者模式(Mediator Pattern),用一箇中介對象來封裝一系列的對象交互。
中介者使各個對象不需要顯式地相互引用,從而使其耦合鬆散,而且可以獨立
地改變它們之間的交互 - 中介者模式屬於行爲型模式,使代碼易於維護
- 比如MVC模式,C(Controller控制器)是M(Model模型)和V(View視圖)的中介者,在前後端交互時起到了中間人的作用
對象之間存在大量的多對多聯繫,將導致系統非常複雜,這些對象既會影響別的對象,也會被別的對象所影響,這些對象稱爲同事對象,它們之間通過彼此的相互作用實現系統的行爲。在網狀結構中,幾乎每個對象都需要與其他對象發生相互作用,而這種相互作用表現爲一個對象與另外一個對象的直接耦合,這將導致一個過度耦合的系統。
中介者模式是“迪米特法則”的一個典型應用。
中介者模式類圖:
中介者模式角色:
● Mediator(抽象中介者):它定義一個接口,該接口用於與各同事對象之間進行通信。
● ConcreteMediator(具體中介者):它是抽象中介者的子類,通過協調各個同事對象來實現協作行爲,它維持了對各個同事對象的引用。
● Colleague(抽象同事類):它定義各個同事類公有的方法,並聲明瞭一些抽象方法來供子類實現,同時它維持了一個對抽象中介者類的引用,其子類可以通過該引用來與中介者通信。
● ConcreteColleague(具體同事類):它是抽象同事類的子類;每一個同事對象在需要和其他同事對象通信時,先與中介者通信,通過中介者來間接完成與其他同事類的通信;在具體同事類中實現了在抽象同事類中聲明的抽象方法。
中介者類承擔了兩方面的職責:
(1) 中轉作用(結構性):通過中介者提供的中轉作用,各個同事對象就不再需要顯式引用其他同事,當需要和其他同事進行通信時,可通過中介者來實現間接調用。該中轉作用屬於中介者在結構上的支持。
(2) 協調作用(行爲性):中介者可以更進一步的對同事之間的關係進行封裝,同事可以一致的和中介者進行交互,而不需要指明中介者需要具體怎麼做,中介者根據封裝在自身內部的協調邏輯,對同事的請求進行進一步處理,將同事成員之間的關係行爲進行分離和封裝。該協調作用屬於中介者在行爲上的支持。
代碼實現:
抽象組件類;抽象同事類
`
public abstract class Component {
protected Mediator mediator;
public void setMediator(Mediator mediator) {
this.mediator = mediator;
}
public void changed (){
mediator.componentChanged(this);
}
public abstract void update();
}
具體同事類: 按鈕組件
/**
* @author 孫一鳴 on 2020/2/20
*/
public class MyButton extends Component{
@Override
public void update() {
//按鈕不產生交互
}
}
具體同事類:組合框類
/**
* 組合框類:具體同事類
* @author 孫一鳴 on 2020/2/20
*/
public class MyComboBox extends Component {
public void update() {
System.out.println("組合框增加一項:比爾蓋茨。");
}
public void select() {
System.out.println("組合框選中項:馬雲");
}
}
具體同事類:列表框類
/**
* 列表框類:具體同事類
* @author 孫一鳴 on 2020/2/20
*/
public class MyList extends Component{
@Override
public void update() {
System.out.println("列表框新加同事:比爾蓋茨");
}
public void select (){
System.out.println("列表框選中項:馬雲");
}
}
具體同事類:文本框類
/**
* //文本框類:具體同事類
*
* @author 孫一鳴 on 2020/2/20
*/
public class MyTextBox extends Component {
public void update() {
System.out.println("客戶信息增加成功後文本框清空。");
}
public void setText() {
System.out.println("文本框顯示:馬雲");
}
}
抽象中介者類:
/**
*
//抽象中介者
* @author 孫一鳴 on 2020/2/20
*/
public abstract class Mediator {
public abstract void componentChanged(Component c);
}
具體中介者類:
/**
* 具體中介者
*
* @author 孫一鳴 on 2020/2/20
*/
public class ConcreteMediator extends Mediator{
//維持對多個同事對象的引用
public MyButton addButton;
public MyList list;
public MyTextBox userNameTextBox;
public MyComboBox cb;
//封裝同事對象之間的交互
@Override
public void componentChanged(Component c) {
//單擊按鈕
if(c == addButton) {
System.out.println("--單擊增加按鈕--");
list.update();
cb.update();
userNameTextBox.update();
}
//從列表框選擇客戶
else if(c == list) {
System.out.println("--從列表框選擇客戶--");
cb.select();
userNameTextBox.setText();
}
//從組合框選擇客戶
else if(c == cb) {
System.out.println("--從組合框選擇客戶--");
cb.select();
userNameTextBox.setText();
}
}
}
測試類:
/**
* @author 孫一鳴 on 2020/2/20
*/
public class Client {
public static void main(String args[]) {
//定義中介者對象
ConcreteMediator mediator;
mediator = new ConcreteMediator();
//定義同事對象
MyButton addBT = new MyButton();
MyList list = new MyList();
MyComboBox cb = new MyComboBox();
MyTextBox userNameTB = new MyTextBox();
addBT.setMediator(mediator);
list.setMediator(mediator);
cb.setMediator(mediator);
userNameTB.setMediator(mediator);
mediator.addButton = addBT;
mediator.list = list;
mediator.cb = cb;
mediator.userNameTextBox = userNameTB;
addBT.changed();
System.out.println("-----------------------------");
list.changed();
}
}
結果截圖:
中介者模式的注意事項和細節
- 多個類相互耦合,會形成網狀結構, 使用中介者模式將網狀結構分離爲星型結構,進行解耦
- 減少類間依賴,降低了耦合,符合迪米特原則
- 中介者承擔了較多的責任,一旦中介者出現了問題,整個系統就會受到影響
- 如果設計不當,中介者對象本身變得過於複雜,這點在實際使用時,要特別注意
本文參考鏈接:https://blog.csdn.net/lovelion/article/details/8483081
版權聲明:本文爲CSDN博主「LoveLion」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。