1. 程式人生 > 其它 >中介者和觀察者模式

中介者和觀察者模式

中介者和觀察者模式的結合

中介者簡單回顧

中介者模式主要處理的場景就是處理多個類之間的通訊, 為了進行統一的管理. 中介者物件就是作為這個統一管理的物件存在, 在中介聚合了所有需要聯絡的物件

**在中介者中主要的成員主要是: **

  • 抽象的中介者, 這個一看就是核心類, 定義了與其他類進行交流的方法
  • 抽象的聯絡者類, 這個就是互相需要通訊的類咯, 裡面聚合了抽象的中介者(因為需要使用他的抽象聯絡方法)
  • 具體的聯絡者類這個就不用說了吧, 具體的聯絡類物件可以例項化的
  • 具體的中介者結構類, 這裡面就需要定義一個可以統一管理的所有聯絡物件的集合了(這裡假設集合, 能夠統一管理就行,按照自己需求來), 實現具體的交流方法進行管理通訊, 所有的通訊都通過這個方法來進行控制

抽象的中介者

public abstract class Mediator {
    // 抽象的聯絡方法, 通過這個給需要聯絡物件傳送訊息
    public abstract void constact(String message,Person person);
}

抽象的聯絡物件

public abstract class Person {
    protected String name;
    // 聚合了中介者物件
    protected Mediator mediator;

    public Person(String name, Mediator mediator) {
        this.name = name;
        this.mediator = mediator;
    }
}

具體聯絡物件

public class Tenant extends Person {
    public Tenant(String name, Mediator mediator) {
        super(name, mediator);
    }

    //和中介聯絡(溝通)
    public void constact(String message) {
        // 呼叫person中聚合的中介者物件的聯絡方法進行物件之間的通訊
        mediator.constact(message,this);
    }

    //獲取資訊
    public void getMessage(String message) {
        System.out.println("租房者" + name + "獲取到的資訊是:" + message);
    }
}
public class HouseOwner extends Person {

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

    //和中介聯絡(溝通)
    public void constact(String message) {
        mediator.constact(message,this);
    }

    //獲取資訊
    public void getMessage(String message) {
        System.out.println("房主" + name + "獲取到的資訊是:" + message);
    }
}

具體的中介者物件

public class MediatorStructure extends Mediator {
    //聚合房主和租房者物件 (根據你的需求儲存,集合啊,陣列啊,多個集合啊,隨意看著來就行)
    private HouseOwner houseOwner;
    private Tenant tenant;

    public HouseOwner getHouseOwner() {
        return houseOwner;
    }

    public void setHouseOwner(HouseOwner houseOwner) {
        this.houseOwner = houseOwner;
    }

    public Tenant getTenant() {
        return tenant;
    }

    public void setTenant(Tenant tenant) {
        this.tenant = tenant;
    }
	// 具體的物件交流方法
    public void constact(String message, Person person) {
        if(person == houseOwner) {
            tenant.getMessage(message);
        } else {
            houseOwner.getMessage(message);
        }
    }
}

測試

public static void main(String[] args) {
        //建立中介者物件
        MediatorStructure mediator = new MediatorStructure();

        //建立租房者物件
        Tenant tenant = new Tenant("李四",mediator);
        //建立房主物件
        HouseOwner houseOwner = new HouseOwner("張三",mediator);

        //中介者要知道具體的房主和租房者
        mediator.setTenant(tenant);
        mediator.setHouseOwner(houseOwner);

        tenant.constact("我要租三室的房子!!!");
        houseOwner.constact("我這裡有三室的房子,你要租嗎?");
}

觀察者簡單回顧

觀察者模式主要就是訂閱釋出的形式, 觀察的主題事件觸發時,通知訂閱的物件

觀察者也差不多, 主要是一下成員

  • 主題: 需要訂閱的物件, 也就是這個進行事件分發, 提供對觀察者集合的操作
  • 觀察者: 接受主題分發的事件提供一個update方法, 供主題物件進行呼叫(也就是事件觸發, 主題就是呼叫你定義好的update方法)

抽象主題角色類

public interface Subject {
    //新增訂閱者(新增觀察者物件)
    void attach(Observer observer);

    //刪除訂閱者
    void detach(Observer observer);

    //通知訂閱者更新訊息
    void notify(String message);
}

抽象觀察者類

public interface Observer {
	// 用來給主題呼叫的
    void update(String message);
}

具體觀察者類,模擬一個

public class WeiXinUser implements Observer {

    private String name;

    public WeiXinUser(String name) {
        this.name = name;
    }
	// 收到通知時的操作, 就簡單列印一下收到事件的資訊吧
    public void update(String message) {
        System.out.println(name + "-" + message);
    }
}

具體的主題角色類

public class SubscriptionSubject implements Subject {

    //定義一個集合,用來儲存多個觀察者物件
    private List<Observer> weiXinUserList = new ArrayList<Observer>();

