中介者模式

在軟體工程領域，中介者模式定義了一箇中介者物件，該物件封裝了系統中物件間的互動方式。 由於它可以在執行時改變程式的行為，這種模式是一種行為型模式 。通常程式由大量的類組成，這些類中包含程式的邏輯和運算。 然而，當開發者將更多的類加入到程式中之後，類間互動關係可能變得更為複雜，這會使得程式碼變得更加難以閱讀和維護，尤其是在重構的時候。 此外，程式將會變得難以修改，因為對其所做的任何修改都有可能影響到其它幾個類中的程式碼。在中介者模式中，物件間的通訊過程被封裝在一箇中介者物件之中。 物件之間不再直接互動，而是透過調解人進行互動。 這麼做可以減少可互動物件間的依賴，從而降低耦合。概述.中介者模式是23個周知模式中的一個，GoF設計模式旨在提供重複出現的設計問題的解決方案，以編寫靈活和可複用的面向物件軟體。也就是說，使物件更加易於實現、修改、測試和複用。中介者設計模式可以解決什麼問題？使用直接逐個訪問並更新彼此的方式進行物件間的互動靈活性低，因為這種方式使物件彼此間緊密耦合，導致不可能單獨修改類間互動關係本身，而不影響關係中進行互動的類。並且這種方式會令物件變得無法複用，並且難以測試。由於"緊耦合的物件"過多瞭解其他物件的內部細節，這種物件難以實現、修改、測試以及複用。中介者模式如何解決上述問題？物件利用中介者物件與其他物件進行間接互動，中介者物件負責控制和協調互動關係，這麼做可使得物件間"松耦合"。這些物件只訪問中介者，不瞭解其他物件的細節。另見UML類圖和時序圖如下。定義.中介者模式是為了“定義一個封裝了物件間互動關係的物件”。這種方式避免了顯式呼叫其他類，促進了類間的松耦合，並且使得類間互動關係本身可以單獨修改。客戶類可以使用中介者向其他客戶類傳送資訊，並且透過中介者引發的事件收到資訊。結構.UML類圖和時序圖.在以上 UML 類圖中，類 codice_1 和 codice_2 不引用和更新彼此。相反，它們引用一個通用的 codice_3 介面以實現類間互動的控制和協調(透過codice_4)，這使得它們獨立於類間互動的具體細節。類 codice_5 實現了類 codice_1 和 codice_2之間的互動細節。上述 UML 時序圖顯示了這些類之間在執行時的互動過程：在這個例子中，一個 codice_5 物件中介，即控制和協調了 codice_1 和 codice_2的物件之間的互動。如果 codice_1 的物件需要與 codice_2 的物件進行互動，例如更新或者同步狀態，codice_1 呼叫codice_5 物件的 codice_15方法，以此得到對 codice_1 物件的改動資訊，並且在 codice_2的物件上執行 codice_18 方法。此後，codice_2 物件呼叫codice_5 物件的 codice_15方法，得到對codice_2 的修改的資料，並且對codice_1 物件呼叫codice_24 方法。類圖.Mediator - 定義 "Colleague" 物件之間的互動介面。ConcreteMediator -實現了"Mediator"介面，並且協調 "Colleague"物件之間的互動，知道所有的 "Colleagues" 物件以及其互動目的。Colleague -定義了透過"Mediator"與其他"Colleague"物件互動的介面。ConcreteColleague -實現了"Colleague"介面，並且透過它的"Mediator"與其他"Colleague"互動。範例.C#.中介者模式確保了構件之間的松耦合，使得它們不直接呼叫彼此，而是透過中介者呼叫彼此。 在下面的例子中，調解人註冊了所有的構件，然後呼叫了它們的SetState方法。public interface IComponentvoid SetState(object state);public class Component1 : IComponentpublic void SetState(object state)throw new NotImplementedException();public class Component2 : IComponentpublic void SetState(object state)throw new NotImplementedException();// Mediates the common taskspublic class Mediatorpublic void ChangeState(object state)this.Component1.SetState(state);this.Component2.SetState(state);一個聊天室，或者一個需要客戶彼此間每次傳送訊息之後執行動作的系統。public delegate void MessageReceivedEventHandler(string message, string from);public class Mediatorpublic event MessageReceivedEventHandler MessageReceived;public void Send(string message, string from)if (MessageReceived != null)Console.WriteLine("Sending '{0}' from {1}", message, from);MessageReceived(message, from);public class Personprivate Mediator _mediator;public Person(Mediator mediator, string name)Name = name;_mediator = mediator;_mediator.MessageReceived += new MessageReceivedEventHandler(Receive);private void Receive(string message, string from)if (from != Name)Console.WriteLine("{0} received '{1}' from {2}", Name, message, from);public void Send(string message)_mediator.Send(message, Name);Java.在以下示例中，一箇中介者物件控制了三個互相互動的按鈕的狀態，為此它有設定狀態的三個方法：codice_25, codice_26 和 codice_27。 當相應的按鈕被啟用時，對應的方法透過codice_28方法被呼叫。於是這裡在互動中每個互動的參與者將自己的行為提交給中介者並且由中介者將這些行為轉給對應的參與者。import java.awt.Font;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JPanel;//Colleague interfaceinterface Command {void execute();//Abstract Mediatorinterface Mediator {void book();void view();void search();void registerView(BtnView v);void registerSearch(BtnSearch s);void registerBook(BtnBook b);void registerDisplay(LblDisplay d);//Concrete mediatorclass 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...");//A concrete colleagueclass 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();//A concrete colleagueclass 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();//A concrete colleagueclass 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));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();