資料結構與演算法_15 _ 二分查詢(上):如何用最省記憶體的方式實現快速查詢功能
阿新 • • 發佈:2021-08-12
前言
我們現實生活中存在很多複雜的 網狀結構 的互動關係,例如每個人必須記錄他(她)所有朋友的手機號,如果其中有人的手機號修改了,就必須通知他(她)所有的朋友一起修改,牽一髮而動全身,非常複雜,如果將這種 網狀結構 變成 星狀結構,將大大降低它們之間的耦合度,新增一箇中介者,在網上建立一個每個朋友都可以訪問的通訊錄,如QQ,我們修改了個人資訊,其他人自然就看到了。
定義
用一箇中介物件來封裝一系列的物件互動,中介者使得各物件不需要顯式的相互引用,從而使其耦合鬆散,而且可以獨立的改變它們之間的互動。
結構
- Colleague,抽象同事類,每個同事類都知道中介者物件。
- ConcreteColleague,具體同事類,通過中介者來和其他的同事類互動。
- Mediator,中介者介面,定義各個同事之間需要互動的方法。
- ConcreteMediator,具體中介者,瞭解並維護各個同事物件,協調各同事之間的互動關係。
簡單實現
抽象同事類
/** * 抽象同事類 */ public abstract class Colleague { private Mediator mediator; public Colleague(Mediator mediator) { this.mediator = mediator; } 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() { System.out.println("ConcreteColleagueB.someOperation"); } }
中介者介面
/**
* 中介者介面
*/
public interface Mediator {
void changed(Colleague colleague);
}
具體中介者
/**
* 具體中介者
*/
public class ConcreteMediator implements Mediator {
private ConcreteColleagueA concreteColleagueA;
private ConcreteColleagueB concreteColleagueB;
public void setConcreteColleagueA(
ConcreteColleagueA concreteColleagueA) {
this.concreteColleagueA = concreteColleagueA;
}
public void setConcreteColleagueB(
ConcreteColleagueB concreteColleagueB) {
this.concreteColleagueB = concreteColleagueB;
}
@Override
public void changed(Colleague colleague) {
if (colleague == concreteColleagueA) {
concreteColleagueB.someOperation();
}
}
}
客戶端
public class Client {
public static void main(String[] args) {
//中介者
ConcreteMediator mediator = new ConcreteMediator();
//兩個同事物件
ConcreteColleagueA colleagueA = new ConcreteColleagueA(mediator);
ConcreteColleagueB colleagueB = new ConcreteColleagueB(mediator);
mediator.setConcreteColleagueA(colleagueA);
mediator.setConcreteColleagueB(colleagueB);
//同事操作
colleagueA.someOperation();
}
}
在實際開發中,我們可以簡化中介者模式,去除中介者介面,直接將中介者實現為一個單例,這樣同事物件中就不需要持有中介者物件了。同事類也不需要有一個共同的抽象父類,任意的物件都可以成為同事。這種實現可以看做廣義的中介者模式。
/**
* 具體中介者,單例實現
*/
public class ConcreteMediator {
private static final ConcreteMediator INSTANCE = new ConcreteMediator();
private ConcreteMediator() {
}
public static ConcreteMediator getInstance() {
return INSTANCE;
}
public void colleagueBOperation() {
new ConcreteColleagueB().someOperation();
}
}
兩個具體同事類
/**
* 具體同事類A
*/
public class ConcreteColleagueA {
public void someOperation() {
ConcreteMediator.getInstance().colleagueBOperation();
}
}
/**
* 具體同事類B
*/
public class ConcreteColleagueB {
public void someOperation() {
System.out.println("ConcreteColleagueB.someOperation");
}
}
客戶端
public class Client {
public static void main(String[] args) {
new ConcreteColleagueA().someOperation();
}
}
中介者模式在SpringMVC的實現
SpringMVC中的DispatcherServlet
public class DispatcherServlet extends FrameworkServlet {
/** List of HandlerMappings used by this servlet. */
@Nullable
private List<HandlerMapping> handlerMappings;
/** List of HandlerAdapters used by this servlet. */
@Nullable
private List<HandlerAdapter> handlerAdapters;
/** List of HandlerExceptionResolvers used by this servlet. */
@Nullable
private List<HandlerExceptionResolver> handlerExceptionResolvers;
/** List of ViewResolvers used by this servlet. */
@Nullable
private List<ViewResolver> viewResolvers;
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
try {
try {
// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
// Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
}
}
DispatcherServlet作為中介者協調具體http請求物件,Controller物件,檢視View物件之間的互動。
總結
優點
- 將多個同事之間的互動封裝到中介者物件中,同事物件之間低耦合。
- 多對多的關係變成了一對多,中介者集中控制同事之間的互動,當互動需要變化時,直接修改中介者。
缺點
- 過度集中化,中介者物件可能會變得非常複雜。
本質
中介者模式的本質是封裝互動。只要是實現封裝物件之間的互動功能,就可以應用中介者模式,標準的中介者模式限制很多,只要本質不變,就可以看做中介者模式。
使用場景
- 如果一組物件之間的互動關係比較複雜,相互依賴,結構混亂,這種情況下可以採用中介者模式。
參考
大戰設計模式【21】—— 中介者模式
設計模式的征途—22.中介者(Mediator)模式
中介者模式(詳解版)
設計模式(十九)——中介者模式(智慧家庭案例)
Mediator Pattern
研磨設計模式-書籍