1.委派模式簡(jiǎn)介
在常用的23種設(shè)計(jì)模式中其實(shí)面沒有委派模式(delegate)的影子,但是在Spring中委派模式確實(shí)用的比較多的一種模式谁榜。
在spring中的體現(xiàn):Spring MVC框架中的DispatcherServlet其實(shí)就用到了委派模式。
委派模式的作用: 基本作用就是負(fù)責(zé)任務(wù)的調(diào)用和分配任務(wù)牺荠,跟代理模式很像卫玖,可以看做是一種特殊情況下的靜態(tài)代理的全權(quán)代理,但是代理模式注重過程原朝,而委派模式注重結(jié)果
2.委派模式的實(shí)例
先引用一張圖來介紹委派模式驯嘱,下圖主要說明了 boss把任務(wù)給leader,而leader做了一個(gè)任務(wù)的分配和調(diào)度的工作,自己沒有做工作喳坠,而是把具體工作交給具體的執(zhí)行者去做鞠评。
下面直接給出實(shí)例:
執(zhí)行的接口
/**
* @Project: spring
* @description: 執(zhí)行的接口
* @author: sunkang
* @create: 2018-08-30 23:10
* @ModificationHistory who when What
**/
public interface IExcuter {
void excute(String command);
}
普通員工A
/**
* @Project: spring
* @description: 員工A執(zhí)行某項(xiàng)命令
* @author: sunkang
* @create: 2018-08-30 23:10
* @ModificationHistory who when What
**/
public class ExcuterA implements IExcuter{
@Override
public void excute(String command) {
System.out.println("員工A 開始做"+command+"的工作");
}
}
普通員工B
/**
* @Project: spring
* @description: 員工B執(zhí)行某項(xiàng)命令
* @author: sunkang
* @create: 2018-08-30 23:10
* @ModificationHistory who when What
**/
public class ExcuterB implements IExcuter{
@Override
public void excute(String command) {
System.out.println("員工B 開始做"+command+"的工作");
}
}
leader委派者
/**
* @Project: spring
* @description: leader 委派者 任務(wù)分發(fā)的作用
* @author: sunkang
* @create: 2018-08-30 23:11
* @ModificationHistory who when What
**/
public class Leader implements IExcuter {
private Map<String,IExcuter> targets = new HashMap<String,IExcuter>();
public Leader() {
targets.put("加密",new ExcuterA());
targets.put("登錄",new ExcuterB());
}
@Override
public void excute(String command) {
targets.get(command).excute(command);
}
}
boss類模擬調(diào)用測(cè)試
/**
* @Project: spring
* @description: boss 模擬客戶執(zhí)行任務(wù)
* @author: sunkang
* @create: 2018-08-30 23:13
* @ModificationHistory who when What
**/
public class Boss
{
public static void main(String[] args) {
Leader leader = new Leader();
//看上去好像是我們的項(xiàng)目經(jīng)理在干活
//但實(shí)際干活的人是普通員工
//這就是典型,干活是我的壕鹉,功勞是你的
leader.excute("登錄");
leader.excute("加密");
}
}
測(cè)試結(jié)果為:
3.委派模式的實(shí)現(xiàn)mvc的簡(jiǎn)單實(shí)例
思考:
在springmvc訪問地址的url
與Controller層配置的url
是如何映射的
Controller層配置的url
如何跟具體的方法
映射的谢澈,參數(shù)
又是如何綁定
的
猜測(cè):
url的地址可以根據(jù)request得到訪問url地址煌贴,配置的url地址可以根據(jù)配置注解得到,這兩者的url匹配上了說明映射成功了锥忿,除了url是不夠的牛郑,還需要一個(gè)中間對(duì)象保存了url和method以及controller對(duì)象的信息,可以把這個(gè)中年的映射對(duì)象放入容器中敬鬓,然后根據(jù)傳入的url從容器取出進(jìn)行匹配淹朋,取出來之后就可以根據(jù)映射來完成方法的調(diào)用了。
下面就簡(jiǎn)單實(shí)現(xiàn)一個(gè)mvc調(diào)用的例子
模擬controller層
/**
* @Project: spring
* @description: 模擬controller層
* @author: sunkang
* @create: 2018-09-03 22:20
* @ModificationHistory who when What
**/
public class MemberAction {
public void getMemberById(String mid){
}
}
模擬serlvert得到的請(qǐng)求如何轉(zhuǎn)發(fā),交給具體的controller處理的
/**
* @Project: spring
* @description: selvelt的任務(wù)分發(fā)者 钉答,主要完成url的映射和調(diào)用
* @author: sunkang
* @create: 2018-09-03 22:21
* @ModificationHistory who when What
**/
public class SelvletDispatcher {
//這里也可以用map 對(duì)象來保存Hanlder對(duì)象
private List<Handler> handlerMapping = new ArrayList<Handler>();
public SelvletDispatcher() {
//簡(jiǎn)單實(shí)現(xiàn)一個(gè)controller的映射
try {
Class clazz = MemberAction.class;
handlerMapping.add(new Handler()
.setController(clazz.newInstance())
.setMethod(clazz.getMethod("getMemberById",new Class[]{String.class}))
.setUrl("/web/getMemberById.json")
);
} catch (Exception e) {
e.printStackTrace();
}
}
private void doService(HttpServletRequest request, HttpServletResponse response){
doDispatch(request,response);
}
/**
* 請(qǐng)求的分發(fā)工作
* @param request
* @param response
*/
private void doDispatch(HttpServletRequest request, HttpServletResponse response) {
//1.獲取用戶請(qǐng)求的url
String uri = request.getRequestURI();
Handler handler =null;
////2础芍、根據(jù)uri 去handlerMapping找到對(duì)應(yīng)的hanler
for(Handler h :handlerMapping){
if(uri.equals(h.getUrl())){
handler = h;
break;
}
}
//3.將具體的任務(wù)分發(fā)給Method(通過反射去調(diào)用其對(duì)應(yīng)的方法)
Object obj = null;
try {
obj = handler.getMethod().invoke(handler.getController(),request.getParameter("mid"));
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
//4、獲取到Method執(zhí)行的結(jié)果数尿,通過Response返回出去
// response.getWriter().write();
}
/**
* 具體的hanlder對(duì)象
*/
class Handler{
//controller對(duì)象
private Object controller;
//controller對(duì)象映射的方法
private String url;
//ulr對(duì)應(yīng)的方法
private Method method;
public Object getController() {
return controller;
}
public Handler setController(Object controller) {
this.controller = controller;
return this;
}
public String getUrl() {
return url;
}
public Handler setUrl(String url) {
this.url = url;
return this;
}
public Method getMethod() {
return method;
}
public Handler setMethod(Method method) {
this.method = method;
return this;
}
}
}