1. 程式人生 > 其它 >資料結構與演算法_15 _ 二分查詢(上):如何用最省記憶體的方式實現快速查詢功能

資料結構與演算法_15 _ 二分查詢(上):如何用最省記憶體的方式實現快速查詢功能

前言

我們現實生活中存在很多複雜的 網狀結構 的互動關係,例如每個人必須記錄他(她)所有朋友的手機號,如果其中有人的手機號修改了,就必須通知他(她)所有的朋友一起修改,牽一髮而動全身,非常複雜,如果將這種 網狀結構 變成 星狀結構,將大大降低它們之間的耦合度,新增一箇中介者,在網上建立一個每個朋友都可以訪問的通訊錄,如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物件之間的互動。

總結

優點

  1. 將多個同事之間的互動封裝到中介者物件中,同事物件之間低耦合。
  2. 多對多的關係變成了一對多,中介者集中控制同事之間的互動,當互動需要變化時,直接修改中介者。

缺點

  1. 過度集中化,中介者物件可能會變得非常複雜。

本質

中介者模式的本質是封裝互動。只要是實現封裝物件之間的互動功能,就可以應用中介者模式,標準的中介者模式限制很多,只要本質不變,就可以看做中介者模式。

使用場景

  1. 如果一組物件之間的互動關係比較複雜,相互依賴,結構混亂,這種情況下可以採用中介者模式。

參考

大戰設計模式【21】—— 中介者模式
設計模式的征途—22.中介者(Mediator)模式
中介者模式(詳解版)
設計模式(十九)——中介者模式(智慧家庭案例)
Mediator Pattern
研磨設計模式-書籍