中介者模式

来源:https://www.cnblogs.com/wangkaihua/archive/2018/07/14/9311153.html
-Advertisement-
Play Games

中介者模式 標簽 : 設計模式 初識中介者模式 定義 用一個中介對象來封裝一系列的對象交互。中介者使得各對象不需要顯式地相互引用,從而使其耦合鬆散,而且可以獨立的改變它們之間的交互。 結構和說明 ![image_1cichf9j215a4eatf87cma7sm9.png 86.7kB][1] Me ...


中介者模式

標簽 : 設計模式


初識中介者模式

定義

用一個中介對象來封裝一系列的對象交互。中介者使得各對象不需要顯式地相互引用,從而使其耦合鬆散,而且可以獨立的改變它們之間的交互。

結構和說明

image_1cichf9j215a4eatf87cma7sm9.png-86.7kB

Mediator:中介者介面。在裡面定義各個同事之間交互需要的方法,可以是公共的通訊方法,比如changed方法,大家都用,也可以是小範圍的交互方法。
ConcreteMediator:具體中介者實現對象。它需要瞭解並維護各個同事對象,並負責具體的協調各同事對象的交互關係。
Colleague:同事類的定義,通常實現成為抽象類,主要負責約束同事對象的類型,並實現一些具體同事類之間的公共功能,比如:每個具體同事類都應該知道中介者對象,也就是具體同事類都會持有中介者對象,就可以定義到這個類裡面。
ConcreteColleague:具體的同事類,實現自己的業務,在需要與其它同事通訊的時候,就與持有的中介者通信,中介者會負責與其它的同事交互。

/**
 * 同事類的抽象父類
 */
public abstract class Colleague {
    /**
     * 持有中介者對象,每一個同事類都知道它的中介者對象
     */
    private Mediator mediator;
    /**
     * 構造方法,傳入中介者對象
     * @param mediator 中介者對象
     */
    public Colleague(Mediator mediator) {
        this.mediator = mediator;
    }
    /**
     * 獲取當前同事類對應的中介者對象
     * @return 對應的中介者對象
     */
    public Mediator getMediator() {
        return mediator;
    }
}


----------
/**
 * 具體的同事類A
 */
public class ConcreteColleagueA extends Colleague {
    public ConcreteColleagueA(Mediator mediator) {
        super(mediator);
    }
    /**
     * 示意方法,執行某些業務功能
     */
    public void someOperation() {
        //在需要跟其他同事通信的時候,通知中介者對象
        getMediator().changed(this);
    }
}


----------
/**
 * 具體的同事類B
 */
public class ConcreteColleagueB extends Colleague {
    public ConcreteColleagueB(Mediator mediator) {
        super(mediator);
    }
    /**
     * 示意方法,執行某些業務功能
     */
    public void someOperation() {
        //在需要跟其他同事通信的時候,通知中介者對象
        getMediator().changed(this);
    }
}


----------
/**
 * 中介者,定義各個同事對象通信的介面
 */
public interface Mediator {
    /**
     * 同事對象在自身改變的時候來通知中介者的方法,
     * 讓中介者去負責相應的與其他同事對象的交互
     * @param colleague 同事對象自身,好讓中介者對象通過對象實例
     *                  去獲取同事對象的狀態
     */
    public void changed(Colleague colleague);
}


----------


/**
 * 具體的中介者實現
 */
public class ConcreteMediator implements Mediator {
    
    /**
     * 持有並維護同事A
     */
    private ConcreteColleagueA colleagueA;
    /**
     * 持有並維護同事B
     */
    private ConcreteColleagueB colleagueB;
    
    /**
     * 設置中介者需要瞭解並維護的同事A對象
     * @param colleague 同事A對象
     */
    public void setConcreteColleagueA(ConcreteColleagueA colleague) {
        colleagueA = colleague;
    }
    /**
     * 設置中介者需要瞭解並維護的同事B對象
     * @param colleague 同事B對象
     */
    public void setConcreteColleagueB(ConcreteColleagueB colleague) {
        colleagueB = colleague;
    }
    
    public void changed(Colleague colleague) {
        //某個同事類發生了變化,通常需要與其他同事交戶
        //具體協調相應的同事對象來實現協作行為
    }

}