    public void attach(Observer observer) {
        weiXinUserList.add(observer);
    }

    public void detach(Observer observer) {
        weiXinUserList.remove(observer);
    }

    public void notify(String message) {
        //遍歷集合
        for (Observer observer : weiXinUserList) {
            //呼叫觀察者物件中的update方法
            observer.update(message);
        }
    }
}

結合

作用: 對專案中複雜依賴的關係管理, 一般是以中介者去管理複雜訂閱關係的模型進行構建

結合上面的中介者和觀察者簡單的例子, 直接就可以看出兩個的關係就是中介者去管理觀察者, 其實結合我也只是按照自己的想法實現,希望看到這篇的朋友能夠給我指出哪些地方需要改進或則有什麼別思路,在此感謝

首先, 直接定義出觀察者的兩個介面: 主題和觀察者

public interface Subject {
    void attach();
    
    void detach();
    
    void notify(String message);
}

public interface Observer {
    void update(String message);
}

可以發現觀察者的話是直接實現觀察者介面就可以了, 但是對於中介者的聯絡物件來說, 他是需要通過聚合物件中介者來進行聯絡通訊的,所以這裡我們需要申明中介者類同時在觀察者物件中聚合此中介者類

public abstract class AbstractUser implements Observer{
    protected String name;
    // 聚合中介者
    protected Mediator mediator;

    public AbstractUser(String name, Mediator mediator) {
        this.name = name;
        this.mediator = mediator;
    }
    
    public abstract void contact(String message);
}

具體實現通訊類, 搞一個qq和一個微信使用者類,好演示

public class QQUser extends AbstractUser {
    public QQUser(String name, Mediator mediator) {
        super(name, mediator);
    }

    @Override
    public void contact(String message) {
        // 中介者只是提供聯絡方式, 這樣你就可以在contact這個具體實現的方法中獲取到是誰傳送了訊息
        // 也可以意味是什麼事件觸發了, 需要通知誰告訴他這個事件觸發了, 這不就是觀察者麼
        mediator.contact(message, this); 
    }

    @Override
    public void update(String message) {
        System.out.println(name + "收到, 使用者更新訊息");
    }
}
public class WeiXinUser extends AbstractUser {
    public WeiXinUser(String name, Mediator mediator) {
        super(name, mediator);
    }

    @Override
    public void contact(String message) {
        mediator.contact(message, this);    
    }

    @Override
    public void update(String message) {
        System.out.println(name + "使用者收到訊息更新的通知");
    }
}

接下來需要修改一上面的主題, 將抽象使用者(聚合了中介者物件)AbstractUser加入方法引數中

public interface Subject {
    void attach(AbstractUser user);
    
    void detach(AbstractUser user);
    // predicateUser 用於控制通知哪些使用者
    void notify(String message, Predicate<AbstractUser> predicateUser);
}

集合了抽象中介者和主題的抽象類MediatorStructure, 在裡面管理了所有的通訊物件, 同時實現主題Subject中的所有方法

public abstract class MediatorStructure extends Mediator implements Subject {
    protected List<AbstractUser> userList = new ArrayList<>();

    @Override
    public void attach(AbstractUser user) {
        userList.add(user);
    }

    @Override
    public void detach(AbstractUser user) {
        userList.remove(user);
    }

    @Override
    public void notify(String message, Predicate<AbstractUser> predicateUser) {
        userList.forEach(it -> {
            if (predicateUser.test(it)) {
                it.update(message);
            }
        });
    }
}

定義最後的中介物件實現, 抽象中介者Mediator的聯絡方法

public class DefaultMediatorStructure extends MediatorStructure{
    // 實現中介者 Mediator 的抽象聯絡方法
    @Override
    public void contact(String message, AbstractUser user) {
        if (user instanceof QQUser) {
            // 如果是訊息來自 qq 使用者, 那就通知所有的微信使用者
            notify(message, WeiXinUser.class::isInstance);
        } else if (user instanceof WeiXinUser) {
            // 同上,如果訊息來自微信使用者則通知所有的qq使用者
            notify(message, QQUser.class::isInstance);
        }
    }
}

測試

public static void main(String[] args) {
    DefaultMediatorStructure mediatorStructure = new DefaultMediatorStructure();

    QQUser qqUser = new QQUser("QQ使用者", mediatorStructure);
    WeiXinUser weixinUser = new WeiXinUser("微信使用者", mediatorStructure);

    mediatorStructure.attach(qqUser);
    mediatorStructure.attach(weixinUser);

    qqUser.contact("唉, 一天又過去了"); // 微信使用者使用者收到訊息更新的通知
    System.out.println("----------------------");
    weixinUser.contact("是啊, 一天過得真快, 今天學到了什麼呀?"); // QQ使用者收到, 使用者更新訊息
    
    
}