中介者模式又叫調停模式,定義如下:用一箇中介者對象封裝一系列的對象的交互,中介者使各個對象不需要顯示的相互作用,從而使其耦合鬆散,而且可以獨立的改變他們之間的交互。
通用類圖如下:
從圖中可以看到,中介者模式由一下幾部分組成:
1.抽象中介者模式Mediator
抽象中介模式定義統一的接口,用於各同事角色之間的通信
2.具體中介者模式ConcreteMediator
具體中介者角色通過協調各個同事角色實現協作行爲,因此它必須依賴於各個同事角色
3.同事角色Colleague
每一個同事角色都知道中介者角色,而且其他的同事角色通信的時候,一定要通過中介角色的協作
說完中介者的通用類圖,下面看看如何應用以及應用中介者模式有哪些好處
現實生活中存在很多的中介者模式,比如和我們自身相關的那就是租房,大家從學校畢業來到社會上工作的第一件事可能就是租房(有房的除外),然後纔是找工作,還有就是機場的調度中心其實也是一箇中介者模式的體現,還有我們做開發現在用的最多一種結構MVC也是中介模式的體現,其中C叫做控制器,V--視圖,M--業務邏輯,前端想要顯示什麼數據首先會詢問C然後又C去詢問M而不是通過V直接詢問M,這樣的設計就是爲了鬆耦合,這也是中介者模式的優點,下面我們以一個實際應用來說明:
一家奔馳的4S店主要設計到的角色有:銷售部門、採購部門、庫存部門
銷售部門:
銷售部門要反饋銷售情況,暢銷就多采購,不暢銷就少採購,同事賣出後要通知庫存部門
庫存部門:
即使是暢銷情況,如果庫存已經超過某個上限也就不需要在採購了
下面是沒有使用中介者模式的類圖
/** * 銷售部門 * */ public class Sale { // 銷售奔馳汽車 public void sellBenz(int carNum) { // 訪問庫存 Stock stock = new Stock(); // 判斷購買量和庫存量 if (stock.getStockNum() < carNum) { // 庫存不夠,通知採購部門進行採購 Purchase purchase = new Purchase(); purchase.buyBenz(carNum); } System.out.println("銷售汽車:" + carNum + "輛"); // 更新庫存 stock.decrease(carNum); } // 打折銷售 public void offSale() { // 訪問庫存 Stock stock = new Stock(); System.out.println("打折處理汽車數量:" + stock.getStockNum()); } // 獲取銷售狀態,用數字0-10來表示,0沒有銷售,10代表非常暢銷 public int getSaleStatus() { Random random = new Random(System.currentTimeMillis()); int saleStatus = random.nextInt(10); System.out.println("汽車的銷售情況:" + saleStatus); return saleStatus; } }
/** * 採購部門 * */ public class Purchase { // 採購奔馳汽車 public void buyBenz(int carNum) { // 詢問銷售部門汽車的銷售情況,如果銷售狀態>8則進行採購,如果是0就暫時不採購,如果處於0--8之間則進行折半採購 Sale sale = new Sale(); if (sale.getSaleStatus() == 0) { System.out.println("銷售情況不好,暫時不採購"); } else if (sale.getSaleStatus() < 8) { int halfNum = carNum / 2; System.out.println("銷售情況不算理想,進行折半採購,採購汽車數量:" + halfNum); // 更新庫存 Stock stock = new Stock(); stock.increase(halfNum); } else { System.out.println("採購汽車:" + carNum + "量"); // 更新庫存 Stock stock = new Stock(); stock.increase(carNum); } } // 不在採購 public void refuseBuyBenz() { System.out.println("不在採購汽車"); } }
/** * 庫存部門 * */ public class Stock { // 庫存中默認100輛奔馳 public static int DEFAULT_NUM = 100; // 庫存汽車容量的上限 public static final int MAX_NUM = 200; // 增加庫存 public void increase(int carNum) { DEFAULT_NUM += carNum; System.out.println("現在庫存量:" + DEFAULT_NUM); } // 減少庫存 public void decrease(int catNum) { DEFAULT_NUM -= catNum; System.out.println("現在庫存剩餘量:" + DEFAULT_NUM); } // 獲取庫存量 public int getStockNum() { return DEFAULT_NUM; } // 清理庫存 public void clearStock() { // 通知銷售 Sale sale = new Sale(); sale.offSale(); // 通知採購 Purchase purchase = new Purchase(); purchase.refuseBuyBenz(); } }
public class Client { public static void main(String[] args) { // 採購人員採購汽車 System.out.println("-----採購汽車------"); Purchase purchase = new Purchase(); purchase.buyBenz(20); // 銷售人員銷售汽車 System.out.println("-----銷售汽車------"); Sale sale = new Sale(); sale.sellBenz(50); // 清理庫存 System.out.println("-----清理庫存-------"); Stock stock = new Stock(); stock.clearStock(); } }
相信大家已經看出這段程序的問題,那就是銷售、採購、庫存之間耦合太緊了,稍微有一個程序需要修改,那麼可能就會導致一片程序的修改,下面看看引入中介者模式之後的效果:
/** * 抽象中介者 * */ public abstract class AbstractMediator { protected Sale sale; protected Purchase purchase; protected Stock stock; public AbstractMediator() { sale = new Sale(this); purchase = new Purchase(this); stock = new Stock(this); } protected abstract void exec(String str, Integer... num); }
/** * * 具體中介者 */ public class Mediator extends AbstractMediator { /** * @param str * @param num */ @Override protected void exec(String str, Integer... num) { if ("buy".equals(str)) { this.buyBenz(num[0]); } if ("sell".equals(str)) { this.sellBenz(num[0]); } if ("offSale".equals(str)) { this.offSale(); } if ("clear".equals(str)) { this.clearStock(); } } // 清理庫存 public void clearStock() { // 通知銷售 super.sale.offSale(); // 通知採購 super.purchase.refuseBuyBenz(); } // 打折銷售 private void offSale() { // 訪問庫存 System.out.println("打折處理汽車數量:" + super.stock.getStockNum()); } // 採購奔馳汽車 private void buyBenz(int carNum) { // 詢問銷售部門汽車的銷售情況,如果銷售狀態>8則進行採購,如果是0就暫時不採購,如果處於0--8之間則進行折半採購 if (super.sale.getSaleStatus() == 0) { System.out.println("銷售情況不好,暫時不採購"); } else if (super.sale.getSaleStatus() < 8) { int halfNum = carNum / 2; System.out.println("銷售情況不算理想,進行折半採購,採購汽車數量:" + halfNum); // 更新庫存 super.stock.increase(halfNum); } else { System.out.println("採購汽車:" + carNum + "量"); // 更新庫存 super.stock.increase(carNum); } } // 銷售奔馳汽車 private void sellBenz(int carNum) { // 訪問庫存 // 判斷購買量和庫存量 if (super.stock.getStockNum() < carNum) { // 庫存不夠,通知採購部門進行採購 super.purchase.buyBenz(carNum); } System.out.println("銷售汽車:" + carNum + "輛"); // 更新庫存 super.stock.decrease(carNum); } }
/** * 抽象同事類 * */ public abstract class AbstractColleague { protected AbstractMediator mediator; public AbstractColleague(AbstractMediator mediator) { this.mediator = mediator; } }
/** * 銷售部門 * */ public class Sale extends AbstractColleague { /** * @param mediator */ public Sale(AbstractMediator mediator) { super(mediator); } // 銷售奔馳汽車 public void sellBenz(int carNum) { super.mediator.exec("sell", 50); } // 打折銷售 public void offSale() { super.mediator.exec("offSale"); } // 獲取銷售狀態,用數字0-10來表示,0沒有銷售,10代表非常暢銷 public int getSaleStatus() { Random random = new Random(System.currentTimeMillis()); int saleStatus = random.nextInt(10); System.out.println("汽車的銷售情況:" + saleStatus); return saleStatus; } }
/** * 庫存部門 * */ public class Stock extends AbstractColleague { /** * @param mediator */ public Stock(AbstractMediator mediator) { super(mediator); // TODO Auto-generated constructor stub } // 庫存中默認100輛奔馳 public static int DEFAULT_NUM = 100; // 庫存汽車容量的上限 public static final int MAX_NUM = 200; // 增加庫存 public void increase(int carNum) { DEFAULT_NUM += carNum; System.out.println("現在庫存量:" + DEFAULT_NUM); } // 減少庫存 public void decrease(int catNum) { DEFAULT_NUM -= catNum; System.out.println("現在庫存剩餘量:" + DEFAULT_NUM); } // 獲取庫存量 public int getStockNum() { return DEFAULT_NUM; } // 清理庫存 public void clearStock() { super.mediator.exec("clear", DEFAULT_NUM); } }
/** * 採購部門 * */ public class Purchase extends AbstractColleague { /** * @param mediator */ public Purchase(AbstractMediator mediator) { super(mediator); } // 採購奔馳汽車 public void buyBenz(int carNum) { super.mediator.exec("buy", 20); } // 不在採購 public void refuseBuyBenz() { System.out.println("不在採購汽車"); } }
public class Client { public static void main(String[] args) { // 創建一箇中介者 AbstractMediator mediator = new Mediator(); // 採購人員採購汽車 System.out.println("-----採購汽車------"); Purchase purchase = new Purchase(mediator); purchase.buyBenz(20); // 銷售人員銷售汽車 System.out.println("-----銷售汽車------"); Sale sale = new Sale(mediator); sale.sellBenz(50); // 清理庫存 System.out.println("-----清理庫存-------"); Stock stock = new Stock(mediator); stock.clearStock(); } }
中介者模式簡單,但是簡單並不代表容易使用,而且有時候很容易被誤用,大家可以嘗試在如下情況使用中介者模式:
1.多個對象之間產生了相互依賴的關係
2.多個對象之間有依賴關係,但是依賴行爲尚不確定或者有發生改變的可能