1. 程式人生 > >折騰Java設計模式之中介者模式

折騰Java設計模式之中介者模式

ani 不同類 cte 要去 裏的 hashmap ESS 一個 java設計模式

博文原址:折騰Java設計模式之中介者模式

中介者模式

中介者模式(Mediator Pattern)是用來降低多個對象和類之間的通信復雜性。這種模式提供了一個中介類,該類通常處理不同類之間的通信,並支持松耦合,使代碼易於維護。中介者模式屬於行為型模式。

通俗點來講就是提供一個中介平臺,說到平臺,那其實很容易聯系到我們很熟悉的房地產中介。我們可以直接通過這個平臺得到我們想要的信息,不用對象自身與其他對象交互。

買房子租房子就不需要去找房東,只需要在中介那裏獲取相應的×××信息。如下圖那樣,兩方只需要找中介即可。

技術分享圖片

再來看一張對比圖。

技術分享圖片

有沒有感覺沒有使用之前,對象間互相依賴互相調用,錯綜復雜,盤根錯節,當加入中介者後,對象間的關系一目了然,清晰明了。由中介對象來封裝一系列對象之間的交互關系。中介者使各個對象之間不需要顯式地相互引用,從而使耦合性降低,而且可以獨立地改變它們之間的交互行為。

中介者模式UML圖

UML類圖和時序圖

技術分享圖片

collague1和collague2類不直接相互依賴,它們是用起控制和協調交互作用的公共中介接口(mediate()方法),這使它們有獨立交互的執行方式。mediate1類實現collague1和collague2之間的依賴。

中介者模式角色

技術分享圖片

抽象中介者(Mediator): 定義了同事對象到中介者對象之間的接口。

具體中介者(ConcreteMediator): 實現抽象中介者的方法,它需要知道所有的具體同事類,同時需要從具體的同事類那裏接收信息,並且向具體的同事類發送信息。

抽象同事類(Colleague): 定義了中介者對象的接口,它只知道中介者而不知道其他的同事對象。

具體同事類(ConcreteColleague) : 每個具體同事類都只需要知道自己的行為即可,但是他們都需要認識中介者。

示例代碼

源碼地址

抽象中介者

@Slf4j
public abstract class Mediator {

    /**
     * 房東map
     */
    protected Map<People, Message> landlordMap = Maps.newHashMap();

    /**
     * 租戶列表
     */
    protected List<People> renterList = Lists.newArrayList();

    /**
     * 註冊房東信息
     *
     * @param landlord 房東
     * @param message  房屋信息
     */
    public void registerLandlord(People landlord, Message message) {
        landlordMap.put(landlord, message);
        log.info("中介信息:房東|{}|加入到中介平臺,房屋信息:{}", landlord.getName(), message);
    }

    /**
     * 變更房東信息
     *
     * @param landlord 房東
     * @param message  房屋信息
     */
    protected void modifyLandlordInfo(People landlord, Message message) {
        landlordMap.put(landlord, message);
        log.info("中介信息:房東|{}|修改他在中介平臺的房屋信息,現房屋信息:{}", landlord.getName(), message);
    }

    /**
     * 註冊租戶信息
     *
     * @param renter 租戶
     */
    public void registerRenter(People renter) {
        renterList.add(renter);
        log.info("中介信息:租戶|{}|來中介平臺租房", renter.getName());
    }

    /**
     * 聲明抽象方法 由具體中介者子類實現 消息的中轉和協調
     */
    public abstract void operation(People people, Message message);

}

抽象同事類

@Data
@AllArgsConstructor
@NoArgsConstructor
public abstract class People {

    private Mediator mediator;

    private String name;

    /**
     * 向中介發送消息
     */
    protected abstract void sendMessage(Message message);

    /**
     * 從中介獲取消息
     */
    protected abstract void getMessage(Message message);
}

具體同事類 房東和租戶

@Slf4j
public class Landlord extends People {

    public Landlord(Mediator mediator, String name) {
        super(mediator, name);
    }

    @Override
    protected void sendMessage(Message message) {
        getMediator().operation(this, message);
    }

    @Override
    protected void getMessage(Message message) {
        log.info("房東|{}|從中介獲取到租戶的信息:{}", getName(), message);
    }
}
@Slf4j
public class Renter extends People {

    public Renter(Mediator mediator, String name) {
        super(mediator, name);
    }

    @Override
    protected void sendMessage(Message message) {
        getMediator().operation(this, message);
    }

    @Override
    protected void getMessage(Message message) {
        log.info("租戶|{}|從中介獲取到房東的信息:{}", getName(), message);
    }
}

具體中介者

public class RealEstateAgent extends Mediator {

    @Override
    public void operation(People people, Message message) {
        if (people instanceof Renter) {
            // 將租戶的租房條件信息發送給房東們
            landlordMap.keySet().forEach(landlord -> landlord.getMessage(message));

            // 租戶收到中介那裏房東的房屋信息
            landlordMap.values().forEach(messages -> people.getMessage(messages));
        } else if (people instanceof Landlord) {
            // 將房東的房屋信息發送給租戶們
            renterList.forEach(renter -> renter.getMessage(message));
            // 變更中介裏的房東房屋信息
            modifyLandlordInfo(people, message);
        }
    }
}

客戶端

@Slf4j
public class Client {

    public static void main(String[] args) {
        Mediator mediator = new RealEstateAgent();
        People laoWang = new Landlord(mediator, "老王");
        People laoLee = new Landlord(mediator, "老李");
        People laoBai = new Landlord(mediator, "老白");

        People xiaoSan = new Renter(mediator, "小3");
        People xiaoWang = new Renter(mediator, "小王");

        mediator.registerLandlord(laoWang, Message.builder().msg("我這有2500的房子,市中心").build());
        mediator.registerLandlord(laoBai, Message.builder().msg("我這有2000的房子,地鐵旁").build());
        mediator.registerLandlord(laoLee, Message.builder().msg("我這有2000的房子,落地陽臺,大空間,采光好,地鐵旁").build());

        mediator.registerRenter(xiaoSan);

        log.info("小3開始找房子");
        xiaoSan.sendMessage(Message.builder().msg("想找個月租2000塊的房子,靠近地鐵").build());
        log.info("沒過多久---------老白升級了房屋信息");
        laoBai.sendMessage(Message.builder().msg("我這有2000的房子,地鐵旁,我又加了空調和熱水器").build());
        mediator.registerRenter(xiaoWang);
        log.info("小王開始找房子");
        xiaoWang.sendMessage(Message.builder().msg("想找個月租2500塊的房子,靠近地鐵").build());
        log.info("沒過多久---------老李也升級了房屋信息");
        laoBai.sendMessage(Message.builder().msg("我這有2000的房子,落地陽臺,大空間,采光好,地鐵旁,我也加了空調和熱水器").build());

    }
}

最終出效果的如下

技術分享圖片

現在我來分析下裏面各個角色的作用:

首先先分析兩個抽象類。抽象同事類,含有名稱和中介者的引用,有2個方法從中介拿信息和發信息給中介。抽象中介者,其中含有房東的map信息,key為房東數據,value為房東的房屋信息,用來房東註冊和房東房屋信息變更;租戶的列表信息,供租戶註冊,同時還有個協調方法,用於協調房東和租戶。

具體抽象類(房地產中介),實現了抽象中介者的協調方法,當租戶發送消息時,將租戶的租房條件信息發送給所有房東們同時該租戶收到中介那裏所有房東的房屋信息;當房東發送消息時,將房東的房屋信息發送給所有租戶們同時變更中介裏的改房東房屋信息。

具體同事實現類(房東和租戶),實現了抽象同事類的讀取消息方法和發送消息方法(該房屋就是依靠中介者的協調方法來實現)。

JDK中的應用

通過使用一個中間對象來進行消息分發以及減少類之間的直接依賴。

java.util.Timer

java.util.concurrent.Executor#execute()

java.util.concurrent.ExecutorService#submit()

java.lang.reflect.Method#invoke()

總結

優點

使用中介者模式可以把對個同事對象之間的交互封裝到中介者對象裏面,從而使得同事對象之間松散耦合。
中介者模式可以將原先多對多的同事對象關系變成中介者對象一對多同事對象的關系,這樣會讓對象之間的關系更容易理解和實現。
同事對象之間的交互都被封裝到中介者對象裏面集中管理,集中了控制交互。當交互發生改變時,著重修改的是中介者對象。當需要擴展中介者對象時,其他同事對象不需要做修改。

缺點

如果同事對象多了,交互也復雜了。中介者會龐大,變得復雜難以維護。

參考

中介者模式|菜鳥教程

Mediator pattern

細數JDK裏的設計模式

JAVA設計模式之 中介者模式【Mediator Pattern】

歡迎關註

技術分享圖片

折騰Java設計模式之中介者模式