體會中介者模式

如果電腦裡面沒有了主板,那麼各個配件之間就必須自行相互交互,以互相傳送數據,理論上說,基本上各個配件相互之間都存在交互數據的可能
image_1cichpuabfrn1m461bn7lkqmpm.png-43kB
有了主板,各個配件的交互完全通過主板來完成,每個配件都只需要和主板交互,而主板知道如何和所有的配件打交道,那就簡單多了
image_1cichqj7g9tcc3h1gbn1vn21j6313.png-10.1kB

存在的問題
如果上面的情況發生在軟體開發上呢?
如果把每個電腦配件都抽象成為一個類或者是子系統,那就相當於出現了多個類之間相互交互,而且交互還很繁瑣,導致每個類都必須知道所有需要交互的類,也就是我們常說的類和類耦合了,是不是很麻煩?
這樣一來,不但開發的時候每個類會複雜,因為要兼顧其它的類,更要命的是每個類在發生改動的時候,需要通知所有相關的類一起修改,因為介面或者是功能發生了變動,使用它的地方都得變,太可怕了吧!
那該如何來簡化這種多個對象之間的交互呢?

使用電腦來看電影
為了演示,考慮一個稍微具體點的功能。在日常生活中,我們經常使用電腦來看電影,把這個過程描述出來,這裡僅僅考慮正常的情況,也就是有主板的情況,簡化後假定會有如下的交互過程:
1:首先是光碟機要讀取光碟上的數據,然後告訴主板,它的狀態改變了
2:主板去得到光碟機的數據,把這些數據交給CPU進行分析處理
3:CPU處理完後,把數據分成了視頻數據和音頻數據,通知主板,它處理完了
4:主板去得到CPU處理過後的數據,分別把數據交給顯卡和音效卡,去顯示出視頻和發出聲音

當然這是一個持續的、不斷重覆的過程,從而形成不間斷的視頻和聲音,具體的運行過程不在討論之列,假設就有如上簡單的交互關係就可以了。也就是說想看電影,把光碟放入光碟機,光碟機開始讀盤,就可以看電影了

使用模式的解決方案
image_1cicht1se18jblc71llg1fckrol1g.png-124.6kB

/**
 * 同事類的抽象父類
 */
public abstract class Colleague {
    /**
     * 持有中介者對象,每一個同事類都知道它的中介者對象
     */
    private Mediator mediator;
    /**
     * 構造方法,傳入中介者對象
     * @param mediator 中介者對象
     */
    public Colleague(Mediator mediator) {
        this.mediator = mediator;
    }
    /**
     * 獲取當前同事類對應的中介者對象
     * @return 對應的中介者對象
     */
    public Mediator getMediator() {
        return mediator;
    }
}


----------
/**
 * CPU類,一個同事類
 */
public class CPU extends Colleague{
    public CPU(Mediator mediator) {
        super(mediator);
    }
    /**
     * 分解出來的視頻數據
     */
    private String videoData = "";
    /**
     * 分解出來的聲音數據
     */
    private String soundData = "";
    /**
     * 獲取分解出來的視頻數據
     * @return 分解出來的視頻數據
     */
    public String getVideoData() {
        return videoData;
    }
    /**
     * 獲取分解出來的聲音數據
     * @return 分解出來的聲音數據
     */
    public String getSoundData() {
        return soundData;
    }
    /**
     * 處理數據,把數據分成音頻和視頻的數據
     * @param data 被處理的數據
     */
    public void executeData(String data){
        //把數據分解開,前面的是視頻數據,後面的是音頻數據
        String [] ss = data.split(",");
        this.videoData = ss[0];
        this.soundData = ss[1];
        //通知主板,CPU的工作完成
        this.getMediator().changed(this);
    }
    
}


----------
/**
 * 光碟機類,一個同事類
 */
