1. 程式人生 > >設計模式 --- 中介者模式

設計模式 --- 中介者模式

1.定義

中介者模式包裝了一系列物件相互作用方式,使得這些物件不必相互明顯作用。從而使他們可以鬆耦合。當某些物件之間作用發生改變的時候,不會立即影響其他的一些物件之間的作用。保證這些作用可以彼此獨立變化。中介者模式將多對多的相互作用轉化為一對多的相互作用。中介者模式將物件的行為和協作抽象化,把物件在小尺度的行為上與其他物件的相互作用分開處理。

 

2.使用場景

當物件之間的互動操作很多且每個物件的行為操作都依賴彼此時,為防止在修改一個物件的行為時,同時涉及修改很多其他物件的行為,可以採用中介者模式來解決緊耦合問題。該模式將物件之間的多對多關係變成一對多關係,中介者物件將系統從網狀結構變成以調停者為中心的星形結構,達到降低系統的複雜性,提高可拓展性的作用。

 

3.簡單實現

以計算機讀取光碟為例。計算機的主機板連線了CPU、記憶體、顯示卡、IO裝置等,任何兩個模組通訊都是通過主機板來協調,這裡的主機板就是相當於中介者的作用。

//抽象同事物件
abstract class Colleague{
    protected  Mediator mediator; //每個同事物件都知道中介者
    public Colleague(Mediator mediator){
        this.mediator = mediator;
    }
}

//CPU 負責將主機板傳過來的音視訊解碼
class CPU extends Colleague{

    private String dataVideo,dataSound; //視訊和音訊資料

    public CPU(Mediator mediator) {
        super(mediator);
    }

    public String getDataVideo() {
        return dataVideo;
    }

    public String getDataSound() {
        return dataSound;
    }

    //資料解碼
    public void decodeData(String data){
        //分割音視訊資料
        String[] tem = data.split(",");
        dataVideo = tem[0];
        dataSound = tem[1];
        //告訴中介者狀態改變
        mediator.change(this);
    }
}

//CD裝置 負責讀取資料
class CDDevice extends Colleague{

    private String data;

    public CDDevice(Mediator mediator) {
        super(mediator);
    }

    //讀取資料
    public String read(){
        return data;
    }

    //載入資料
    public void load(){
        data = "視訊資料data,音訊資料data"; //模擬資料
        //通知中介者
        mediator.change(this);
    }

}

//顯示卡 負責顯示視訊資料
class GraphicsCard extends Colleague{

    public GraphicsCard(Mediator mediator) {
        super(mediator);
    }

    public void showVideo(String data){
        System.out.println("視訊顯示:" + data);
    }
}

//音效卡 負責音訊播放
class SoundCard extends Colleague{

    public SoundCard(Mediator mediator) {
        super(mediator);
    }

    public void palySound(String data){
        System.out.println("音訊播放:" + data);
    }
}

//抽象中介者
abstract class Mediator{
    //同事物件改變時通知中介者方法
    //再由中介者通知其它人
    abstract void change(Colleague colleague);
}

//主機板
class MainBoard extends Mediator{
    private CPU cpu;
    private CDDevice cdDevice;
    private GraphicsCard graphicsCard;
    private SoundCard soundCard;

    @Override
    void change(Colleague colleague) {
        if (colleague == cdDevice){
            //如果是CD裝置讀取了資料
            handleCD((CDDevice)colleague);
        }else if (colleague == cpu){
            //如果CPU處理完資料
            handleCPU((CPU)colleague);
        }
    }

    //處理cd取得資料後與其他裝置的互動
    private void handleCD(CDDevice c){
        //交由CPU解碼
        cpu.decodeData(c.read());
    }

    //處理CPU處理完資料後與其他裝置的互動
    private void handleCPU(CPU cpu){
        //交給顯示卡顯示視訊
        graphicsCard.showVideo(cpu.getDataVideo());
        //交給音效卡播放音訊
        soundCard.palySound(cpu.getDataSound());
    }

    public CPU getCpu() {
        return cpu;
    }

    public void setCpu(CPU cpu) {
        this.cpu = cpu;
    }

    public CDDevice getCdDevice() {
        return cdDevice;
    }

    public void setCdDevice(CDDevice cdDevice) {
        this.cdDevice = cdDevice;
    }

    public GraphicsCard getGraphicsCard() {
        return graphicsCard;
    }

    public void setGraphicsCard(GraphicsCard graphicsCard) {
        this.graphicsCard = graphicsCard;
    }

    public SoundCard getSoundCard() {
        return soundCard;
    }

    public void setSoundCard(SoundCard soundCard) {
        this.soundCard = soundCard;
    }
}

public class MediatorMaode {
    public static void main(String[] args){
        //構建一個主機板
        MainBoard mainBoard = new MainBoard();
        //建立各種裝置
        CPU cpu = new CPU(mainBoard);
        CDDevice cdDevice = new CDDevice(mainBoard);
        GraphicsCard graphicsCard = new GraphicsCard(mainBoard);
        SoundCard soundCard = new SoundCard(mainBoard);

        //設定零件到主機板
        mainBoard.setCdDevice(cdDevice);
        mainBoard.setCpu(cpu);
        mainBoard.setGraphicsCard(graphicsCard);
        mainBoard.setSoundCard(soundCard);

        //播放
        cdDevice.load();
    }
}

輸出:

 

4.小結

如果依賴關係如網狀比較複雜,可以考慮使用中介者模式進行解耦,但是如果幾個類之間的依賴關係並不複雜,使用中介者模式反而會使邏輯結構變得複雜。