Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> java/android 設計模式學習筆記(18)---中介者模式

java/android 設計模式學習筆記(18)---中介者模式

編輯:關於Android編程

這篇博客我們介紹一下中介者模式(Mediator Pattern),也是行為型模式之一,中介者模式也稱為調解者模式或者調停者模式,顧名思義,它的作用是在若干類或者若干模塊之間承當中介。
  通常情況下,一個程序必然要包含大量的類,隨著項目的進行,類和模塊的數量必然要進一步增加,特別是當需要維護或者重構時,類與類之間復雜的網狀結構會讓事情變得越來越復雜,降低程序的可讀性和可維護性,並且修改一個類需要牽涉到其他類,不符合開閉原則。所以此時中介者模式能夠將這些網狀結構的類變成星型依賴,所以類都只依賴於中介者,不直接依賴於其他類。

特點

中介者模式包裝了一系列對象相互作用的方式,使得這些對象不必相互明顯作用,從而使耦合松散,而且可以獨立地改變它們之間的交互。
  中介者模式可以將多對多的網狀結構轉換成一對多的星型結構,達到降低系統的復雜性,提高可擴展性的作用。在沒有中介者角色之前,所有對象都需要依賴其他對象,持有他們的引用,也就是說對象之間是緊耦合的,有了中介者之後,一切就簡單了,每個對象都會在自己狀態改變時,告訴中介者,每個對象都會對中介者發出的請求做出回應。
這裡寫圖片描述這裡寫圖片描述vcrKus+1xLOhvrC+zbrcw/fIt8HLo7q1sbbUz/PWrrzktcS9u7ulstnX97rctuDH0sO/uPa21M/ztcTQ0M6qstnX97a80sDAtbHLtMvKsaOszqq3wNa51NrQ3rjE0ru49rbUz/O1xNDQzqrKsaOszazKscnmvLDQ3rjEuty24Mbky/u21M/ztcTQ0M6qo6y/ybLJ08PW0L3p1d/Eo8q9o6zAtL3ivva99PHuus+1xM7KzOKhozwvcD4NCjxoMSBpZD0="uml類圖">UML類圖

我們來看看中介者模式的 uml 類圖:
這裡寫圖片描述
中介者模式有三個角色:

Mediator:抽象中介者角色,定義了同事對象到中介者對象的接口,可以通過抽象類或者接口的方式實現;ConcreteMediator:具體中介者角色,繼承或者實現了抽象中介者,實現了父類定義的方法,它從具體的同事對象接受消息,向具體同事對象發出命令;Colleague:抽象同事類角色,定義了同事對象的接口,它只知道中介者而不知道其他的同事對象;ConcreteColleague:具體同事類角色,繼承抽象同事類,每個具體同事類都知道本身在小范圍內的行為,而不知道它在大范圍內的目的。  根據上面的類圖我們寫出中介者模式的通用代碼:
抽象同事類:
Colleague.class

 

public abstract class Colleague {

    protected Mediator mediator;

    public void setMediator(Mediator mediator) {
        this.mediator = mediator;
    }

    public abstract void operation();
}

具體同事類:
ConcreteColleagueA.class && ConcreteColleagueB.class

public class ConcreteColleagueA extends Colleague{

    public void notifyColleagueB() {
        mediator.notifyColleagueB();
    }

    @Override
    public void operation() {
        System.out.print("this is ConcreteColleagueA's operation\n");
    }
}
public class ConcreteColleagueB extends Colleague{

    public void notifyColleagueA() {
        mediator.notifyColleagueA();
    }

    @Override
    public void operation() {
        System.out.print("this is ConcreteColleagueB's operation\n");
    }
}

抽象中介者角色:
Mediator.class

public abstract class Mediator {

    protected Colleague colleagueA;
    protected Colleague colleagueB;

    public Mediator(Colleague colleagueA, Colleague colleagueB) {
        this.colleagueA = colleagueA;
        this.colleagueB = colleagueB;
    }

    public abstract void notifyColleagueA();
    public abstract void notifyColleagueB();
}

ConcreteMediator.class

public class ConcreteMediator extends Mediator{

    public ConcreteMediator(Colleague colleagueA, Colleague colleagueB) {
        super(colleagueA, colleagueB);
    }

    @Override
    public void notifyColleagueA() {
        if (colleagueA != null) {
            colleagueA.operation();
        }
    }

    @Override
    public void notifyColleagueB() {
        if (colleagueB != null) {
            colleagueB.operation();
        }
    }
}

測是代碼:

public class Client {
    public static void main(String[] args) {
        Colleague colleagueA = new ConcreteColleagueA();
        Colleague colleagueB = new ConcreteColleagueB();

        Mediator mediator = new ConcreteMediator(colleagueA, colleagueB);
        colleagueA.setMediator(mediator);
        colleagueB.setMediator(mediator);

        ((ConcreteColleagueA)colleagueA).notifyColleagueB();
        ((ConcreteColleagueB)colleagueB).notifyColleagueA();
    }
}

最後結果:

this is ConcreteColleagueB's operation
this is ConcreteColleagueA's operation

兩個 Colleague 類成功通過 Mediator 進行了相互作用。上面這個是中介者模式的標准寫法,就我自己在項目中實際使用中介者模式來說,有時候將同事子類抽象出一個 Colleague 父類是不太合理的,因為子類之間的業務邏輯的不同,導致他們很難抽象出一些公用方法,所以這時候使用中介者模式,可以省去 Colleague 這個角色,讓 Mediator 直接依賴於幾個同事子類;同時也可以不定義Mediator接口,把具體的中介者對象實現成為單例,這樣同事對象不再持有中介者,而是在需要的時候直接獲取中介者對象並調用;中介者也不再持有同事對象,而是在具體處理方法裡面去創建,或獲取,或從數據傳入需要的同事對象。

