委派模式
? 精簡程序邏輯,便于閱讀
? 其基本作用是負(fù)責(zé)任務(wù)的調(diào)度和分配任務(wù),和代理模式很像,可以看做是一種特殊情況下的靜態(tài)代理的全權(quán)代理,但是代理模式注重過程,但是委派模式注重結(jié)果。
? 是一種行為型模式。
? 一般Delegate,Dispatcher結(jié)尾的都是委派
不屬于GOF23種設(shè)計(jì)模式
通用類圖

Delegate 委派角色
負(fù)載在各個(gè)具體角色實(shí)例之間做出決策,并且判斷和調(diào)用具體的方法
Deletgate委派類,委派類收到任務(wù)后,交給對應(yīng)的集體干活的人事干活
public class Delegate implements Task{
public void doTask() {
System.out.println("代理執(zhí)行開始....");
Task task = null;
if (new Random().nextBoolean()){
task = new ConcreteA();
task.doTask();
}else{
task = new ConcreteB();
task.doTask();
}
System.out.println("代理執(zhí)行完畢....");
}
}
案例
老板叫員工干活
? 老板叫經(jīng)理干活,經(jīng)理通過不同的內(nèi)容叫不同的員工去做事情

首先定義接口,把干活的內(nèi)容抽象出來
public interface IEmployee {
public void doing(String command);
}
接下來定義員工a和員工B
public class EmployeeA implements IEmployee {
@Override
System.out.println("我是員工A,我現(xiàn)在開始干" + command + "工作");
}
}
public class EmployeeB implements IEmployee {
@Override
public void doing(String command) {
System.out.println("我是員工B,我現(xiàn)在開始干" + command + "工作");
}
}
經(jīng)理記錄員工
public class Leader implements IEmployee {
private Map<String,IEmployee> targets = new HashMap<String,IEmployee>();
public Leader() {
targets.put("加密",new EmployeeA());
targets.put("登錄",new EmployeeB());
}
//項(xiàng)目經(jīng)理自己不干活
public void doing(String command){
targets.get(command).doing(command);
}
}
老板叫經(jīng)理干活
public class Boss {
public void command(String command,Leader leader){
leader.doing(command);
}
}
測試
public class DelegateTest {
public static void main(String[] args) {
//客戶請求(Boss)、委派者(Leader)、被被委派者(Target)
//委派者要持有被委派者的引用
//代理模式注重的是過程, 委派模式注重的是結(jié)果
//策略模式注重是可擴(kuò)展(外部擴(kuò)展),委派模式注重內(nèi)部的靈活和復(fù)用
//委派的核心:就是分發(fā)、調(diào)度、派遣
//委派模式:就是靜態(tài)代理和策略模式一種特殊的組合
new Boss().command("登錄",new Leader());
}
}
這種方式能夠避免我們使用if或者switch去判斷
可以看到老板其實(shí)并不需要關(guān)心干活的是誰,只需要找領(lǐng)導(dǎo)就行了,這個(gè)是符合最少知道原則的
在源碼中的應(yīng)用
Spring Web MVC
org.springframework.web.servlet.DispatcherServlet#doDispatch
不同的請求交給不同的請求處理器mappedHandler去處理
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
//勝率了很多源代碼
// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
}
JDK-雙親委派
? 一個(gè)類加載器在加載類時(shí),先把這個(gè)請求委派給自己的父類加載器去執(zhí)行,如果父類加載器還存在父類加載器, 就繼續(xù)向上委派,直到頂層的啟動(dòng)類加載器。如果父類加載器能夠完成類加加載,就成功返回,如果父類加載器無法完成加載,那么子加載器オ會(huì)嘗試試自己去加載。
? 從定義中可以看到雙親加載模型一個(gè)類加載器加載類時(shí),首先不是自己加載,而是委派給父加載器。
? 下面我們來看看 ClassLoader#loadClass
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
Class<?> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
long t1 = System.nanoTime();
c = findClass(name);
// this is the defining class loader; record the stats
sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
sun.misc.PerfCounter.getFindClasses().increment();
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
先看父類有沒有,有的話就父來loadClass
反射-Method
public Object invoke(Object obj, Object... args)
throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
MethodAccessor ma = methodAccessor; // read volatile
if (ma == null) {
ma = acquireMethodAccessor();
}
return ma.invoke(obj, args);
}
可以看到全權(quán)交給了MethodAccessor來調(diào)用
sun.reflect.NativeMethodAccessorImpl#invoke
public Object invoke(Object var1, Object[] var2) throws IllegalArgumentException, InvocationTargetException {
if (++this.numInvocations > ReflectionFactory.inflationThreshold() && !ReflectUtil.isVMAnonymousClass(this.method.getDeclaringClass())) {
MethodAccessorImpl var3 = (MethodAccessorImpl)(new MethodAccessorGenerator()).generateMethod(this.method.getDeclaringClass(), this.method.getName(), this.method.getParameterTypes(), this.method.getReturnType(), this.method.getExceptionTypes(), this.method.getModifiers());
this.parent.setDelegate(var3);
}
return invoke0(this.method, var1, var2);
}
metho沒干啥,委派給了別人來做,這樣我們不用關(guān)心底層是怎么用的
有點(diǎn)類似于門面模式,但是委派是行為型模式,門面是結(jié)構(gòu)型模式
Spring中的BeanDefinition
解析xml中的Bean標(biāo)簽也使用了委派模式
org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#parseBeanDefinitions
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);
}
else {
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
Element的話就交給BeanDefinitionParserDelegate來處理了
靜態(tài)代理會(huì)在前后增加一些邏輯,委派模式就是全權(quán)交給別人來處理
總結(jié)
優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
-
通過任務(wù)委派能夠?qū)⒁粋€(gè)
大型的任務(wù)細(xì)化,- 通過統(tǒng)一管理這些子任務(wù)的完成情況實(shí)現(xiàn)任務(wù)的跟進(jìn)
能夠加快任務(wù)執(zhí)行的效率。
缺點(diǎn)
- 任務(wù)委派方式需要根據(jù)任務(wù)的復(fù)雜程度進(jìn)行不同的改變
- 在任務(wù)比較復(fù)雜的情況下可能需要進(jìn)行多重委派
- 容易造成紊亂
和代理的區(qū)別
委派是行為型模式
代理是結(jié)構(gòu)型模式
- 委派注重任務(wù)派遣
- 注重結(jié)果
- 代理注重增強(qiáng)
- 注重過程
- 委派是特殊的靜態(tài)代理,相當(dāng)于全權(quán)代理
我的筆記倉庫地址gitee 快來給我點(diǎn)個(gè)Star吧