public class CDDriver extends Colleague{
    public CDDriver(Mediator mediator) {
        super(mediator);
    }
    /**
     * 光碟機讀取出來的數據
     */
    private String data = "";
    /**
     * 獲取光碟機讀取出來的數據
     * @return 光碟機讀取出來的數據
     */
    public String getData(){
        return this.data;
    }
    /**
     * 讀取光碟
     */
    public void readCD(){
        //逗號前是視頻顯示的數據,逗號後是聲音
        this.data = "設計模式,值得好好研究";
        //通知主板,自己的狀態發生了改變
        this.getMediator().changed(this);
    }
}


----------
/**
 * 音效卡類,一個同事類
 */
public class SoundCard extends Colleague{
    public SoundCard(Mediator mediator) {
        super(mediator);
    }
    
    /**
     * 按照聲頻數據發出聲音
     * @param data 發出聲音的數據
     */
    public void soundData(String data){
        System.out.println("畫外音:"+data);
    }
    
}


----------
/**
 * 顯卡類,一個同事類
 */
public class VideoCard extends Colleague{
    public VideoCard(Mediator mediator) {
        super(mediator);
    }
    
    /**
     * 顯示視頻數據
     * @param data 被顯示的數據
     */
    public void showData(String data){
        System.out.println("您正觀看的是:"+data);
    }
    
}


----------
/**
 * 中介者對象的介面
 */
public interface Mediator {
    /**
     * 同事對象在自身改變的時候來通知中介者的方法,
     * 讓中介者去負責相應的與其他同事對象的交互
     * @param colleague 同事對象自身,好讓中介者對象通過對象實例
     *                  去獲取同事對象的狀態
     */
    public void changed(Colleague colleague);
}


----------
/**
 * 主板類,實現中介者介面
 */
public class MotherBoard implements Mediator{
    /**
     * 需要知道要交互的同事類——光碟機類
     */
    private CDDriver cdDriver = null;
    /**
     * 需要知道要交互的同事類——CPU類
     */
    private CPU cpu = null;
    /**
     * 需要知道要交互的同事類——顯卡類
     */
    private VideoCard videoCard = null;
    /**
     * 需要知道要交互的同事類——音效卡類
     */
    private SoundCard soundCard = null;

    public void setCdDriver(CDDriver cdDriver) {
        this.cdDriver = cdDriver;
    }
    public void setCpu(CPU cpu) {
        this.cpu = cpu;
    }
    public void setVideoCard(VideoCard videoCard) {
        this.videoCard = videoCard;
    }
    public void setSoundCard(SoundCard soundCard) {
        this.soundCard = soundCard;
    }
    
    public void changed(Colleague colleague) {
        if(colleague == cdDriver){
            //表示光碟機讀取數據了
            this.opeCDDriverReadData((CDDriver)colleague);
        }else if(colleague == cpu){
            //表示CPU處理完了
            this.opeCPU((CPU)colleague);
        }
    }
    /**
     * 處理光碟機讀取數據過後與其他對象的交互
     * @param cd 光碟機同事對象
     */
    private void opeCDDriverReadData(CDDriver cd){
        //1:先獲取光碟機讀取的數據
        String data = cd.getData();
        //2:把這些數據傳遞給CPU進行處理
        this.cpu.executeData(data);
    }
    /**
     * 處理CPU處理完數據後與其他對象的交互
     * @param cpu CPU同事類
     */
    private void opeCPU(CPU cpu){
        //1:先獲取CPU處理過後的數據
        String videoData = cpu.getVideoData();
        String soundData = cpu.getSoundData();
        //2:把這些數據傳遞給顯卡和音效卡展示出來
        this.videoCard.showData(videoData);
        this.soundCard.soundData(soundData);
    }
    
}


----------
public class Client {
    public static void main(String[] args) {
        //1:創建中介者——主板對象
        MotherBoard mediator = new MotherBoard();
        //2:創建同事類
        CDDriver cd = new CDDriver(mediator);
        CPU cpu = new CPU(mediator);
        VideoCard vc = new VideoCard(mediator);
        SoundCard sc = new SoundCard(mediator);
        //3:讓中介者知道所有的同事
        mediator.setCdDriver(cd);
        mediator.setCpu(cpu);
        mediator.setVideoCard(vc);
        mediator.setSoundCard(sc);
        
        //4:開始看電影,把光碟放入光碟機,光碟機開始讀盤
        cd.readCD();
    }
}

理解中介者模式

認識中介者模式

1:中介者模式的功能
中介者的功能非常簡單,就是封裝對象之間的交互。如果一個對象的操作會引起其它相關對象的變化,或者是某個操作需要引起其它對象的後續或連帶操作,而這個對象又不希望自己來處理這些關係,那麼就可以找中介者,把所有的麻煩扔給它,只在需要的時候通知中介者,其它的就讓中介者去處理就可以了。
反過來,其它的對象在操作的時候,可能會引起這個對象的變化,也可以這麼做。最後對象之間就完全分離了,誰都不直接跟其它對象交互,那麼相互的關係,全部被集中到中介者對象裡面了,所有的對象就只是跟中介者對象進行通信,相互之間不再有聯繫。
把所有對象之間的交互都封裝在中介者當中,無形中還得到另外一個好處,就是能夠集中的控制這些對象的交互關係,這樣有什麼變化的時候,修改起來就很方便。

2:需要Mediator介面嗎
有沒有使用Mediator介面的必要,取決於是否會提供多個不同的中介者實現。如果中介者實現只有一個的話,而且預計中也沒有需要擴展的要求,那麼就可以不定義Mediator介面,讓各個同事對象直接使用中介者實現對象;如果中介者實現不只一個,或者預計中有擴展的要求,那麼就需要定義Mediator介面,讓各個同事對象來面向中介者介面編程,而無需關心具體的中介者實現。

3:同事關係
在中介者模式中,要求這些類都要繼承相同的類,也就是說,這些對象從某個角度講是同一個類型,算是兄弟對象。
正是這些兄弟對象之間的交互關係很複雜,才產生了把這些交互關係分離出去,單獨做成中介者對象,這樣一來,這些兄弟對象就成了中介者對象眼裡的同事。

4:同事和中介者的關係
中介者對象和同事對象之間是相互依賴的 。

5:如何實現同事和中介者的通信
一種實現方式是在Mediator介面中定義一個特殊的通知介面,作為一個通用的方法,讓各個同事類來調用這個方法 。
另外一種實現方式是可以採用觀察者模式,把Mediator實現成為觀察者,而各個同事類實現成為Subject,這樣同事類發生了改變,會通知Mediator。Mediator在接到通知過後,會與相應的同事對象進行交互。

6:中介者模式的調用順序示意圖
image_1cicidgia18d21tkikd1n849hd1t.png-31.4kB

廣義中介者示例——部門與人員

1:部門和人員的關係 : 是 多對多的
2:問題的出現
想想部門和人員的功能交互,舉幾個常見的功能:
(1)部門被撤銷
(2)部門之間進行合併
(3)人員離職
(4)人員從一個部門調職到另外一個部門

想想要實現這些功能,按照前面的設計,該怎麼做呢?
(1)系統運行期間,部門被撤銷了,就意味著這個部門不存在了,可是原來這個部門下所有的人員,每個人員的所屬部門中都有這個部門呢,那麼就需要先通知所有的人員,把這個部門從它們的所屬部門中去掉,然後才可以清除這個部門。
(2)部門合併,是合併成一個新的部門呢,還是把一個部門併入到另一個部門?如果是合併成一個新的部門,那麼需要把原有的兩個部門撤銷,然後再新增一個部門;如果是把一個部門合併到另一個部門裡面,那就是撤銷掉一個部門,然後把這個部門下的人員移動到這個部門。不管是那種情況,都面臨著需要通知相應的人員進行更改這樣的問題。
(3)人員離職了,反過來就需要通知他所屬於的部門,從部門的擁有人員的記錄中去除掉這個人員。
(4)人員調職,同樣需要通知相關的部門,先從原來的部門中去除掉,然後再到新的部門中添加上。

看了上述的描述,感覺如何?
麻煩的根源在什麼地方呢?仔細想想,對了,麻煩的根源就在於部門和人員之間的耦合,這樣導致操作人員的時候,需要操作所有相關的部門,而操作部門的時候又需要操作所有相關的人員,使得部門和人員攪和在了一起。

3:中介者來解決
找到了根源就好辦了,採用中介者模式,引入一個中介者對象來管理部門和人員之間的關係,就能解決這些問題了。
如果採用標準的中介者模式,想想上面提出的那些問題點吧,就知道實現起來會很彆扭。因此採用廣義的中介者來解決,這樣部門和人員就完全解耦了,也就是說部門不知道人員,人員也不知道部門,它們完全分開,它們之間的關係就完全由中介者對象來管理了。

/**
 *  描述部門和人員關係的類
 */
public class DepUserModel {
    /**
     * 用於部門和人員關係的編號,用做主鍵
     */
    private String depUserId;
    /**
     * 部門的編號
     */
    private String depId;
    /**
     * 人員的編號
     */
    private String userId;
    public String getDepUserId() {
        return depUserId;
    }
    public void setDepUserId(String depUserId) {
        this.depUserId = depUserId;
    }
    public String getDepId() {
        return depId;
    }
    public void setDepId(String depId) {
        this.depId = depId;
    }
    public String getUserId() {
        return userId;
    }
    public void setUserId(String userId) {
        this.userId = userId;
    }
}


----------
/**
 * 部門類
 */
public class Dep{
    /**
     * 描述部門編號
     */
    private String depId;
    /**
     * 描述部門名稱
     */
    private String depName;
    public String getDepId() {
        return depId;
    }
    public void setDepId(String depId) {
        this.depId = depId;
    }
    public String getDepName() {
        return depName;
    }
    public void setDepName(String depName) {
        this.depName = depName;
    }
    /**
     * 撤銷部門
     * @return 是否撤銷成功
     */
    public boolean deleteDep(){
        //1:要先通過中介者去清除掉所有與這個部門相關的部門和人員的關係
        DepUserMediatorImpl mediator = DepUserMediatorImpl.getInstance();
        mediator.deleteDep(depId);
        //2:然後才能真的清除掉這個部門
        //請註意在實際開發中,這些業務功能可能會做到業務層去,
        //而且實際開發中對於已經使用的業務數據通常是不會被刪除的,
        //而是會被做為歷史數據保留
        return true;
    }
}


----------
    /**
     * 人員名稱
     */
    private String userName;
    public String getUserId() {
        return userId;
    }
    public void setUserId(String userId) {
        this.userId = userId;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    /**
     * 人員離職
     * @return 是否處理成功
     */
    public boolean dimission(){
        //1:要先通過中介者去清除掉所有與這個人員相關的部門和人員的關係
        DepUserMediatorImpl mediator = DepUserMediatorImpl.getInstance();
        mediator.deleteUser(userId);
        //2:然後才能真的清除掉這個人員
        //請註意,實際開發中,人員離職,是不會真的刪除人員記錄的,
        //通常是把人員記錄的狀態或者是刪除標記設置成已刪除,
        //只是不再參加新的業務,但是已經發生的業務記錄是不會被清除掉的
        
        return true;
    }
}


----------
/**
 * 實現部門和人員交互的中介者實現類
 * 說明:為了演示的簡潔性,只示例實現撤銷部門和人員離職的功能
 */
public class DepUserMediatorImpl{
    private static DepUserMediatorImpl mediator = new DepUserMediatorImpl();
    private DepUserMediatorImpl(){
        //調用初始化測試數據的功能
        initTestData();
    }
    public static DepUserMediatorImpl getInstance(){
        return mediator;
    }
    
    /**
     * 測試用,記錄部門和人員的關係
     */
    private Collection<DepUserModel> depUserCol = new ArrayList<DepUserModel>();
    /**
     * 初始化測試數據
     */
    private void initTestData(){
        //準備一些測試數據
        DepUserModel du1 = new DepUserModel();
        du1.setDepUserId("du1");
        du1.setDepId("d1");
        du1.setUserId("u1");        
        depUserCol.add(du1);
        
        DepUserModel du2 = new DepUserModel();
        du2.setDepUserId("du2");
        du2.setDepId("d1");
        du2.setUserId("u2");        
        depUserCol.add(du2);
        
        DepUserModel du3 = new DepUserModel();
        du3.setDepUserId("du3");
        du3.setDepId("d2");
        du3.setUserId("u3");        
        depUserCol.add(du3);
        
        DepUserModel du4 = new DepUserModel();
        du4.setDepUserId("du4");
        du4.setDepId("d2");
        du4.setUserId("u4");        
        depUserCol.add(du4);
        
        DepUserModel du5 = new DepUserModel();
        du5.setDepUserId("du5");
        du5.setDepId("d2");
        du5.setUserId("u1");        
        depUserCol.add(du5);
    }
    /**
     * 完成因撤銷部門的操作所引起的與人員的交互,需要去除相應的關係
     * @param depId 被撤銷的部門對象的編號
     * @return 是否已經正確的處理了因撤銷部門所引起的與人員的交互
     */
    public boolean deleteDep(String depId) {
        //請註意:為了演示簡單,部門撤銷後,原部門的人員怎麼處理等後續業務處理,這裡就不管了
        
        //1:到記錄部門和人員關係的集合裡面,尋找跟這個部門相關的人員
        //設置一個臨時的集合,記錄需要清除的關係對象
        Collection<DepUserModel> tempCol = new ArrayList<DepUserModel>();
        for(DepUserModel du : depUserCol){
            if(du.getDepId().equals(depId)){
                //2:需要把這個相關的記錄去掉,先記錄下來
                tempCol.add(du);
            }
        }
        //3:從關係集合裡面清除掉這些關係
        depUserCol.removeAll(tempCol);
        
        return true;
    }
    /**
     * 完成因人員離職引起的與部門的交互
     * @param userId 離職的人員的編號
     * @return 是否正確處理了因人員離職引起的與部門的交互
     */
    public boolean deleteUser(String userId) {
        //1:到記錄部門和人員關係的集合裡面,尋找跟這個人員相關的部門
        //設置一個臨時的集合,記錄需要清除的關係對象
        Collection<DepUserModel> tempCol = new ArrayList<DepUserModel>();
        for(DepUserModel du : depUserCol){
            if(du.getUserId().equals(userId)){
                //2:需要把這個相關的記錄去掉,先記錄下來
                tempCol.add(du);
            }
        }
        //3:從關係集合裡面清除掉這些關係
        depUserCol.removeAll(tempCol);
    
        return true;
    }
    /**
     * 測試用,在內部列印顯示一下一個部門下的所有人員
     * @param dep 部門對象
     */
    public void showDepUsers(Dep dep) {
        for(DepUserModel du : depUserCol){
            if(du.getDepId().equals(dep.getDepId())){
                System.out.println("部門編號="+dep.getDepId()+"下麵擁有人員,其編號是:"+du.getUserId());
            }
        }
    }
    /**
     * 測試用,在內部列印顯示一下一個人員所屬的部門
     * @param user 人員對象
     */
    public void showUserDeps(User user) {
        for(DepUserModel du : depUserCol){
            if(du.getUserId().equals(user.getUserId())){
                System.out.println("人員編號="+user.getUserId()+"屬於部門編號是:"+du.getDepId());
            }
        }
    }
    /**
     * 完成因人員調換部門引起的與部門的交互
     * @param userId 被調換的人員的編號
     * @param oldDepId 調換前的部門的編號
     * @param newDepId 調換後的部門的編號
     * @return 是否正確處理了因人員調換部門引起的與部門的交互
     */
    public boolean changeDep(String userId,String oldDepId, String newDepId) {
        //本示例不去實現了
        return false;
    }
    

    /**
     * 完成因部門合併操作所引起的與人員的交互
     * @param colDepIds 需要合併的部門的編號集合
     * @param newDep 合併後新的部門對象
     * @return 是否正確處理了因部門合併操作所引起的與人員的交互
     */
    public boolean joinDep(Collection<String> colDepIds, Dep newDep) {
        //本示例不去實現了      
        return false;
    }
}


----------
public class Client {
    public static void main(String[] args) {
        DepUserMediatorImpl mediator = DepUserMediatorImpl.getInstance();
        //準備要撤銷的部門,僅僅需要一個部門編號
        Dep dep = new Dep();
        dep.setDepId("d1");
        Dep dep2 = new Dep();
        dep2.setDepId("d2");
        //準備用於測試的人員,也只需要一個人員編號
        User user = new User();
        user.setUserId("u1");
        
        //測試撤銷部門,在運行之前,輸出一下,看這個人員屬於哪些部門     
        System.out.println("撤銷部門前------------------");
        mediator.showUserDeps(user);
        
        //真正執行業務,撤銷這個部門
        dep.deleteDep();
        
        //再次輸出一下,看這個人員屬於哪些部門
        System.out.println("撤銷部門後------------------");
        mediator.showUserDeps(user);
        
        //測試人員離職,在運行之前,輸出一下,看這個部門下都有哪些人員
        System.out.println("---------------------------------");
        System.out.println("人員離職前------------------");
        mediator.showDepUsers(dep2);
        
        //真正執行業務,人員離職
        user.dimission();
        
        //再次輸出一下,看這個部門下都有哪些人員
        System.out.println("人員離職後------------------");
        mediator.showDepUsers(dep2);
    }
}

中介者模式的優缺點

1:鬆散耦合
2:集中控制交互
3:多對多變成一對多
4:過度集中化

思考中介者模式

中介者模式的本質

封裝交互

何時選用中介者模式

1:如果一組對象之間的通信方式比較複雜,導致相互依賴、結構混亂,可以採用中介者模式,把這些對象相互的交互管理起來,各個對象都只需要和中介者交互,從而使得各個對象鬆散耦合,結構也更清晰易懂
2:如果一個對象引用很多的對象,並直接跟這些對象交互,導致難以復用該對象。可以採用中介者模式,把這個對象跟其它對象的交互封裝到中介者對象裡面,這個對象就只需要和中介者對象交互就可以了


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 我當時就想咋回事呢 明明函數是定義在Animation裡面的 方法也是由它調用的 所以this應該指向的是Animation呀 於是乎我就繼續往下看 看打了 奧,明白了 setTimeout 和 setInterval 一般都是這麼寫 timer=setTimeout(function(){},10 ...
  • 我們在學習es6的時候會遇到一個神奇的語法 一個括弧和一個箭頭就可以實現一個函數,有時遇到參數時只傳參數就行甚至都不用寫括弧,看似簡單其實跟我們在es5中的函數是一樣的有時會改變我們this的指向。下麵我們來看一下箭頭函數我們先來按常規語法定義函數: 該函數使用箭頭函數可以使用僅僅一行代碼搞定! 是 ...
  • 聖杯模式是Javascript中用來實現繼承的一種方法,它的簡單形式如下所示 這種聖杯模式的本質在於,中間生成了一個對象,起到了隔離的作用,今後為Son.prototype添加屬性時,全部都會加在這個對象裡面,所以不會對父級產生影響。 而向上查找是沿著__proto__查找,可以順利查找到父級的屬性 ...
  • 宿主對象即瀏覽器提供的對象,主要包括DOM對象和BOM對象。 一、DOM源起 1.SGML、XML和XHTML SGML(標準通用標記語言)是定義使用標簽來表示數據的標記語言的語法。 - 標簽由一個小於號和一個大於號之間的文本組成,如<title> - 標簽分為起始標簽和結束標簽,分別表示一個特定區 ...
  • 一、跨站腳本攻擊(XSS) 跨站腳本攻擊是指通過存在安全漏洞的Web網站註冊用戶的瀏覽器運行非法的HTML標簽或JavaScript進行的一種攻擊。動態創建的HTML部分有可能隱藏著安全漏洞。就這樣,當攻擊者編寫腳本,設下陷阱,用戶在自己的瀏覽器上運行時,一不小心就會受到被動攻擊。 跨站腳本攻擊有可 ...
  • 公司這幾天項目很緊張,然後一直有各種亂七八糟的事,突然說要整個搜索的功能,第一時間想到的就是用php的模糊搜索,但是性能耗的很大,並且調取出的數據的速度賊慢,在百度上找到一個通過js來搜索的功能分享給大家。 這個是頁面 出來後的效果: 頁面代碼: js代碼 php只做了輸出數據所以在這裡就不放出來了 ...
  • Web Worker SharedWorker Service Worker ...
  • 1.DOM簡介 當網頁被載入時,瀏覽器會創建頁面的文檔對象模型,即DOM(Document Object Model)。 2.DOM操作HTML 2.1 改變HTML輸出流 不要在文檔載入完成之後使用document.write()。會覆蓋該文檔 2.2 尋找元素 通過id找到HTML元素 通過標簽 ...
一周排行
    -Advertisement-
    Play Games
  • Timer是什麼 Timer 是一種用於創建定期粒度行為的機制。 與標準的 .NET System.Threading.Timer 類相似,Orleans 的 Timer 允許在一段時間後執行特定的操作,或者在特定的時間間隔內重覆執行操作。 它在分散式系統中具有重要作用,特別是在處理需要周期性執行的 ...
  • 前言 相信很多做WPF開發的小伙伴都遇到過表格類的需求,雖然現有的Grid控制項也能實現,但是使用起來的體驗感並不好,比如要實現一個Excel中的表格效果,估計你能想到的第一個方法就是套Border控制項,用這種方法你需要控制每個Border的邊框,並且在一堆Bordr中找到Grid.Row,Grid. ...
  • .NET C#程式啟動閃退,目錄導致的問題 這是第2次踩這個坑了,很小的編程細節,容易忽略,所以寫個博客,分享給大家。 1.第一次坑:是windows 系統把程式運行成服務,找不到配置文件,原因是以服務運行它的工作目錄是在C:\Windows\System32 2.本次坑:WPF桌面程式通過註冊表設 ...
  • 在分散式系統中,數據的持久化是至關重要的一環。 Orleans 7 引入了強大的持久化功能,使得在分散式環境下管理數據變得更加輕鬆和可靠。 本文將介紹什麼是 Orleans 7 的持久化,如何設置它以及相應的代碼示例。 什麼是 Orleans 7 的持久化? Orleans 7 的持久化是指將 Or ...
  • 前言 .NET Feature Management 是一個用於管理應用程式功能的庫,它可以幫助開發人員在應用程式中輕鬆地添加、移除和管理功能。使用 Feature Management,開發人員可以根據不同用戶、環境或其他條件來動態地控制應用程式中的功能。這使得開發人員可以更靈活地管理應用程式的功 ...
  • 在 WPF 應用程式中,拖放操作是實現用戶交互的重要組成部分。通過拖放操作,用戶可以輕鬆地將數據從一個位置移動到另一個位置,或者將控制項從一個容器移動到另一個容器。然而,WPF 中預設的拖放操作可能並不是那麼好用。為瞭解決這個問題,我們可以自定義一個 Panel 來實現更簡單的拖拽操作。 自定義 Pa ...
  • 在實際使用中,由於涉及到不同編程語言之間互相調用,導致C++ 中的OpenCV與C#中的OpenCvSharp 圖像數據在不同編程語言之間難以有效傳遞。在本文中我們將結合OpenCvSharp源碼實現原理,探究兩種數據之間的通信方式。 ...
  • 一、前言 這是一篇搭建許可權管理系統的系列文章。 隨著網路的發展,信息安全對應任何企業來說都越發的重要,而本系列文章將和大家一起一步一步搭建一個全新的許可權管理系統。 說明:由於搭建一個全新的項目過於繁瑣,所有作者將挑選核心代碼和核心思路進行分享。 二、技術選擇 三、開始設計 1、自主搭建vue前端和. ...
  • Csharper中的表達式樹 這節課來瞭解一下表示式樹是什麼? 在C#中,表達式樹是一種數據結構,它可以表示一些代碼塊,如Lambda表達式或查詢表達式。表達式樹使你能夠查看和操作數據,就像你可以查看和操作代碼一樣。它們通常用於創建動態查詢和解析表達式。 一、認識表達式樹 為什麼要這樣說?它和委托有 ...
  • 在使用Django等框架來操作MySQL時,實際上底層還是通過Python來操作的,首先需要安裝一個驅動程式,在Python3中,驅動程式有多種選擇,比如有pymysql以及mysqlclient等。使用pip命令安裝mysqlclient失敗應如何解決? 安裝的python版本說明 機器同時安裝了 ...