示例與源碼

在 Android 源碼中也有很多使用中介者模式的例子,比如最突出的就是 Binder 中的 Binder Driver 這個角色,它連接了 Binder client , Binder server 和 ServiceManager,相當於一個中介者,感興趣的可以去看看我的這篇博客android IPC通信(下)-AIDL。
  我這裡仍然以 wiki 的 demo 為例,使用 Mediator 來控制 3 個按鈕實現 book,view 和 search 的功能:
同事類角色:
Command.class

interface Command {
    void execute();
}

BtnView.class、BtnSearch.class、BtnBook.class、LblDisplay.class

class BtnView extends JButton implements Command {

    Mediator med;

    BtnView(ActionListener al, Mediator m) {
        super("View");
        addActionListener(al);
        med = m;
        med.registerView(this);
    }

    public void execute() {
        med.view();
    }

}
class BtnSearch extends JButton implements Command {

    Mediator med;

    BtnSearch(ActionListener al, Mediator m) {
        super("Search");
        addActionListener(al);
        med = m;
        med.registerSearch(this);
    }

    public void execute() {
        med.search();
    }

}
class BtnBook extends JButton implements Command {

    Mediator med;

    BtnBook(ActionListener al, Mediator m) {
        super("Book");
        addActionListener(al);
        med = m;
        med.registerBook(this);
    }

    public void execute() {
        med.book();
    }

}
class LblDisplay extends JLabel {

    Mediator med;

    LblDisplay(Mediator m) {
        super("Just start...");
        med = m;
        med.registerDisplay(this);
        setFont(new Font("Arial", Font.BOLD, 24));
    }

}

中介者角色:
Mediator.class

interface Mediator {
    void book();
    void view();
    void search();
    void registerView(BtnView v);
    void registerSearch(BtnSearch s);
    void registerBook(BtnBook b);
    void registerDisplay(LblDisplay d);
}

ParticipantMediator.class

class ParticipantMediator implements Mediator {

    BtnView btnView;
    BtnSearch btnSearch;
    BtnBook btnBook;
    LblDisplay show;

    //....
    public void registerView(BtnView v) {
        btnView = v;
    }

    public void registerSearch(BtnSearch s) {
        btnSearch = s;
    }

    public void registerBook(BtnBook b) {
        btnBook = b;
    }

    public void registerDisplay(LblDisplay d) {
        show = d;
    }

    public void book() {
        btnBook.setEnabled(false);
        btnView.setEnabled(true);
        btnSearch.setEnabled(true);
        show.setText("booking...");
    }

    public void view() {
        btnView.setEnabled(false);
        btnSearch.setEnabled(true);
        btnBook.setEnabled(true);
        show.setText("viewing...");
    }

    public void search() {
        btnSearch.setEnabled(false);
        btnView.setEnabled(true);
        btnBook.setEnabled(true);
        show.setText("searching...");
    }

}

最後測試程序:

class MediatorDemo extends JFrame implements ActionListener {

    Mediator med = new ParticipantMediator();

    MediatorDemo() {
        JPanel p = new JPanel();
        p.add(new BtnView(this, med));
        p.add(new BtnBook(this, med));
        p.add(new BtnSearch(this, med));
        getContentPane().add(new LblDisplay(med), "North");
        getContentPane().add(p, "South");
        setSize(400, 200);
        setVisible(true);
    }

    public void actionPerformed(ActionEvent ae) {
        Command comd = (Command) ae.getSource();
        comd.execute();
    }

    public static void main(String[] args) {
        new MediatorDemo();
    }

}

用法可能和上面的有些差距,但是思想是一樣的,代碼也一目了然。

總結

在面向對象的變成語言裡,一個類必然會與其他類產生依賴關系,如果這種依賴關系如網狀般錯綜復雜,那麼必然會影響我們的代碼邏輯以及執行效率,適當地使用中介者模式可以對這種依賴關系進行解耦使邏輯結構清晰,但是,如果幾個類之間的關系並不復雜,耦合也很少,使用中介者模式反而會使得原本不復雜的邏輯結構變得復雜,所以,我們在決定使用中介者模式之前需要多多考慮,權衡利弊。
  優點:

適當的使用中介者模式可以避免同事類之間的過度耦合,使得各同事類之間可以相對獨立地使用;使用中介者模式可以將對象間一對多的關聯轉變為一對一的關聯,使對象間的關系易於理解和維護;使用中介者模式可以將對象的行為和協作進行抽象,能夠比較靈活的處理對象間的相互作用。  缺點:使用中介者模式需要權衡一下,不能因為同事類少就不適合使用中介者模式,也不能因為同事類多就一定要使用中介者模式,重要的是解耦合,就算是三個類,他們直接的耦合很嚴密,導致一個類的修改會嚴重影響到另外兩個類,這時候就可以考慮使用中介者,另一方面,類如果很多但是相互都是簡單的連接,耦合性低,使用中介者模式就顯得不是那麼必要了;隨著同事子類的增多和類之間關系的復雜化,中介者會變得越來越龐大,減少可維護性。

 

源碼下載

https://github.com/zhaozepeng/Design-Patterns/tree/master/MediatorPattern

 
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved